/* ******************************************************************************* * void SpiClrFifoCounter( SPI_MemMapPtr base) ******************************************************************************* * Input : base : Pointer to SPI0/ SPI1 /SPI2 Register Base * Output : void * Description : Clear RX and TX FIFO counters for respective SPI module ******************************************************************************* */ void SpiClrFifoCounter( SPI_MemMapPtr base) { //-->Clear RX and TX FIFO counters SPI_MCR_REG(base) |=(SPI_CLR_TXFIFO<<SPI_MCR_CLR_TXF_SHIFT); SPI_MCR_REG(base) |=(SPI_CLR_RXFIFO<<SPI_MCR_CLR_RXF_SHIFT); }// End of SpiClrFifoCounter
/* ******************************************************************************* * void SpiDisable( SPI_MemMapPtr base ); ******************************************************************************* * Input : base : Pointer to SPI0/ SPI1 /SPI2 Register Base * Output : void * Description : Disable respective SPI module ******************************************************************************* */ void SpiDisable( SPI_MemMapPtr base) { //-->Disable SPI SPI_MCR_REG(base) |=SPI_DISABLE; SPI_MCR_REG(base) &= (~SPI_MCR_MDIS_MASK); }// End of SpiDisable
/* ******************************************************************************* * void SpiSetMode( SPI_MemMapPtr base, uint8_t mode) ******************************************************************************* * Input : base : Pointer to SPI0/ SPI1 /SPI2 Register Base * mode : 1=> Master * 0=> Slave * Output : void * Description : Enable Master or Slave mode for respective SPI module ******************************************************************************* */ void SpiSetMode( SPI_MemMapPtr base , uint8_t mode) { if(SPI_MASTER_MODE == mode) { //-->SPI in Master mode SPI_MCR_REG(base) |= (SPI_MASTER_MODE <<SPI_MCR_MSTR_SHIFT ); } else { //-->SPI in Slave mode SPI_MCR_REG(base) |= (SPI_SLAVE_MODE <<SPI_MCR_MSTR_SHIFT ); } }// End of SpiSetMode
/* ******************************************************************************* * void SpiSetTxFifo( SPI_MemMapPtr base, uint8_t tx_fifo_enable) ******************************************************************************* * Input : base : Pointer to SPI0/ SPI1 /SPI2 Register Base * tx_fifo_enable: 1=> FIFO disabled * 0=> FIFO Enabled * Output : void * Description : Enable or disable Tx Fifo for respective SPI module ******************************************************************************* */ void SpiSetTxFifo( SPI_MemMapPtr base, uint8_t tx_fifo_enable) { if(SPI_DISABLE_RXFIFO == tx_fifo_enable) { //--> Disable Tx FIFO SPI_MCR_REG(base) |=(SPI_DISABLE_TXFIFO <<SPI_MCR_DIS_TXF_SHIFT); } else { //--> Disable Tx FIFO SPI_MCR_REG(base) |=(SPI_ENABLE_TXFIFO <<SPI_MCR_DIS_TXF_SHIFT); } }//End of SpiSetTxFifo
OSStatus spi_deinit( spi_driver_t* spi_driver ) { clear_spi_fifos( spi_driver->spi_peripheral ); /* Halt transfer */ SPI_MCR_REG( spi_driver->spi_peripheral ) |= (uint32_t) ( SPI_MCR_HALT_MASK ); /* Disable module */ SPI_MCR_REG( spi_driver->spi_peripheral ) &= ~(uint32_t) ( SPI_MCR_MDIS_MASK ); /* Disable SPI peripheral clock */ set_spi_peripheral_clock( spi_driver->spi_peripheral, false ); return kNoErr; }
//========================================================================= //函数名称:spi_re //函数参数:spin:SPI通道号。 // data[]:需要接收的数据。 //函数返回:返回接收到字节的长度 //功能概要:SPI接收数据。 //========================================================================= u32 spi_re(SPIn spin,u8 data[]) { u32 n=0; while(SPI_SR_REG(SPIN[spin]) & SPI_SR_RFDF_MASK) //RFDF为1,Rx FIFO is not empty. { data[n++] = (u8)SPI_POPR_REG(SPIN[spin]); //保存接收到的数据 SPI_SR_REG(SPIN[spin]) |= SPI_SR_RFDF_MASK; } /************* 清标志位 ***************/ SPI_SR_REG(SPIN[spin]) = (SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK ); /************** 清FIFO计数器 **************/ SPI_MCR_REG(SPIN[spin]) |= (SPI_MCR_CLR_TXF_MASK //Clear the Tx FIFO counter. |SPI_MCR_CLR_RXF_MASK //Clear the Rx FIFO counter. ); return n; //n为0,则没接收到数据 }
static void spi_status_print(SPI_MemMapPtr p) { #define CTAR_REG_USED (0) printf("MCR %x, TCR %x, CTAR %x, SR %x, RSER %x\r\n", SPI_MCR_REG(p), SPI_TCR_REG(p), SPI_CTAR_REG( p, CTAR_REG_USED ), SPI_SR_REG(p), SPI_RSER_REG(p)); }
//========================================================================= //函数名称:spi_send //函数参数:spin:SPI通道号。 // data[]:需要发送的数据。 // len:数据长度。 //函数返回:无 //功能概要:SPI发送数据。 //========================================================================= void spi_send(SPIn spin,u8 data[],u32 len) { u32 i = 0; u8 temp; SPI_TX_WAIT(spin); do { /************* 清标志位 ***************/ SPI_SR_REG(SPIN[spin]) = (SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK ); /************** 清FIFO计数器 **************/ SPI_MCR_REG(SPIN[spin]) |= (SPI_MCR_CLR_TXF_MASK //Clear TX FIFO.写1清 Tx FIFO counter |SPI_MCR_CLR_RXF_MASK //Clear RX FIFO. 写1清 the Rx FIFO counter. ); //SPI_SR_REG(SPIN[spin]) |= SPI_SR_RFDF_MASK; }while( (SPI_SR_REG(SPIN[spin]) & SPI_SR_RFDF_MASK)); //如果 Rx FIFO 非空,则清FIFO. /***************** 发送len-1个数据 *******************/ ; for(i = 0;i < (len-1);i++) { //DELAY_MS(1); SPI_PUSHR_REG(SPIN[spin]) = 0 | SPI_PUSHR_CONT_MASK //Continuous Peripheral Chip Select Enable,1为 传输期间保持PCSn信号 ,即继续传输数据 | SPI_PUSHR_CTAS(0) | SPI_PUSHR_TXDATA(data[i]); //要传输的数据 while( !(SPI_SR_REG(SPIN[spin]) & SPI_SR_RFDF_MASK)); //RFDF为1,Rx FIFO is not empty. temp = (u8)SPI_POPR_REG(SPIN[spin]); //读取一次接收的数据 SPI_SR_REG(SPIN[spin]) |= SPI_SR_RFDF_MASK; } /***************** 发送最后一个数据 *******************/ SPI_PUSHR_REG(SPIN[spin]) = 0 | SPI_PUSHR_CTAS(0) | SPI_PUSHR_EOQ_MASK //End Of Queue,1为 传输SPI最后的数据 | SPI_PUSHR_TXDATA(data[i]); SPI_EOQF_WAIT(spin); //要及时把RX FIFO的东西清掉,不然这里就无限等待 while( !(SPI_SR_REG(SPIN[spin]) & SPI_SR_RFDF_MASK)); //RFDF为1,Rx FIFO is not empty. temp = (u8)SPI_POPR_REG(SPIN[spin]); //读取一次接收的数据 //SPI_SR_REG(SPIN[spin]) |= SPI_SR_RFDF_MASK; }
/** * @brief SPI接收数据 * * @param spino SPI通道号 * @param data[] 需要发送的数据 * * @return 1 成功 * @return 0 失败 */ uint8_t spi_rcv(uint8_t spino, uint8_t data[]) { SPI_MemMapPtr base_addr = spi_get_base_address(spino); if(SPI_SR_REG(base_addr) & SPI_SR_RFDF_MASK) /* Rx FIFO is not empty */ { data[0] = (uint8_t)SPI_POPR_REG(base_addr); /* Received Data */ SPI_SR_REG(base_addr) |= SPI_SR_RFDF_MASK; /* The RFDF bit can be cleared by writing 1 */ return 1; } SPI_SR_REG(base_addr) = (SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK); SPI_MCR_REG(base_addr) |= SPI_MCR_CLR_TXF_MASK /* Clear the Tx FIFO counter. */ | SPI_MCR_CLR_RXF_MASK; /* Clear the Rx FIFO counter. */ return 0; }
/** * @brief SPI发送数据 * * @param spino SPI通道号 * @param data[] 需要发送的数据 * @param len 需要发送的数据 */ void spi_snd(uint8_t spino, uint8_t data[], uint32_t len) { uint32_t i = 0; SPI_MemMapPtr base_addr = spi_get_base_address(spino); SPI_SR_REG(base_addr) = (SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK); SPI_MCR_REG(base_addr) |= SPI_MCR_CLR_TXF_MASK /* Clear TX FIFO */ | SPI_MCR_CLR_RXF_MASK; /* Clears the RX Counter */ for (i = 0; i < len; i++) { if (i == (len - 1)) { SPI_PUSHR_REG(base_addr) = 0 | SPI_PUSHR_CTAS(0) /* Clock and Transfer Attributes Select */ | SPI_PUSHR_EOQ_MASK /* End Of Queue */ | SPI_PUSHR_TXDATA(data[i]); /* Transmit Data */ } else { SPI_PUSHR_REG(base_addr) = 0 | SPI_PUSHR_CONT_MASK | SPI_PUSHR_CTAS(0) | SPI_PUSHR_TXDATA(data[i]); } } /* 等待数据发送完毕 */ while((SPI_SR_REG(base_addr) & SPI_SR_TCF_MASK)==0); SPI_SR_REG(base_addr) |= SPI_SR_TCF_MASK; }
static void clear_spi_fifos( SPI_MemMapPtr spi_peripheral ) { SPI_MCR_REG( spi_peripheral ) |= (uint32_t)( SPI_MCR_CLR_RXF_MASK | SPI_MCR_CLR_TXF_MASK ); SPI_SR_REG ( spi_peripheral ) |= (uint32_t)( SPI_SR_RFOF_MASK ); }
OSStatus spi_init( spi_driver_t* spi_driver, SPI_MemMapPtr spi_peripheral, uint32_t baud_rate_bps, uint8_t chip_select, bool polarity, bool phase, bool use_dma ) { uint8_t br = get_baud_rate_scaler_register_value( baud_rate_bps ); spi_driver->spi_peripheral = spi_peripheral; spi_driver->baud_rate_bps = baud_rate_bps; spi_driver->chip_select = chip_select; spi_driver->polarity = polarity; spi_driver->phase = phase; spi_driver->use_dma = use_dma; /* Enable SPI peripheral clock */ set_spi_peripheral_clock( spi_peripheral, true ); /* Enable SPI peripheral and clean up (stop) any previous transfer * MDIS = 0 to enable * HALT = 1 to stop transfer * MSTR = 1 for master mode * DCONF = 0 for SPI * PCSIS[x] = 1 for CS active low */ SPI_MCR_REG( spi_peripheral ) &= ~(uint32_t) ( SPI_MCR_MDIS_MASK | SPI_MCR_DCONF(0) ); SPI_MCR_REG( spi_peripheral ) |= (uint32_t) ( (0x1<<24)|SPI_MCR_HALT_MASK | SPI_MCR_MSTR_MASK | SPI_MCR_PCSIS( 1 << chip_select ) ); /* Select Clock and Transfer Attributes Register (CTAR). Always use CTAR0 */ SPI_PUSHR_REG( spi_peripheral ) &= ~(uint32_t) SPI_PUSHR_CTAS(CTAR_REG_USED); /* Reset Clock and Transfer Attributes (CTAR) register */ SPI_CTAR_REG( spi_peripheral, CTAR_REG_USED ) = 0; /* Set SPI configuration * FMSZ = 7. Set frame size to 8-bit. frame size = FMSZ + 1 * CPOL = phase * CPHA = polarity * DBR = 00 * PBR = 2 * BR = calculate based on baud_rate_Mbps * PCSSCK = 0 * PASC = 0 * PDT = 0 * CSSCK = BR - 1 * ASC = BR - 1 * DT = 0 */ SPI_CTAR_REG( spi_peripheral, CTAR_REG_USED ) |= (uint32_t) ( SPI_CTAR_CPOL_MASK & (uint32_t)( polarity << SPI_CTAR_CPOL_SHIFT ) ) | (uint32_t) ( SPI_CTAR_CPHA_MASK & (uint32_t)( phase << SPI_CTAR_CPHA_SHIFT ) ) | (uint32_t) ( SPI_CTAR_FMSZ( 8 - 1 ) ) | (uint32_t) ( SPI_CTAR_DBR_MASK & ( DOUBLE_BAUD_RATE << SPI_CTAR_DBR_SHIFT ) ) | (uint32_t) ( SPI_CTAR_PBR( CTAR_PBR ) ) | (uint32_t) ( SPI_CTAR_BR( br ) ) | (uint32_t) ( SPI_CTAR_CSSCK( br - 1 ) ) | (uint32_t) ( SPI_CTAR_ASC( br - 1 ) ); clear_spi_fifos( spi_peripheral ); /* Enable the start transfer bit */ SPI_MCR_REG( spi_peripheral ) &= ~(uint32_t) ( SPI_MCR_HALT_MASK ); if(use_dma) { SPI_RSER_REG( spi_peripheral ) |= (0x3<<24)|(0x3<<16); DMA_init(); } spi_status_print(spi_peripheral); return kNoErr; }
/* ******************************************************************************* * void SpiEnableReceiver( SPI_MemMapPtr base) ******************************************************************************* * Input : base : Pointer to SPI0/ SPI1 /SPI2 Register Base * Output : void * Description : Enable Receiver for respective SPI module ******************************************************************************* */ void SpiEnableReceiver( SPI_MemMapPtr base) { SPI_MCR_REG(base) |= (SPI_RECV_ENABLE <<SPI_MCR_ROOE_SHIFT ); }//End of SpiEnableREeceiver
/* ******************************************************************************* * void SpiSetPCS( SPI_MemMapPtr base , uint8_t peri_chip_sel) ******************************************************************************* * Input : base : Pointer to SPI0/ SPI1 /SPI2 Register Base * peri_chip_sel: 0=> Low * 1=> High * Output : void * Description : Set Peripheral Chip Select for respective SPI module ******************************************************************************* */ void SpiSetPCS( SPI_MemMapPtr base, uint8_t peri_chip_sel) { //-->Peripheral Chip Select is Inactive Low SPI_MCR_REG(base) |=SPI_MCR_PCSIS(peri_chip_sel); }// End of SpiSetPCS
//========================================================================= //函数名称:spi_init //函数参数:spin:SPI通道号。 // Master:是否是主机。 //函数返回:无 //功能概要:SPI初始化。 //========================================================================= void spi_init(SPIn spin,SPI_CFG master) { //使能SPI模块时钟,配置SPI引脚功能 if(spin == 0) { SIM_SCGC6 |= SIM_SCGC6_DSPI0_MASK; //PORTA_PCR14 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK;//PCS0 //DSE=1:输出时高驱动能力 PORTA_PCR15 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK;//SCK PORTA_PCR16 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK;//SOUT PORTA_PCR17 = 0 | PORT_PCR_MUX(0x2);//SIN } else if(spin == 1) { SIM_SCGC6 |= SIM_SCGC6_SPI1_MASK; PORTE_PCR1 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; //SOUT PORTE_PCR2 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; //SCK PORTE_PCR3 = 0 | PORT_PCR_MUX(0x2); //SIN PORTE_PCR4 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; //PCS0 } else { SIM_SCGC3 |= SIM_SCGC3_SPI2_MASK; PORTD_PCR13 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; //SOUT PORTD_PCR12 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; //SCK PORTD_PCR14 = 0 | PORT_PCR_MUX(0x2)/* | PORT_PCR_DSE_MASK*/; //SIN //PORTD_PCR15 = 0 | PORT_PCR_MUX(0x2)/* | PORT_PCR_DSE_MASK*/; //PCS1 } SPI_MCR_REG(SPIN[spin]) = 0 | SPI_MCR_CLR_TXF_MASK //Clear the Tx FIFO counter. | SPI_MCR_CLR_RXF_MASK //Clear the Rx FIFO counter. //| SPI_MCR_PCSIS_MASK | SPI_MCR_HALT_MASK; //根据主从机模式设置工作模式。MCU提供最大主机频率是1/2主频,最大从机频率是1/4主频 if(master == MASTER) { SPI_MCR_REG(SPIN[spin]) = (0 | SPI_MCR_MSTR_MASK //Master,主机模式 // | SPI_MCR_PCSIS(2) //PCS1 ); SPI_CTAR_REG(SPIN[spin],0) = (0 //| SPI_CTAR_DBR_MASK //双波特率 ,这里设 DBR=1,CPHA=1,PBR=00,得SCK Duty Cycle 为 50/50 //| SPI_CTAR_CPHA_MASK //数据在SCK上升沿改变(输出),在下降沿被捕捉(输入读取)。如果是0,则反之。 w25x16在上升沿读取数据;NRF24L01在上升沿读取数据 | SPI_CTAR_PBR(1) //波特率分频器 ,0~3 对应的分频值Prescaler为 2、3、5、7 | SPI_CTAR_PDT(0x00) //延时因子为 PDT*2+1 ,这里PDT为3,即延时因子为7。PDT为2bit | SPI_CTAR_BR(0) //波特率计数器值 ,当BR<=3,分频Scaler 为 2*(BR+1) ,当BR>=3,分频Scaler 为 2^BR 。BR为4bit //SCK 波特率 = (fSYS/Prescaler) x [(1+DBR)/Scaler ] fSYS 为 Bus clock // 100M 2 1 2 = 50M 这里以最大的来算 // 100M 5 1 2 =20M //| SPI_CTAR_CPOL_MASK //时钟极性,1表示 SCK 不活跃状态为高电平, NRF24L01 不活跃为低电平 | SPI_CTAR_FMSZ(0x07) //每帧传输 7bit+1 ,即8bit (FMSZ默认就是8) // | SPI_CTAR_LSBFE_MASK //1为低位在前。 //| SPI_CTAR_CSSCK(1) // //|SPI_CTAR_PCSSCK(2) //设置片选信号有效到时钟第一个边沿出现的延时的预分频值。tcsc延时预分频 2*x+1; ); //LSBFE 为 0 ,数据在前 } else { //默认从机模式 SPI_CTAR_SLAVE_REG(SPIN[spin],0) = 0 | SPI_CTAR_SLAVE_FMSZ(0x07) | SPI_CTAR_SLAVE_CPOL_MASK | SPI_CTAR_SLAVE_CPHA_MASK; } //DELAY_MS(100); /************* 清标志位 ***************/ SPI_SR_REG(SPIN[spin]) = (SPI_SR_EOQF_MASK //End of Queue Flag,发送队列空了,发送完毕 | SPI_SR_TFUF_MASK //Transmit FIFO Underflow Flag,传输FIFO下溢标志位,SPI为从机模式,Tx FIFO为空,而外部SPI主机模式启动传输,标志位就会置1,写1清0 | SPI_SR_TFFF_MASK //Transmit FIFO Fill Flag,传输FIFO满标志位。 写1或者DMA控制器发现传输FIFO满了就会清0。 0表示Tx FIFO满了 | SPI_SR_RFOF_MASK //Receive FIFO Overflow Flag,接收FIFO溢出标志位。 | SPI_SR_RFDF_MASK); //Receive FIFO Drain Flag,接收FIFO损耗标志位,写1或者DMA控制器发现传输FIFO空了就会清0。0表示Rx FIFO空 SPI_MCR_REG(SPIN[spin]) &= ~SPI_MCR_HALT_MASK; //启动SPI传输。1为暂停,0为启动 DELAY_MS(1); }
/* ******************************************************************************* * void SpiEnable( SPI_MemMapPtr base ) ******************************************************************************* * Input : base : Pointer to SPI0/ SPI1 /SPI2 Register Base * Output : void * Description : Enable The SPI module ******************************************************************************* */ void SpiEnable( SPI_MemMapPtr base ) { SPI_MCR_REG(base) &= SPI_ENABLE; }//End of SpiEnable
/** * @brief SPI初始化 * * @param spino SPI通道号 * @param master 是否是主机 * * @return E_ID 输入序号错误 * @return E_OK 初始化正常 */ ER spi_init(uint8_t spino, uint8_t master) { if((spino < 0) || (spino > SPI_NO_GET(SPI2))) { return (E_ID); } SPI_MemMapPtr base_addr = spi_get_base_address(spino); /* 使能SPI模块时钟,配置SPI引脚功能 */ if(SPI_MOD_SET(spino) == SPI0) { SIM_SCGC6 |= SIM_SCGC6_DSPI0_MASK; /* PORT_PCR_MUX(0x2) : SPI功能 * PORT_PCR_DSE_MASK : Drive Strength Enable */ gpio_init(PORT_NO_GET(SD_CS), PIN_NO_GET(SD_CS), OUT_PUT, HIGH_POWER); /* PCS0 */ PORTA_PCR15 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; /* SCK */ PORTA_PCR16 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; /* SOUT */ PORTA_PCR17 = 0 | PORT_PCR_MUX(0x2); /* SIN */ } else if(SPI_MOD_SET(spino) == SPI1) { SIM_SCGC6 |= SIM_SCGC6_SPI1_MASK; PORTE_PCR4 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; /* PCS0 */ PORTE_PCR2 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; /* SCK */ PORTE_PCR1 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; /* SOUT */ PORTE_PCR3 = 0 | PORT_PCR_MUX(0x2); /* SIN */ } else { SIM_SCGC3 |= SIM_SCGC3_SPI2_MASK; } SPI_MCR_REG(base_addr) = 0 | SPI_MCR_CLR_TXF_MASK /* Clear the Tx FIFO counter. */ | SPI_MCR_CLR_RXF_MASK /* Clear the Rx FIFO counter. */ | SPI_MCR_HALT_MASK; /* Starts and stops DSPI transfers */ /* 根据主从机模式设置工作模式 */ if(master == MASTER) { SPI_MCR_REG(base_addr) |= SPI_MCR_MSTR_MASK; /* Master/Slave Mode Select */ SPI_CTAR_REG(base_addr,0) = 0 | SPI_CTAR_DBR_MASK /* Double Baud Rate */ | SPI_CTAR_FMSZ(0x07) /* Frame Size: 8bit */ | SPI_CTAR_PDT_MASK /* 延时因子为7 */ | SPI_CTAR_BR(0x8); /* Selects the scaler value for the baud rate. */ //| SPI_CTAR_CPOL_MASK; /* Clock Polarity */ //| SPI_CTAR_CPHA_MASK; /* Clock Phase */ } else { SPI_CTAR_SLAVE_REG(base_addr,0) = 0 | SPI_CTAR_SLAVE_FMSZ(0x07) | SPI_CTAR_SLAVE_CPOL_MASK | SPI_CTAR_SLAVE_CPHA_MASK; } SPI_SR_REG(base_addr) = SPI_SR_EOQF_MASK /* End of Queue Flag */ | SPI_SR_TFUF_MASK /* Transmit FIFO Underflow Flag */ | SPI_SR_TFFF_MASK /* Transmit FIFO Fill Flag */ | SPI_SR_RFOF_MASK /* Receive FIFO Overflow Flag */ | SPI_SR_RFDF_MASK; /* Receive FIFO Drain Flag */ SPI_MCR_REG(base_addr) &= ~SPI_MCR_HALT_MASK; /* start */ return (E_OK); }