2022-04-19 01:59 AM
Hello,
I am working on SAI part of the NUCLEO-F756ZG board and I observe an issue with the DMA.
The configuration is:
The code is very simple: two buffers, the transmit buffer is filled with a sequence of numbers (0, 1, 2,...), HAL_SAI_Transmit_DMA and HAL_SAI_Receive_DMA are called. When HAL_SAI_RxHalfCpltCallback is reached the receive buffer is displayed.
#define SAI_DMA_BUFFER_SIZE (320 * 8 * 2)
static uint16_t __attribute__((section(".sai_dma_buffer_section"))) __attribute__((aligned(32))) sai_receive_buffer[SAI_DMA_BUFFER_SIZE] = {0};
static uint16_t __attribute__((section(".sai_dma_buffer_section"))) __attribute__((aligned(32))) sai_transmit_buffer[320 * 8] = {0};
static volatile uint32_t audio_data_available = 0;
static volatile uint32_t audio_data_buffer_index = 0;
/**
* @brief Rx Transfer completed callback.
* @param hsai pointer to a SAI_HandleTypeDef structure that contains
* the configuration information for SAI module.
* @retval None
*/
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
{
UNUSED(hsai);
audio_data_buffer_index = 1;
audio_data_available = 1;
HAL_GPIO_TogglePin(AUDIO_READY_GPIO_Port, AUDIO_READY_Pin);
}
/**
* @brief Rx Transfer half completed callback.
* @param hsai pointer to a SAI_HandleTypeDef structure that contains
* the configuration information for SAI module.
* @retval None
*/
void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
{
UNUSED(hsai);
audio_data_buffer_index = 0;
audio_data_available = 1;
HAL_GPIO_TogglePin(AUDIO_READY_GPIO_Port, AUDIO_READY_Pin);
}
/**
* @brief SAI error callback.
* @param hsai pointer to a SAI_HandleTypeDef structure that contains
* the configuration information for SAI module.
* @retval None
*/
void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hsai);
console_printf("error in SAI\n");
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
/* USER CODE BEGIN SysInit */
mpu_configuration();
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART3_UART_Init();
MX_LWIP_Init();
MX_TIM2_Init();
MX_DMA_Init();
MX_SAI1_Init();
/* USER CODE BEGIN 2 */
for (size_t i = 0; i < ARRAY_LENGTH(sai_transmit_buffer); i++) {
sai_transmit_buffer[i] = i;
sai_receive_buffer[i] = 0xFFFF;
}
if (HAL_SAI_Transmit_DMA(&hsai_BlockB1, (uint8_t*)sai_transmit_buffer, 32) != HAL_OK) {
console_printf("HAL_SAI_Transmit_DMA failed %u\n", hsai_BlockB1.ErrorCode);
}
if (HAL_SAI_Receive_DMA(&hsai_BlockA1, (uint8_t*)sai_receive_buffer, 3200) != HAL_OK) {
console_printf("HAL_SAI_Receive_DMA failed\n");
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (audio_data_available) {
break;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
for (size_t i = 0; i < 32; i++) {
console_printf("[%d] = 0x%04x\n", i, sai_receive_buffer[i]);
}
console_printf("end\n");
while(1);
/* USER CODE END 3 */
}
Unfortunatelly in the receive buffer only the first 11 slots are valid (the rest is zero).
Some investigations:
As far as I know the only difference between circular and normal DMA is the first one never stops and overwrites the oldest data. In this example the receive buffer is displayed before DMA loop so the beahvior should be the same as normal mode. Did I missed something ? What point should I verify ?
Best regards,
Thibaut
Solved! Go to Solution.
2022-04-19 02:49 AM
> console_printf("[%d] = 0x%04x\n", i, sai_receive_buffer[i]);
is probably slow enough, so that by the time it prints the 12th datum, the Rx DMA has already rolled over and overwritten the Rx buffer up to that point and beyond.
JW
2022-04-19 02:49 AM
> console_printf("[%d] = 0x%04x\n", i, sai_receive_buffer[i]);
is probably slow enough, so that by the time it prints the 12th datum, the Rx DMA has already rolled over and overwritten the Rx buffer up to that point and beyond.
JW
2022-04-19 05:04 AM
Hello JW,
Thanks for your answer, You're right.
HAL_SAI_RxCpltCallback is called during the print loop.
Best regards,
Thibaut