cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F446 I2S fails to work

CDave.1
Associate II

Hi,

I have setup STM32F446 MCU such that, when pressing the user blue button, it will trigger an external interrupt. Inside the interrupt routine, it contains the I2S receive function:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

int16_t audio_buffer[16000];

HAL_I2S_Receive(&hi2s2, (uint16_t *) audio_buffer, 16000, 100);

}

However, when debugging, as soon as I pressed the blue button the program just ceases to work. In the debugger console, the message displayed was:

Temporary breakpoint 1, main () at ../Src/main.cpp:82

82  HAL_Init();

Program received signal SIGTRAP, Trace/breakpoint trap.

HardFault_Handler () at ../Src/stm32f4xx_it.c:86

86 {

Could anyone please guide me on solving this issue? thank you.

1 ACCEPTED SOLUTION

Accepted Solutions

> It's unlikely that you have this amount of stack space available.

Normal non-RTOS setups place stack at top of SRAM, of which there's plenty in the 'F446, >100kB.

How is I2S set up? CubeF4 has this very "helpful" explanation of the HAL_I2S_Receive() Size parameter:

* @param Size number of data sample to be sent: [sic!]

* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S

* configuration phase, the Size parameter means the number of 16-bit data length

* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected

* the Size parameter means the number of 16-bit data length.

But okay, sources are there and readable, so I know what they meant:

if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
  {
    hi2s->RxXferSize = (Size << 1U);
    hi2s->RxXferCount = (Size << 1U);

in other words, if you've set I2S to 24 or 32 bits, you have to have twice as big buffer - if this was the case here, it may be that writing variables overrun some real stack data (like return address).

I believe I've already ranted here about this particular comment, but I'm not going to look it up, I really couldn't care less about Cube at this point.

JW

View solution in original post

5 REPLIES 5
TDK
Guru

> int16_t audio_buffer[16000];

You're trying to assign 32kB onto the stack. It's unlikely that you have this amount of stack space available. Put this instead into a global buffer.

You're also calling a blocking function from within an interrupt context which is bad form but shouldn't cause a hard fault.

If you feel a post has answered your question, please click "Accept as Solution".

> It's unlikely that you have this amount of stack space available.

Normal non-RTOS setups place stack at top of SRAM, of which there's plenty in the 'F446, >100kB.

How is I2S set up? CubeF4 has this very "helpful" explanation of the HAL_I2S_Receive() Size parameter:

* @param Size number of data sample to be sent: [sic!]

* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S

* configuration phase, the Size parameter means the number of 16-bit data length

* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected

* the Size parameter means the number of 16-bit data length.

But okay, sources are there and readable, so I know what they meant:

if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
  {
    hi2s->RxXferSize = (Size << 1U);
    hi2s->RxXferCount = (Size << 1U);

in other words, if you've set I2S to 24 or 32 bits, you have to have twice as big buffer - if this was the case here, it may be that writing variables overrun some real stack data (like return address).

I believe I've already ranted here about this particular comment, but I'm not going to look it up, I really couldn't care less about Cube at this point.

JW

I have moved the variable so that it is global instead of being local to the interruption function, thanks for pointing that out.

I have changed the blocking function to the DMA variant, is that the right way to do it?

Yes I set I2S to 24 bits, after doubling the buffer size and setting it as a global variable there is no error anymore, although the data collected is inaccurate (that is another issue though). Thanks for the detailed explanation, I should have examined the source code like you did.

If you don't mind me asking, why you don't care about Cube anymore?

I never used Cube so I never really cared. And I guess I'm tired of ST ignoring the garage-scale users generally (and by that I mean the middle management, not the few ST employees whom you see here regularly).

JW