- #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
- }