2024-11-20 03:42 PM - edited 2024-11-20 03:43 PM
I am using a Nucleo-H743ZI as a SPI slave device for the following coms method:
Master Pulls SS low, Delay 1ms.
Master Transmit/Receive 1 Byte (Wait for high busy line)
Slave RXP Interrupt-> Lower Busy Line
Slave Transmit/Receive 1 Byte
Slave Process Byte, Set next transmit byte
Slave Raise Busy Line
Master Transmit/Receive 1 Byte
Repeat untilldata is done
Master Raises SS
The Master is acting properly and the slave receive is correct; however, the slave transmit is two bytes behind. For now I have hard coded the transmit to send 5. All the data is received correctly by the slave in this time but the slave does not transmit 5 until the third byte is received.
SLAVE SETUP:
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 0x0;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi1.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi1.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
//MY INIT:
HAL_GPIO_WritePin(nFPINT_GPIO_Port, nFPINT_Pin, GPIO_PIN_SET); //raise /busy line
__HAL_SPI_DISABLE(&hspi1);
hspi1.Instance->UDRDR = 0xA5;
__HAL_SPI_CLEAR_OVRFLAG(&hspi1);
__HAL_SPI_CLEAR_EOTFLAG(&hspi1);
__HAL_SPI_CLEAR_FREFLAG(&hspi1);
__HAL_SPI_DISABLE_IT(&hspi1, SPI_IT_TXP);
__HAL_SPI_ENABLE_IT(&hspi1, SPI_IT_RXP);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
// /CS handler
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == GPIO_PIN_14) {
if(HAL_GPIO_ReadPin(nCS_GPIO_Port, nCS_Pin) == GPIO_PIN_RESET){
__HAL_SPI_DISABLE(&hspi1);
__HAL_SPI_ENABLE(&hspi1);
txBuffer = 0; //transmit 0 for first byte
}
}
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
}
void spiISRSTM(SPI_HandleTypeDef *hspi) {
HAL_GPIO_WritePin(nFPINT_GPIO_Port, nFPINT_Pin, GPIO_PIN_RESET); //Lower /Busy
if (hspi->Instance->SR & SPI_FLAG_TXP) {
(*(__IO uint8_t *)&hspi->Instance->TXDR) = 5; // transmit
}
//Receive if ready
if (hspi->Instance->SR & SPI_FLAG_RXP) {
rxBuffer = (*(__IO uint8_t *)&hspi->Instance->RXDR);
ProcessSPI(); //Process SPI data
}
__HAL_SPI_CLEAR_UDRFLAG(hspi);
__HAL_SPI_CLEAR_OVRFLAG(hspi);
__HAL_SPI_CLEAR_EOTFLAG(hspi);
__HAL_SPI_CLEAR_FREFLAG(hspi);
}
2024-11-21 03:01 AM
Hello @EthanMankins
To ensure efficient SPI transmit/receive, you should fill the TX FIFO before enabling TXP and RXP interrupts. Here is a code snippet to guide you:
// Initialization code
void SPI_Init(void) {
// Other initialization code..
// Fill the TX FIFO before enabling interrupts
while (__HAL_SPI_GET_FLAG(&hspi, SPI_FLAG_TXP)) {
// Fill the TX FIFO with data
*((__IO uint8_t *)&hspi.Instance->TXDR) = *pTxData++;
}
// Enable the TXP interrupt
__HAL_SPI_ENABLE_IT(&hspi, SPI_IT_TXP);
// Enable the RXP interrupt
__HAL_SPI_ENABLE_IT(&hspi, SPI_IT_RXP);
// Enable the SPI
__HAL_SPI_ENABLE(&hspi);
}
// Interrupt Service Routine (ISR)
void SPI_IRQHandler(void) {
// Check the TXP flag
if (__HAL_SPI_GET_FLAG(&hspi, SPI_FLAG_TXP)) {
// Transmit data
*((__IO uint8_t *)&hspi.Instance->TXDR) = *pTxData++;
}
// Check the RXP flag
if (__HAL_SPI_GET_FLAG(&hspi, SPI_FLAG_RXP)) {
// Receive data
*pRxData++ = *((__IO uint8_t *)&hspi.Instance->RXDR);
}
// Other ISR code...
}
2024-11-21 09:36 AM
Hi @Saket_Om ,
I just gave this a shot, and starting with pTxData = 0, it transmits 16, 17, 18... Based on the definition of a FIFO I would have expected it to transmit 0, 1, 2, 3... Why would it start with the last in 16 instead of first in 0?
2024-11-21 02:58 PM
@Saket_Om I have found that filling the buffer does not effect the operation. The same issue persists
2024-11-22 12:34 AM - edited 2024-11-22 12:34 AM
Hello @EthanMankins
Could you please share the complete code for both the master and slave devices, including the main function, so that we can assist you more efficiently?
Could you please check with the HAL API to see if it works fine for your application? If it does, you can use it as inspiration to customize your SPI functions.
2024-11-22 09:03 AM
SLAVE:
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 0x0;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi1.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi1.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
HAL_GPIO_WritePin(nFPINT_GPIO_Port, nFPINT_Pin, GPIO_PIN_SET);
__HAL_SPI_DISABLE(&hspi1);
hspi1.Instance->UDRDR = 0xA5;
__HAL_SPI_CLEAR_OVRFLAG(&hspi1);
__HAL_SPI_CLEAR_EOTFLAG(&hspi1);
__HAL_SPI_CLEAR_FREFLAG(&hspi1);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
// /CS handler
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == GPIO_PIN_14) {
if(HAL_GPIO_ReadPin(nCS_GPIO_Port, nCS_Pin) == GPIO_PIN_RESET){
HAL_GPIO_WritePin(nFPINT_GPIO_Port, nFPINT_Pin, GPIO_PIN_RESET);
txBuffer = 2;
*((__IO uint8_t *)&hspi1.Instance->TXDR) = txBuffer;
__HAL_SPI_ENABLE(&hspi1);
__HAL_SPI_ENABLE_IT(&hspi1, SPI_IT_RXP);
HAL_GPIO_WritePin(nFPINT_GPIO_Port, nFPINT_Pin, GPIO_PIN_SET);
}
if(HAL_GPIO_ReadPin(nCS_GPIO_Port, nCS_Pin) == GPIO_PIN_SET){
__HAL_SPI_DISABLE_IT(&hspi1, SPI_IT_RXP);
__HAL_SPI_DISABLE(&hspi1);
hspi1.Instance->UDRDR = 0xA5;
__HAL_SPI_CLEAR_OVRFLAG(&hspi1);
__HAL_SPI_CLEAR_EOTFLAG(&hspi1);
__HAL_SPI_CLEAR_FREFLAG(&hspi1);
}
}
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
}
void spiISRSTM(SPI_HandleTypeDef *hspi) {
//Receive if ready
if (hspi->Instance->SR & SPI_FLAG_RXP) {
HAL_GPIO_WritePin(nFPINT_GPIO_Port, nFPINT_Pin, GPIO_PIN_RESET); //Lower nFPINT
rxBuffer = (*(__IO uint8_t *)&hspi->Instance->RXDR);
(*(__IO uint8_t *)&hspi->Instance->TXDR) = 1;
HAL_GPIO_WritePin(nFPINT_GPIO_Port, nFPINT_Pin, GPIO_PIN_SET);
}
__HAL_SPI_CLEAR_UDRFLAG(hspi);
__HAL_SPI_CLEAR_OVRFLAG(hspi);
__HAL_SPI_CLEAR_EOTFLAG(hspi);
__HAL_SPI_CLEAR_FREFLAG(hspi);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART3_UART_Init();
MX_USB_OTG_FS_PCD_Init();
MX_USART2_UART_Init();
MX_SPI1_Init();
MX_TIM2_Init();
HAL_GPIO_WritePin(nFPINT_GPIO_Port, nFPINT_Pin, GPIO_PIN_SET);
__HAL_SPI_DISABLE(&hspi1);
hspi1.Instance->UDRDR = 0xA5;
__HAL_SPI_CLEAR_OVRFLAG(&hspi1);
__HAL_SPI_CLEAR_EOTFLAG(&hspi1);
__HAL_SPI_CLEAR_FREFLAG(&hspi1);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
while (1)
{
}
}
MASTER:
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 0x0;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */
__HAL_SPI_ENABLE(&hspi2);
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_RESET); // Pull CS low
HAL_Delay(1);
while(nOutputByte != -1)
{
int nReceiveByte = STM_SPI_Xmit(&hspi2, nOutputByte);
nOutputByte = SpiISR_Packet(NULL, (DWORD)this, nReceiveByte); //delay untilnFPINT line is high
}
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_SET); // Pull CS high
volatile uint8_t rxBuffer;
volatile uint8_t txBuffer;
volatile uint8_t byteRd = 0;
volatile uint8_t byteXd = 0;
int STM_SPI_Xmit(SPI_HandleTypeDef *hspi, int nOutputByte){
txBuffer = (uint8_t) nOutputByte;
__HAL_SPI_ENABLE(hspi);
__HAL_SPI_ENABLE_IT(hspi, SPI_IT_TXP); // Enable TXP untill byte is sent
while(!byteXd){}
byteXd = 0; // Clear byte is sent flag
while (!byteRd){} // Poll while no byte is Received
byteRd = 0;
return (int) rxBuffer;
}
void spiISRSTM(SPI_HandleTypeDef *hspi) {
if (hspi->Instance->SR & SPI_FLAG_TXP) {
SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART); // start SPI master
(*(__IO uint8_t *)&hspi->Instance->TXDR) = txBuffer; // transmit
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXP); // disable TXP
while(!__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXC)){}
// printf("|%u ", (uint8_t)txBuffer);
byteXd = 1;
}
//Receive if ready
if (hspi->Instance->SR & SPI_FLAG_RXP) {
rxBuffer = (*(__IO uint8_t *)&hspi->Instance->RXDR);
// printf("%u|", (uint8_t)rxBuffer);
byteRd = 1;
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXP);
}
__HAL_SPI_DISABLE(hspi);
__HAL_SPI_CLEAR_UDRFLAG(hspi);
__HAL_SPI_CLEAR_OVRFLAG(hspi);
__HAL_SPI_CLEAR_EOTFLAG(hspi);
__HAL_SPI_CLEAR_FREFLAG(hspi);
}
2024-11-22 09:05 AM
I have tire the HALAPI however, I could not get it to work with transferring one byte at a time and was told it would likely not work with HALAPI.