Data forwarding between SPI1 and SPI2
Hi,
device: STM32G031F6
What efficient way could forward RX data of SPI2 to TX of SPI2, and RX of SPI1 to TX of SPI2?
And also, this device itself has a fixed buffer to send over SPI2 TX to another master device.
I think this will require some kind of synchronization between these two SPIs, or adding queue-based functionality to share buffer data between tthe wo SPIs.
SPI2 config: Full Duplex Slave, RX/TX circular DMA configured
SPI1 config: Ful duplex Master, RX/TX circular DMA configured, Baudrate=8MHz.
I configured DMA as a circular buffer because SPI2 missed some random requests from another master device. But with the circular mode, it never missed any data requests.
Below you can see my simple Thread functions start SPI transmissions
void StartSpiSlaveBusTask(void const *argument)
{
SpiSlaveDevice(BufferSlaveTX, BufferSlaveRX, TILES_DATA_BUFFER_SIZE);
for (;;)
{
DELAY_MS(1);
}
osThreadTerminate(spiSlaveBusTaskHandler);
}
void StartSpiMasterBusTask(void const *argument)
{
SpiMasterDevice(BufferMasterTX, BufferMasterRX, TILES_DATA_BUFFER_SIZE);
for (;;)
{
DELAY_MS(1);
}
osThreadTerminate(spiMasterBusTaskHandler);
}Below SPI bus handler functions
// holds a reference to the comms task, so that the interrupt can wake it when an SPI transfer is complete
#ifndef CONFIG_POLLING_SPI_DR_STATE_CHECK
TaskHandle_t slave_task_handle;
TaskHandle_t master_task_handle;
#endif //>!CONFIG_POLLING_SPI_DR_STATE_CHECK
/**
* @brief function handles spi2 bus data flow
*
* @param TxBuffer
* @param RxBuffer
* @param len
* @return TransferState
*/
TransferState SpiSlaveDevice(uint8_t *TxBuffer, uint8_t *RxBuffer, uint16_t len)
{
HAL_StatusTypeDef ret = HAL_ERROR; // default to error, so we can see, if value actually gets updated by HAL
#ifndef CONFIG_POLLING_SPI_DR_STATE_CHECK
// save a reference to this thread, so that the interrupt handler can wake it up
slave_task_handle = xTaskGetCurrentTaskHandle();
#endif //>!CONFIG_POLLING_SPI_DR_STATE_CHECK
ret = HAL_SPI_TransmitReceive_DMA(&hspi2, (uint8_t *)TxBuffer, (uint8_t *)RxBuffer, len);
#ifndef CONFIG_POLLING_SPI_DR_STATE_CHECK
// suspend the thread until SPI transfer is complete
ulTaskNotifyTake(1, portMAX_DELAY);
#endif //>!CONFIG_POLLING_SPI_DR_STATE_CHECK
if (ret != HAL_OK || ret != HAL_BUSY)
{
return TRANSFER_ERR;
}
return TRANSFER_END;
}
/**
* @brief function handles spi1 bus data flow
*
* @param TxBuffer
* @param RxBuffer
* @param len
* @return TransferState
*/
TransferState SpiMasterDevice(uint8_t *TxBuffer, uint8_t *RxBuffer, uint16_t len)
{
HAL_StatusTypeDef ret = HAL_ERROR; // default to error, so we can see, if value actually gets updated by HAL
#ifndef CONFIG_POLLING_SPI_DR_STATE_CHECK
// master a reference to this thread, so that the interrupt handler can wake it up
master_task_handle = xTaskGetCurrentTaskHandle();
#endif //>!CONFIG_POLLING_SPI_DR_STATE_CHECK
ret = HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t *)TxBuffer, (uint8_t *)RxBuffer, len);
#ifndef CONFIG_POLLING_SPI_DR_STATE_CHECK
// suspend the thread until SPI transfer is complete
ulTaskNotifyTake(1, portMAX_DELAY);
#endif //>!CONFIG_POLLING_SPI_DR_STATE_CHECK
if (ret != HAL_OK || ret != HAL_BUSY)
{
return TRANSFER_ERR;
}
return TRANSFER_END;
}
/**
* @brief Callback when the DMA transfer is complete.
* It just calls NotifyGive to wake the comms thread when it returns
*
* @param hspi
*/
#ifndef CONFIG_POLLING_SPI_DR_STATE_CHECK
uint8_t c = 0;
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (hspi->Instance == SPI2)
{
BaseType_t slaveTaskWoken = 0;
vTaskNotifyGiveFromISR(slave_task_handle, &slaveTaskWoken);
portYIELD_FROM_ISR(slaveTaskWoken);
}
else
{
BaseType_t masterTaskWoken = 0;
vTaskNotifyGiveFromISR(master_task_handle, &masterTaskWoken);
portYIELD_FROM_ISR(masterTaskWoken);
}
}
#endif //>!CONFIG_POLLING_SPI_DR_STATE_CHECKI tried adding buffer copying functions into HAL_SPI_TxRxCpltCallback ISR, but copying the data at the right point is probably slow and sometimes it missed starting from the header because the DMA buffer is circular.
the microcontroller has another task also, that's why I need to implement the most efficient way.
Please share any ideas you have, Thanks
