/** * @file ivec_mcal_spi.c * @author Akshat Dabas (akshat@vecmocon.com) * @brief This source file contains API and Private members for SPI Functionality * @version 0.1.0 * @date 2024-Mar-12 * * @copyright Copyright (c) 2024 * */ #include "../Core/Include/ivec_mcal_spi.h" /*REQUIRED SPI CONFIGS*/ /*=======================================================================================PRIVATE_MEMBERS======================================================================================*/ static volatile uint8_t b_SPI0_INIT_FLAG=0; static volatile uint8_t b_SPI1_INIT_FLAG=0; static volatile int i32bufferIdx0=0; static volatile int i32bufferIdx1=0; static volatile uint8_t u8rxbuffer0[SPI_PKT_SIZE], u8rxbuffer1[SPI_PKT_SIZE]; static const DL_SPI_Config gSPI_0_config = { .mode = DL_SPI_MODE_CONTROLLER, .frameFormat = DL_SPI_FRAME_FORMAT_MOTO3_POL1_PHA1, .parity = DL_SPI_PARITY_NONE, .dataSize = DL_SPI_DATA_SIZE_8, .bitOrder = DL_SPI_BIT_ORDER_MSB_FIRST, }; static const DL_SPI_ClockConfig gSPI_0_clockConfig = { .clockSel = DL_SPI_CLOCK_BUSCLK, .divideRatio = DL_SPI_CLOCK_DIVIDE_RATIO_1 }; /*____________________________________________________________________________________________________________________________________________________________________________________________*/ /*============================================================================================================================================================================================= PRIVATE_DECLARATIONS ==============================================================================================================================================================================================*/ /** * @brief Receive in static buffer Function for UART * * @param uart_inst * @return uint8_t */ uint8_t _prv_u8MCAL_spi_receive(SPI_Regs *SPI_inst) { uint8_t temp; temp=DL_SPI_receiveData8(SPI_inst); return temp; } /** * @brief Function to read byte by byte in IRQ Handler * */ void _prv_vspicallback() { switch (DL_SPI_getPendingInterrupt(SPI0)) { case DL_SPI_IIDX_RX: if(i32bufferIdx0>SPI_PKT_SIZE-1) { i32bufferIdx0=0; } u8rxbuffer0[i32bufferIdx0]=_prv_u8MCAL_spi_receive(SPI0); i32bufferIdx0++; break; case DL_SPI_IIDX_RX_TIMEOUT: __asm("nop"); break; case DL_SPI_IIDX_RX_FULL: __asm("nop"); break; case DL_SPI_IIDX_TX_UNDERFLOW: __asm("nop"); break; case DL_SPI_IIDX_PARITY_ERROR: __asm("nop"); break; case DL_SPI_IIDX_RX_OVERFLOW: __asm("nop"); break; default: break; } switch (DL_SPI_getPendingInterrupt(SPI1)) { case DL_SPI_IIDX_RX: if(i32bufferIdx1>SPI_PKT_SIZE-1) { i32bufferIdx1=0; } u8rxbuffer1[i32bufferIdx1]=_prv_u8MCAL_spi_receive(SPI1); i32bufferIdx1++; break; case DL_SPI_IIDX_RX_TIMEOUT: __asm("nop"); break; case DL_SPI_IIDX_RX_FULL: __asm("nop"); break; case DL_SPI_IIDX_TX_UNDERFLOW: __asm("nop"); break; case DL_SPI_IIDX_PARITY_ERROR: __asm("nop"); break; case DL_SPI_IIDX_RX_OVERFLOW: __asm("nop"); break; default: break; } } /** * @brief Default Interrupt Callback for SPI_0 * */ void SPI0_IRQHandler(void) { _prv_vspicallback(); } void SPI1_IRQHandler(void) { _prv_vspicallback(); } /*============================================================================================================================================================================================= API ==============================================================================================================================================================================================*/ /** * @brief Initialize SPI in Controller/Master Mode * * @param SPI_inst Pointer to SPI config registers * @param BR enum to set SPI Bit Rate * @return xCoreStatus_t */ xCoreStatus_t xMCAL_SPI_init(SPI_Regs *SPI_inst, xSPI_CS_t xCS ) { assert(SPI_inst == SPI0 || SPI_inst == SPI1); assert(!(b_SPI0_INIT_FLAG == 1 && b_SPI1_INIT_FLAG == 1)); if(xCS!=0) { return STATUS_INIT_FAIL; } DL_SPI_setClockConfig(SPI_inst, (DL_SPI_ClockConfig *) &gSPI_0_clockConfig); DL_SPI_init(SPI_inst, (DL_SPI_Config *) &gSPI_0_config); /* Configure Controller mode */ if(xCS==0) { /* * Set the bit rate clock divider to generate the serial output clock * outputBitRate = (spiInputClock) / ((1 + SCR) * 2) * 1000000 = (40000000)/((1 + 19) * 2) */ DL_SPI_setBitRateSerialClockDivider(SPI_inst, 19); } //DL_SPI_enableLoopbackMode(SPI_inst); /* Set RX and TX FIFO threshold levels */ //DL_SPI_setFIFOThreshold(SPI_inst, DL_SPI_RX_FIFO_LEVEL_1_2_FULL, DL_SPI_TX_FIFO_LEVEL_1_2_EMPTY); DL_SPI_setFIFOThreshold(SPI_inst, DL_SPI_RX_FIFO_LEVEL_ONE_FRAME, DL_SPI_TX_FIFO_LEVEL_EMPTY); /*Enable Interrupt*/ DL_SPI_enableInterrupt(SPI_inst, (DL_SPI_INTERRUPT_PARITY_ERROR | DL_SPI_INTERRUPT_RX | DL_SPI_INTERRUPT_RX_FULL | DL_SPI_INTERRUPT_RX_OVERFLOW | DL_SPI_INTERRUPT_RX_TIMEOUT | DL_SPI_INTERRUPT_TX_UNDERFLOW)); /* Enable module */ DL_SPI_enable(SPI_inst); if(SPI_inst==SPI0) { NVIC_EnableIRQ(SPI0_INT_IRQn); b_SPI0_INIT_FLAG=1; } else if(SPI_inst==SPI1) { NVIC_EnableIRQ(SPI1_INT_IRQn); b_SPI1_INIT_FLAG=1; } return STATUS_SUCCESS; } /** * @brief Function to Receive SPI Message * * @param SPI_inst Pointer to SPI config registers * @param u8SPI_RxData variable where received data will be stored * @param size Number of bytes to read * @return xCoreStatus_t */ xCoreStatus_t _prv_xSPI_getData(SPI_Regs *SPI_inst, uint8_t *u8SPI_RxData, uint8_t size ) { assert(SPI_inst == SPI0 || SPI_inst == SPI1); assert(b_SPI0_INIT_FLAG != 0 || b_SPI1_INIT_FLAG != 0); if(SPI_inst==SPI0) { for(uint8_t i=0;i