0

I am trying to retrieve sound from MEMS microphones of my board, STM32F746G-Discovery. I am trying to use BSP Library. My board has wm8994 audio codec, and its schematic is here.

I wrote a code which appears below:

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stm32746g_discovery_audio.h"
#include "wm8994.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define AUDIO_BLOCK_SIZE   ((uint32_t)0xFFFE)
#define AUDIO_NB_BLOCKS    ((uint32_t)4)
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

I2C_HandleTypeDef hi2c3;

SAI_HandleTypeDef hsai_BlockA2;
SAI_HandleTypeDef hsai_BlockB2;
DMA_HandleTypeDef hdma_sai2_b;
DMA_HandleTypeDef hdma_sai2_a;

UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SAI2_Init(void);
static void MX_I2C3_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
void BSP_AUDIO_IN_TransferComplete_CallBack(void);
void BSP_AUDIO_IN_HalfTransfer_CallBack(void);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint32_t  audio_rec_buffer_state;
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
    /* USER CODE BEGIN 1 */
    uint8_t res = 0;
    uint16_t  internal_buffer[AUDIO_BLOCK_SIZE];
    uint32_t bytesread = 0;
    /* 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 */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_SAI2_Init();
    MX_I2C3_Init();
    MX_USART1_UART_Init();
    /* USER CODE BEGIN 2 */
    audio_rec_buffer_state = BUFFER_OFFSET_NONE;
    res = BSP_AUDIO_IN_Init(INPUT_DEVICE_DIGITAL_MICROPHONE_2, 35, AUDIO_FREQUENCY_44K);

    if(!res) {
        res = BSP_AUDIO_IN_Record(internal_buffer, AUDIO_BLOCK_SIZE);
        for (int block_number = 0; block_number < AUDIO_NB_BLOCKS; ++block_number) {
            while(audio_rec_buffer_state != BUFFER_OFFSET_HALF);
            audio_rec_buffer_state = BUFFER_OFFSET_NONE;
            while(audio_rec_buffer_state != BUFFER_OFFSET_FULL);
            audio_rec_buffer_state = BUFFER_OFFSET_NONE;
        }
        BSP_AUDIO_IN_Stop(CODEC_PDWN_SW);
        BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE, 35, AUDIO_FREQUENCY_44K);
        BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
        res = BSP_AUDIO_OUT_Play(internal_buffer, AUDIO_BLOCK_SIZE);
        BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW);
    }
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
}

// Callback Functions
void BSP_AUDIO_IN_TransferComplete_CallBack(void)
{
  audio_rec_buffer_state = BUFFER_OFFSET_FULL;
  return;
}

void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
{
  audio_rec_buffer_state = BUFFER_OFFSET_HALF;
  return;
}

The problem here is that when I perform debugging, the program enters an IRQ function, and cannot exit from there. The function is below:

void DMA2_Stream7_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Stream7_IRQn 0 */

  /* USER CODE END DMA2_Stream7_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_sai2_b);
  /* USER CODE BEGIN DMA2_Stream7_IRQn 1 */

  /* USER CODE END DMA2_Stream7_IRQn 1 */
}
    

What's the problem? I hope everything is clear. I am very new to stm32 so I am very sorry if I forget something. Thank you for your response in advance. Note: I actually wanted to add photos of configuration of SAI peripherals in CubeMX, but I needed to add a lot of links so stackoverflow though my question as spam. I therefore had to remove them.

  • Nowhere in your [posted] code do you initialize `hdma_sai2_b`. That is, during initlialization, I would expect something like (e.g.): `init_dma_handle(&hdma_sai2_b,dma_channel_number);` You call `MX_SAI2_Init`. But, from here: https://github.com/lvgl/lv_port_stm32f746_disco_atollic/blob/master/Core/Src/main.c it's a static function that does (e.g.): `hsai_BlockA2.Instance = SAI2_Block_A;` So, your version has to do a lot of that. So, the struct has bogus values or some other init is needed. I'd dump out the struct and ensure it's valid. You can breakpoint on the isr and single step ... – Craig Estey Jun 19 '22 at 00:15
  • ... to see what it likes or doesn't like. That is, _where_ inside `HAL_DMA_IRQHandler` is it spinning [forever]. There's an awful lot of STM provided/generated code that is a black box (i.e. you have to trust it does the right thing for your configuration). – Craig Estey Jun 19 '22 at 00:20
  • @CraigEstey, I totally agree with you. I confused that the initialization of SAI components. However, when I debug, I saw that everything initialize clearly inside the BSP_AUDIO_IN_Init function. And I also performed debugging on the IRQHandler function, I expected the program to go into an error case, however, it made an assignment to halfXfercpltClbck(or sth like this) property of a variable which derived from a struct, SAI_HandleTypedef. – akoluaciklinux Jun 19 '22 at 12:02
  • Additionally, what can I initialize with a function like init_dma_handle. I looked at the link you sent but I couldn't find the definition of the lv_init, tft_init, touchpad_init, functions. I wanted to look at it to get inspiration. – akoluaciklinux Jun 19 '22 at 12:04
  • It can be one of the two things (and you can check which one specifically): either it hangs inside HAL_DMA_IRQHandler or it keeps calling this interrupt again and again and again. Put a breakpoint at the HAL_DMA_Handler and use debug. See if you keep arriving at that line multiple times or just one. (I suspect interrupt keeps firing indefinitely, but I need a confirmation). – Ilya Jun 20 '22 at 12:59
  • @Ilya, I think the second one because when press "Step Into" in stm32CubeIDE, it reaches the end of the HAL_DMA_IRQHandler. When the function ends, I cannot exit from DMA2_Stream7_IRQHandler function and I Step Into HAL_Dma_IRQHandler again. – akoluaciklinux Jun 20 '22 at 13:53
  • You need to clear the interrupt flag of the DMA2 Stream 7 (most likely) or an interrupt flag at SAI. It keeps entering interrupt because the flag of the event is still set. As a crude test, you could write DMA2->HIFCR = 0xFFFFFFFF; in the interrupt handler. See what happens. It's not a proper solution, but if it works, I will write a proper explanation. – Ilya Jun 20 '22 at 14:26
  • @Ilya I cannot try your suggestion because I cannot find any structure that has a property named HIFCR. – akoluaciklinux Jun 20 '22 at 16:58
  • I have the exact same microcontroller and the same disco board, although I'm not using generated code. Something is missing from your project. Some definitions. It's in the same file where all peripheral definitions are. Sometimes autosuggestions don't show up if you don't include stm32f746xx.h (the file with peripheral structs) into every source file where you want to see them. DMA_TypeDef. I have no problem using it. – Ilya Jun 20 '22 at 19:09
  • Have you solved it? The issue is almost certainly with interrupt flags not being cleared – Ilya Jun 24 '22 at 13:37
  • @IlyaUnfortunately I didn't enable the SAI interrupt in CubeMX, now the program goes into `BSP_AUDIO_IN_TransferComplete_CallBack` and `BSP_AUDIO_IN_HalfTransfer_CallBack` functions. The program now however cannot leave these two functions. It first goes into `BSP_AUDIO_IN_HalfTransfer_CallBack` and then goes into `BSP_AUDIO_IN_TransferComplete_CallBack` and goes like this. I think the issue is that DMA is somehow isn't filled, or DMA is filled but the related interrupt signal isn't sent to CPU.What do you think? – akoluaciklinux Jul 17 '22 at 08:53

0 Answers0