chg-stn-motherboard-ti-mcu/Core/Source/ivec_mcal_spi.c

318 lines
8.8 KiB
C

/**
* @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
*/
IVEC_CoreStatus_e xMCAL_SPI_init(SPI_Regs *SPI_inst, IVEC_SpiCs_e xCS )
{
assert(SPI_inst == SPI0 || SPI_inst == SPI1);
assert(!(b_SPI0_INIT_FLAG == 1 && b_SPI1_INIT_FLAG == 1));
if(xCS!=0)
{
return IVEC_CORE_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 IVEC_CORE_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
*/
IVEC_CoreStatus_e _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<size;i++)
{
for(uint8_t j=0;j<=i32bufferIdx0;j++)
{
u8SPI_RxData[j]=u8rxbuffer0[j];
}
}
}
if(SPI_inst==SPI1)
{
for(uint8_t i=0;i<size;i++)
{
for(uint8_t j=0;j<=i32bufferIdx1;j++)
{
u8SPI_RxData[j]=u8rxbuffer1[j];
}
}
}
i32bufferIdx0=0;
i32bufferIdx1=0;
return IVEC_CORE_STATUS_SUCCESS;
}
/**
* @brief Function to Transmit SPI Message
*
* @param SPI_inst Pointer to CAN config registers
* @param u8SPI_TxData data to be transmitted
* @param size Number of bytes to transmit
* @return xCoreStatus_t
*/
IVEC_CoreStatus_e xMCAL_SPI_TxData(SPI_Regs *SPI_inst, uint8_t *u8SPI_TxData, 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 (!DL_SPI_isTXFIFOFull(SPI_inst))
{
DL_GPIO_clearPins(GPIOB,DL_GPIO_PIN_20);
for(uint8_t i=0;i<size;i++)
{
DL_SPI_transmitData8(SPI_inst,u8SPI_TxData[i]);
while(DL_SPI_isBusy(SPI_inst));
}
} else
{
return IVEC_CORE_STATUS_ERROR;
}
DL_GPIO_setPins(GPIOB,DL_GPIO_PIN_20);
_prv_xSPI_getData(SPI_inst,u8SPI_RxData, size );
return IVEC_CORE_STATUS_SUCCESS;
}
/**
* @brief
*
* @param SPI_inst Pointer to SPI config registers
* @return xCoreStatus_t
*/
IVEC_CoreStatus_e xMCAL_SPI_deinit(SPI_Regs *SPI_inst)
{
assert(SPI_inst == SPI0 || SPI_inst == SPI1);
assert(b_SPI0_INIT_FLAG != 0 || b_SPI1_INIT_FLAG != 0);
if(SPI_inst==SPI0)
{
NVIC_DisableIRQ(SPI0_INT_IRQn);
DL_SPI_disablePower(SPI_inst);
b_SPI0_INIT_FLAG=0;
}
else if(SPI_inst==SPI1)
{
NVIC_DisableIRQ(SPI1_INT_IRQn);
DL_SPI_disablePower(SPI_inst);
b_SPI1_INIT_FLAG=0;
}
return IVEC_CORE_STATUS_SUCCESS;
}
/*____________________________________________________________________________________________________________________________________________________________________________________________*/