HAL_SAI_Receive() causes hardware timer callback to never exit?
Posted: Thu May 20, 2021 10:37 am
Hi,
i'm trying to sample a microphone inside a hardware timer callback, but the program gets stuck when it runs.
CPU: STM32L452RE
Here is the program:
The output when i run this program is:
More links: https://community.st.com/s/question/0D5 ... n-isr-loop
Thanks!
i'm trying to sample a microphone inside a hardware timer callback, but the program gets stuck when it runs.
CPU: STM32L452RE
Here is the program:
Code: Select all
#include <SoftwareSerial.h>
#include <Arduino.h>
#include <HardwareTimer.h>
#include "stm32l4xx.h"
#include "stm32l4xx_hal.h"
#include "stm32l4xx_hal_def.h"
#include "stm32l4xx_hal_gpio.h"
#include "stm32l4xx_hal_sai.h"
#include "stm32l4xx_hal_exti.h"
#include "stm32l4xx_hal_cortex.h"
#include "Sysclock_Config.h"
void assert_failed(uint8_t* inFileName, uint32_t line) {
char* fileNameAsString = (char*)inFileName;
Serial2.println(F("*** [HAL ASSERT FAILED] ***"));
Serial2.printf("%s\r\n", (char*)inFileName);
Serial2.printf("%i\r\n", line);
}
void _Error_Handler(const char* file, int line) {
Serial2.println(F("*** [ERROR HANDLED] ***"));
Serial2.printf("%s\r\n", file);
Serial2.printf("%i\r\n", line);
}
GPIO_InitTypeDef gpioInit;
SAI_HandleTypeDef saiHandle;
RCC_PeriphCLKInitTypeDef periphInit;
uint8_t SAIDataBuffer[8] = { 0 };
HardwareTimer sampleTimer(TIM3);
void samplerCallback();
// the setup function runs once when you press reset or power the board
void setup() {
delay(5000);
Serial2.begin(115200);
Serial2.println("Starting");
/*
Enable the GPIO B clock.
*/
__HAL_RCC_GPIOB_CLK_ENABLE();
/*
Enable the peripheral clock.
*/
__HAL_RCC_SAI1_CLK_ENABLE();
/*
Configure the GPIO pins.
*/
/**
SAI1_A_Block_A GPIO Configuration
PB15 ------> SAI1_SD_A
PB10 ------> SAI1_SCK_A
PB12 ------> SAI1_FS_A
*/
gpioInit.Pin = GPIO_PIN_15 | GPIO_PIN_10 | GPIO_PIN_12;
gpioInit.Mode = GPIO_MODE_AF_PP;
gpioInit.Pull = GPIO_NOPULL;
gpioInit.Speed = GPIO_SPEED_FREQ_LOW;
gpioInit.Alternate = GPIO_AF13_SAI1;
HAL_GPIO_Init(GPIOB, &gpioInit);
pinMode(PB1, OUTPUT);
digitalWrite(PB1, LOW);
__HAL_SAI_DISABLE(&saiHandle);
// Block type def.
saiHandle.Instance = SAI1_Block_A; // audio block A.
saiHandle.Init.Protocol = SAI_FREE_PROTOCOL;
saiHandle.Init.FirstBit = SAI_FIRSTBIT_MSB;
saiHandle.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_44K;
saiHandle.Init.AudioMode = SAI_MODEMASTER_RX; // block a must provide clock signals and receive from the data line.
saiHandle.Init.Synchro = SAI_ASYNCHRONOUS; // we only want to use this one audio block.
saiHandle.Init.SynchroExt = SAI_SYNCEXT_DISABLE; // disable sychronizing the 2 audio blocks.
saiHandle.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE; // assume to power the data?
saiHandle.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; // any frame length allowed.
saiHandle.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY; // used for interrupts.
saiHandle.Init.MonoStereoMode = SAI_STEREOMODE; // mono mode only available in transmission mode.
saiHandle.Init.CompandingMode = SAI_NOCOMPANDING; // telecommunications specification (not needed)
saiHandle.Init.TriState = SAI_OUTPUT_NOTRELEASED; // assume the SAI is ma
//saiHandle.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
//saiHandle.Init.DataSize = SAI_DATASIZE_32;
// block frame parameters.
saiHandle.FrameInit.FrameLength = 64; // 64 bit frame. (2 slots)
saiHandle.FrameInit.ActiveFrameLength = 32; // Frame synchronization active level length. (half the frame length)
saiHandle.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
saiHandle.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
saiHandle.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
// block slot parameters.
saiHandle.SlotInit.FirstBitOffset = 0; // no offset in receive mode -> FBOFF <= (SLOTSZ - DS)
saiHandle.SlotInit.SlotSize = SAI_SLOTSIZE_32B; // 32 bits per slot to contain the 32 data bits (24 data, 8 zeroed)
saiHandle.SlotInit.SlotNumber = 2;
saiHandle.SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
/*
https://www.keil.com/pack/doc/CMSIS/Driver/html/group__sai__interface__gr.html
*/
HAL_StatusTypeDef saiStatus = HAL_SAI_InitProtocol(&saiHandle,
SAI_I2S_STANDARD, // runs the SAI_InitI2S() function.
SAI_PROTOCOL_DATASIZE_24BIT,// 24 bits (24 bit is standard for I2S).
2); // number of slots per frame - 1
__HAL_SAI_ENABLE(&saiHandle); // without this line of code the first read takes 84us because it settings sai enabled.
if (saiStatus != HAL_OK)
{
Serial2.println("SAI ERROR");
while (1) {}
}
sampleTimer.setMode(1, TIMER_OUTPUT_COMPARE, NC); // remove this for new version of STM32Dino, required version 1.8.0.
sampleTimer.setOverflow(16000, HERTZ_FORMAT);
sampleTimer.detachInterrupt();
sampleTimer.attachInterrupt(samplerCallback);
sampleTimer.resume();
}
long elapsed = 0;
void samplerCallback()
{
long stamp = micros();
HAL_StatusTypeDef rxResponse;
/*
* Perform sampling
*/
rxResponse = HAL_SAI_Receive(&saiHandle, SAIDataBuffer, 2U, 10000);
if (rxResponse != HAL_OK)
{
Serial2.println("Error in SAI");
while (1) { }
}
elapsed = micros() - stamp;
}
void signalWatchdog()
{
// do signal watchdog (placeholder)
}
void loop() {
signalWatchdog();
Serial2.println(elapsed);
}
For some reason it stops printing the elapsed time after a coupe of micros(). I'm not sure why it stops?11:33:44.117 -> 4Starting
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 0
11:34:45.448 -> 4
11:34:45.448 -> 11
11:34:45.448 -> 4
11:34:45.448 -> 5
11:34:45.448 -> 5
11:34:45.448 -> 4
11:34:45.448 -> 4
11:34:45.448 -> 4
11:34:45.448 -> 5
11:34:45.448 -> 10
11:34:45.448 -> 4 <------------ The printing stops here, but the program carries on running
More links: https://community.st.com/s/question/0D5 ... n-isr-loop
Thanks!