2025-11-10 8:11 PM - edited 2025-11-10 8:14 PM
Description:
My RTOS application on NUCLEO-H563ZI board runs a thread CollectSamplesThread. I generate an interrupt every 8Khz using a timer and the ISR triggers a non blocking SPI transfer:
The application code:
void InitAdeSpi()
{
// SPI1 Initialisation
if (hSPI.hdmarx != NULL)
{
HAL_DMA_RegisterCallback(hSPI.hdmarx, HAL_DMA_XFER_CPLT_CB_ID, AdcSpiRxCallback);
}
}
void AdcSpiRxCallback()
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
// Release the sempahore thats blocked to validate the frames in CollectSamplesThread
xSemaphoreGiveFromISR(xSpiRxSemph, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}void TIM3_IRQHandler(void)
{
EvbDataRdyTimerHandler();
}
void EvbDataRdyTimerHandler(void) // Ensure this matches the existing declaration
{
__HAL_TIM_CLEAR_FLAG(&hTimDready, TIM_FLAG_UPDATE);
// Release the sempahore that is blocked in the CollectSamplesThread for Dready callback
xSemaphoreGiveFromISR(xSamplesAvailSemph, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} void CollectSamplesThread(void *pArg)
{
HAL_StatusTypeDef halStatus;
int32_t status = 0;
if (pArg == NULL)
{
while (1)
{
if (xSemaphoreTake(xSamplesAvailSemph, portMAX_DELAY) == pdTRUE)
{
halStatus = HAL_SPI_TransmitReceive_DMA(hSPI, pTxData, pRxData, (uint16_t)numBytes);
if (halStatus != HAL_OK)
{
status = -1;
}
if (status == 0)
{
if (xSemaphoreTake(xSpiRxSemph, portMAX_DELAY) == pdTRUE)
{
//Validate samples
}
}
}
}
}Issue:
Tx DMA ISR is hit, Rx DMA ISR is not hit. SPI1 ISR, SPI1_IRQHandler, is also not hit.
Additional info:
System clock is configured to 250 Mhz.
Before calling HAL_SPI_TransmitReceive_DMA,
At if (halStatus != HAL_OK),
2025-11-10 10:40 PM
While I have no idea on what's wrong with SPI DMA, I can see some other problems with your code.
To minimize jitter you should move all ADC-related actions to timer ISR; you should do fixed-frequency sampling anyway.
With the default SysTick freq of 1 kHz anything requiring higher frequency and implemented in a RTOS thread will only have chance to work if the thread is the only one with the highest priority.
My likely solution would be: control ADC operation in timer ISR, put ADC data to buffer of system queue in RX DMA ISR, process the data from this queue in a thread. No semaphores needed.
2025-11-10 11:28 PM
Have not used H5, but in general hSPI.hdmarx is used internally by HAL.
You could implement
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
or void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) ?
at the global level, overriding the default "do nothing" handlers.
hth
KnarfB
2025-11-11 1:15 AM
Hello @WCarey
It is better to first get your SPI communication working without an RTOS. Once it is functioning correctly, you can then integrate the operating system.
Please check the example below as reference to implement your SPI transfer: