#define ECSPI_FIFO_SIZE 64
//#define DEBUG
#define SPI_RETRY_TIMES 2
#define BURST_L 8
//master device ECSPI1 for test
uint8_t tx_buf_ecspi1[ECSPI_FIFO_SIZE*4];
uint8_t rx_buf_ecspi1[ECSPI_FIFO_SIZE*4];
//slave device ECSPI2 for test
uint8_t tx_buf_ecspi2[ECSPI_FIFO_SIZE*4];
uint8_t rx_buf_ecspi2[ECSPI_FIFO_SIZE*4];
//ECSPI device configuration @HWX
param_ecspi_t param[2] = {{1,1,1,0,0,12,0,0},//sschanel=1,master,ECSPI1,5MHz
{0,0,1,1,1,12,0,0}};//sschanel=1,slave,ECSPI2,non-single burst,5MHz
static void ecspi_start_transfer(unsigned instance, uint16_t brs_bts);
static int ecspi_xfer_slv(unsigned instance, const uint8_t * tx_buf, uint8_t * rx_buf, int bytes);
static int ecspi_xfer_mst(unsigned instance, const uint8_t * tx_buf, uint8_t * rx_buf, int bytes);
/*///////////////////////////////////////////////////////////////////////////////
// Code
///////////////////////////////////////////////////////////////////////////////*/
static void ecspi_start_transfer(unsigned instance, uint16_t brs_bts)
{
// Set burst length
HW_ECSPI_CONREG(instance).B.BURST_LENGTH = brs_bts - 1;
// Clear status
HW_ECSPI_STATREG_WR(instance, BM_ECSPI_STATREG_RO | BM_ECSPI_STATREG_TC);
}
static int ecspi_xfer_slv(unsigned instance, const uint8_t * tx_buf, uint8_t * rx_buf, int bytes)
{
// new added by @HWX
/* Configure ECSPI.CONREG */
/* Configure ECSPI.CONFIGREG */
/* Fill TXFIFO*/
/* Wait for RXFIFO Interrupt(Ready or Data Request or Full) */
/* Read Data from RXFIFO*/
uint32_t val;
uint32_t idx;
val = 0;
// return ERROR_GENERIC;
// }
// Read from Rx FIFO
for (idx = 0; bytes > 0; bytes -= 4, idx += 4)
{
val = HW_ECSPI_RXDATA_RD(instance);
if (rx_buf)
{
switch (bytes)
{
default:
rx_buf[idx + 3] = val >> 24;
// rx_buf[idx + 2] = (val >> 16) & 0xFF;
// rx_buf[idx + 1] = (val >> 8) & 0xFF;
// rx_buf[idx] = val & 0xFF;
break;
case 3:
rx_buf[idx + 2] = (val >> 16) & 0xFF;
// rx_buf[idx + 1] = (val >> 8) & 0xFF;
// rx_buf[idx] = val & 0xFF;
break;
case 2:
rx_buf[idx + 1] = (val >> 8) & 0xFF;
// rx_buf[idx] = val & 0xFF;
break;
case 1:
rx_buf[idx] = val & 0xFF;
break;
}
}
}
//#ifdef DEBUG
// printf("ecspi_xfer_slave: Receive data 0x%x %x %x %x,",rx_buf[0],rx_buf[1],rx_buf[2],rx_buf[3]);
//#endif
// Clear status,write 1 to clear it
// HW_ECSPI_STATREG_WR(instance, BM_ECSPI_STATREG_TC);
return SUCCESS;
}
//! [url=home.php?mod=space&uid=247401]@brief[/url] Perform a SPI master transfer.
//!
//! @param instance ECSPI module instance number starting at 1.
//! @param tx_buf
//! @param rx_buf
//! @param bytes Number of bytes to transfer.
//!
//! [url=home.php?mod=space&uid=2539868]@Todo[/url] Use interrupts to get notification of transfer completion instead of
//! polling the ECSPI STATREG and pausing 500 碌s.
static int ecspi_xfer_mst(unsigned instance, const uint8_t * tx_buf, uint8_t * rx_buf, int bytes)
{
uint32_t val;
uint32_t idx;
//
// // Start burst
// HW_ECSPI_CONREG_SET(instance, BM_ECSPI_CONREG_SMC);
//
// // Write to Tx FIFO
// val = 0;
//
// for (idx = 0; idx < bytes; idx += 4)
// {
// // Only read from the buffer if it is not NULL. If a tx_buf is not provided,
// // then transfer 0 bytes.
// if (tx_buf)
// {
// val = tx_buf[idx] + (tx_buf[idx + 1] << 8) + (tx_buf[idx + 2] << 16) + (tx_buf[idx + 3] << 24);
// }
//
// HW_ECSPI_TXDATA_WR(instance, val);
// }
// // write 1 to start burst immediately
//// HW_ECSPI_CONREG_SET(instance, BM_ECSPI_CONREG_XCH);
// //poll the value of XCH BIT,if XCH = 0, transfer process is over already.
//// while(BG_ECSPI_CONREG_XCH(HW_ECSPI_CONREG_ADDR(instance)) == 0)
//// {
////
//// }
// // Wait for transfer complete
// val = SPI_RETRY_TIMES;
// while (!HW_ECSPI_STATREG(instance).B.TC)
// {
// val--;
// if (val == 0)
// {
////#ifdef DEBUG
//// printf("ecspi_xfer: Transfer timeout.\n");
////#endif
// return ERROR_GENERIC;
// }
//
//// hal_delay_us(500); //delay module not added now @HWX
// }
// if(HW_ECSPI_STATREG(instance).B.RR)
// {
for (idx = 0; bytes > 0; bytes -= 4, idx += 4)
{
val = HW_ECSPI_RXDATA_RD(instance);
if (rx_buf)
{
switch (bytes)
{
default:
rx_buf[idx + 3] = val >> 24;
// rx_buf[idx + 2] = (val >> 16) & 0xFF;
// rx_buf[idx + 1] = (val >> 8) & 0xFF;
// rx_buf[idx] = val & 0xFF;
break;
case 3:
rx_buf[idx + 2] = (val >> 16) & 0xFF;
// rx_buf[idx + 1] = (val >> 8) & 0xFF;
// rx_buf[idx] = val & 0xFF;
break;
case 2:
rx_buf[idx + 1] = (val >> 8) & 0xFF;
// rx_buf[idx] = val & 0xFF;
break;
case 1:
rx_buf[idx] = val & 0xFF;
break;
}
}
}
// }
// Clear status
HW_ECSPI_STATREG_WR(instance, BM_ECSPI_STATREG_TC);
return SUCCESS;
}
int ecspi_configure(dev_ecspi_e instance, const param_ecspi_t * param)
{
// Reset eCSPI controller
HW_ECSPI_CONREG(instance).B.EN = 1;
// Setup chip select
HW_ECSPI_CONREG(instance).B.CHANNEL_SELECT = param->channel;
// Setup mode
uint32_t channelMask = 1 << param->channel;
uint32_t value = HW_ECSPI_CONREG(instance).B.CHANNEL_MODE;
BW_ECSPI_CONREG_CHANNEL_MODE(instance, param->mode ? (value | channelMask) : (value & ~channelMask));
// Setup pre & post clock divider
HW_ECSPI_CONREG(instance).B.PRE_DIVIDER = (param->pre_div == 0) ? 0 : (param->pre_div - 1);
HW_ECSPI_CONREG(instance).B.POST_DIVIDER = param->post_div;
// Enable eCSPI
HW_ECSPI_CONREG(instance).B.EN = 1;
// Setup SCLK_PHA, SCLK_POL, SS_POL
value = HW_ECSPI_CONFIGREG(instance).B.SCLK_PHA;
HW_ECSPI_CONFIGREG(instance).B.SCLK_PHA = param->sclk_pha ? (value | channelMask) : (value & ~channelMask);
value = HW_ECSPI_CONFIGREG(instance).B.SCLK_POL;
HW_ECSPI_CONFIGREG(instance).B.SCLK_POL = param->sclk_pol ? (value | channelMask) : (value & ~channelMask);
value = HW_ECSPI_CONFIGREG(instance).B.SS_POL;
HW_ECSPI_CONFIGREG(instance).B.SS_POL = param->ss_pol ? (value | channelMask) : (value & ~channelMask);
HW_ECSPI_CONFIGREG(instance).B.SS_CTL |= channelMask;
// HW_ECSPI_CONFIGREG(instance).B.SS_CTL = 0x0;
// HW_ECSPI_PERIODREG(instance).B.SAMPLE_PERIOD = 0x10;
//Configure the Rx_threshold
HW_ECSPI_DMAREG(instance).B.RX_THRESHOLD = 0x1; //unit = one word(32 bits)
//Enable RDR interrupt
// HW_ECSPI_INTREG(instance).B.TCEN =0x01;
HW_ECSPI_INTREG(instance).B.RDREN =1;
return SUCCESS;
}
//! @todo Validate [url=home.php?mod=space&uid=18481]@a[/url] dev value for the chip, since not all chips will have all 5 instances.
int ecspi_open(dev_ecspi_e dev, const param_ecspi_t * param)
{
// Configure IO signals
ecspi_iomux_config(dev);
// Ungate the module clock.
clock_gating_config(REGS_ECSPI_BASE(dev), CLOCK_ON);
// Configure eCSPI registers
ecspi_configure(dev, param);
return SUCCESS;
}
int ecspi_close(dev_ecspi_e dev)
{
// Disable controller
HW_ECSPI_CONREG(dev).B.EN = 0;
// Gate the module clock.
clock_gating_config(REGS_ECSPI_BASE(dev), CLOCK_OFF);
return SUCCESS;
}
//! @todo Handle tranfers larger than the FIFO length!
int ecspi_xfer(dev_ecspi_e dev, const uint8_t * tx_buf, uint8_t * rx_buf, uint16_t brs_bts)
{
uint32_t retv = SUCCESS;
// Set bytes for burst
int bytes = brs_bts >> 3;
// Handle non-byte-aligned bits
if ((brs_bts & 0x7) != 0)
{
bytes++;
}
// Check burst length
if (bytes > ECSPI_FIFO_SIZE * 4)
{
#ifdef DEBUG
printf("ecspi_xfer: Burst out of length.\n");
#endif
retv = ERROR_GENERIC;
}
if (retv == SUCCESS)
{
// Prepare transfer
ecspi_start_transfer(dev, brs_bts);
// Initiate transfer
uint32_t channel = HW_ECSPI_CONREG(dev).B.CHANNEL_SELECT;
// Handle different mode transfer
if ((HW_ECSPI_CONREG(dev).B.CHANNEL_MODE & (1 << channel)) == 0)
{
retv = ecspi_xfer_slv(dev, tx_buf, rx_buf, bytes);
}
else
{
retv = ecspi_xfer_mst(dev, tx_buf, rx_buf, bytes);
}
}
return retv;
}
//static void Ecspi1_txIsr(void){
// static int i = 0;
// ecspi_xfer(DEV_ECSPI1, &tx_buf_ecspi1[i], &rx_buf_ecspi1[i], BURST_L);
// if(i < ECSPI_FIFO_SIZE*4)
// {
// i++;
// }
// else{
// i = 0;
// }
//}
static int i = 0;
static void Ecspi2_rxIsr(void){
ecspi_xfer(DEV_ECSPI2, &tx_buf_ecspi2[i], &rx_buf_ecspi2[i], BURST_L);
if(i < (ECSPI_FIFO_SIZE*4-16))
{
i += 1;
}
else{
i = 0;
}
}
//spi module initialize @HWX
void Spi_Init(void){
// ecspi_open(DEV_ECSPI1, ¶m[0]); //Enable ECSPI1
ecspi_open(DEV_ECSPI2, ¶m[1]); //Enable ECSPI2
// bind the ECSPI1 TDR ISR in GIC
// GIC_SpiIntInstall(Ecspi1_txIsr, IAR_INT_eCSPI1, 0x54, 0);
// GIC_IntEnable(IAR_INT_eCSPI1, 1);
// bind the ECSPI2 RDR ISR in GIC
GIC_SpiIntInstall(Ecspi2_rxIsr, IAR_INT_eCSPI2, 0x55, 0);
GIC_IntEnable(IAR_INT_eCSPI2, 1);
//for ecspi1,datas need to be wrote into norflash
}