cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F767ZI: Hard fault with FreeRTOS mutexes + DMA I2C

PB1
Associate III

My setting is a Nucleo F767ZI board with a IKS01A2 shield. I created a FreeRTOS project that periodically queries the temperature sensor, calculates an average of temperature data, and prints the temperature on the UART. It has three threads that work as follows:

- The first thread performs a HAL_I2C_Mem_Read_DMA to read temperature from the sensor on the shield, stops on a FreeRTOS event (that is fired by the DMA completion callback), then acquires mutex A, puts the temperature data in a shared circular buffer, releases A, and then sleeps (period: 100 ms).

- The second thread acquires mutex A, calculates the average of the temperatures stored in the shared circular buffer, releases A, then acquires mutex B, puts the average in a shared variable, releases B, and then sleeps (period: 500 ms).

- The third thread acquires mutex B, reads the shared variable with the average temperature, releases B, prints on the UART and then sleeps (period: 1000 ms).

The application fails in few seconds with a hard fault. What I learned from some experiments is that the hard fault does not happen if I disable the DMA I2C read code. When this code is enabled, the only way to avoid the hard fault is disallowing the threads to share the mutexes, e,g, by disabling the second thread.

Am I failing something?

Best,

Pietro

1 ACCEPTED SOLUTION

Accepted Solutions

Hello @PB1 

Just tested your project (fortunately I have HTS221 sensor in hands 🙂) and I reproduced the behavior. 

It seems it's a stack size issue of printTask(). I increased it from 128kB to 256kB and the issue disappeared.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

View solution in original post

5 REPLIES 5
Pavel A.
Evangelist III

Am I failing something?

If no one else is working on this code - yes it might be you.

 

Remember DMA has a scope a lot longer than the functions and code calling it, so don't DMA to auto/local buffers on the stack which may collapse immediately.

On CM7 parts pay attention to cache coherency. And 32-byte cache lines.

On the F767 use DTCM RAM for DMA buffers, it's much less complicated as this memory is not cached, being already 0-wait state and bolted to the wrong side of the core.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Pavel A.
Evangelist III

@Tesla DeLorean But isn't this weird? How the DTCM RAM of 'F7 can be zero wait state if DMA burst can grab it at any moment? Is it a terrible hack?

PB1
Associate III

Tried this way:

...
/* USER CODE BEGIN PV */
static uint8_t buf[2] __attribute__((section(".dtcm")));
...
void StartTemperatureTask(void *argument)
{
  ...
  for(;;)
  {
    lastWakeTime += 100;
    osDelayUntil(lastWakeTime);
    hts221_temperature_raw_get_async(&hi2c1, buf);
    ...

but it still generates hard faults.

Hello @PB1 

Just tested your project (fortunately I have HTS221 sensor in hands 🙂) and I reproduced the behavior. 

It seems it's a stack size issue of printTask(). I increased it from 128kB to 256kB and the issue disappeared.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.