because the SysTick ISR has been assigned to the FreeRTOS xPortSysTickHandler() function without regard to HAL operations.

I think this can be corrected by calling HAL_IncTick() before calling xPortSysTickHandler() in SysTick_Handler() similar to as follows:

void SysTick_Handler(void)
{
// for internal HAL function HAL_GetTick() use
HAL_IncTick(); // *must* be called last or a Hard Fault will be generated
xPortSysTickHandler();
}

Note: For some reason, if the xPortSysTickHandler() function is not called last in SysTick_Handler(), a Hard Fault exception will occur!
Also note, it is quite confusing to see multiple instances of SysTick being initialized in these examples:

  1. in HAL_Init()
  2. in SystemClock_Config()
  3. in vTaskStartScheduler()

Also, HAL code initializes and expects the SysTicks generated to be 1 mS ticks,

but the FreeRTOS can easily be configured (via FreeRTOSConfig.hconfigTICK_RATE_HZ)

to be another value, which would cause the HAL-related timeouts to be incorrect.

A hard fault occurs because we execute the xPortSysTickHandler() and the scheduler is not yet started,

to avoid it you can add the following code into the systick interrupt:

void SysTick_Handler(void)
{
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
} HAL_IncTick();
}

Actually in this STM32Cube version we have to configure both HAL and FreeRTOS ticks with Systick interrupt

and with the same frequency (every 1 ms), an update will be done on next releases

The HAL_Delay function is implemented as "weak",

so what I have done is to re-map it to the FreeRTOS task-aware vTaskDelay() function:

void HAL_Delay(volatile uint32_t millis)
{
/* replace HAL library blocking delay function
* with FreeRTOS thread aware equivalent */
vTaskDelay(millis);
}

In addition, I call the HAL_IncTick() function from the FreeRTOS TickHook:

void vApplicationTickHook(void)
{
HAL_IncTick();
}

Hello Lix and all

Thank you for the hunts, but I think I need to be more specific in my problem description.

I am using DMA in order to perform I2C reads/writes using functionnality from stm32f4xx_hal_i2c.c and stm32f4xx_hal_dma.c.

When the DMA transfer completes, it calls " I2C_DMAMasterTransmitCplt"

which itself call " if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, I2C_TIMEOUT_FLAG) != HAL_OK)"

(in fact multiple calls to the same function for different flags).

The "I2C_WaitOnFlagUntilTimeout" relies on the HAL_GetTick.

The problem:
- in the free rtos port, the systick priority is set to lowest priority
- since my code is currently executing the DMA driver code, the systick cannot execute,
so the I2C_WaitOnFlagUntilTimeout hangs in permanent loop if the flag did not reach the expected state.

(please note that STM32CubeMx set the systick priority to the highest priority so the hang does not show up in non RTOS application).

Since HAL_GetTick is declared weak (thanks Lix for mentionning it), I override it with:

uint32_t HAL_GetTick(void)
{
// GY bug with timeout function
uint32_t temp = SCB->ICSR & SCB_ICSR_VECTPENDING_Msk; // )
if (temp == 0x0f000UL)
{
SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;
uwTick++;
}
// GY end bug with timeout function
return uwTick;
}

The timeout is now "kind of" working.

(It would fail if i get event that would have higher priority than systick).

In my opinion, this "solution" is a kludge on top of a combination of design flaws.

In the first place, and in fact the route cause of the problem, a driver is supposed to be short lived.

The driver should never poll waiting on an event.

Instead of polling it should just exit and let an I2c driver wait for the relevant interrupt.

(eventually, driver could "test the water" and do the job if the flag is in the expected state

in order to avoid extra interrupt, but this need to be carefully thought not to fall into time race condition).

Doing so would return the processing to user level code allowing low priority drivers to execute and likely letting RTOS do its job.

Then the FreeRTOS port should not move the systick priority as long as the base STM32F HAL drivers expect it to be the highest priority.

Even if switching systick prirority to highest would solve the "Driver timeout isssue",

it could only be a short term workaround since being stuck in a driver for tens of milliseconds is bad

in standard environment and unacceptable in RTOS environment.

You should note several things:

first and foremost, FreeRTOS sets the SysTick by itself, and if you try to override it is a bad idea (as the ST HAL libraries sometime do).

Normally, the SysTick is set to prio 5 (check the FreeRTOSConfig.h file, the configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY define).

That means that all interrupt handlers that use FreeRTOS APIs (semaphores, mutexes, queues, etc) must have a lower priority than the FreeRTOS scheduler.

Only interrupt handlers that don't use FreeRTOS APIs can have higher priorities than configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY.

Therefore keeping the ST original SysTick priority is not an option, on the contrary,

all initialisations of SysTick out of FreeRTOS should be eliminated

(I found one in the USB Device Library, but maybe there are others too, didn't search for all).

Now to my solutions:

for one, re-mapping HAL_Delay() to vTaskDelay() solves the problem of blocking a function in a timeout.

The FreeRTOS delay doesn't hold the whole processor, only the task that calls it.

On another hand, by letting the FreeRTOS tickHook to increment HALs millisecond variable

you still assure compatibility to possible functions that would directly use HAL_GetTick() function

(as "I2C_WaitOnFlagUntilTimeout" does) but with the mention that it is task aware,

as it is called from inside FreeRTOS.

Moreover, there are no more priority issues, as long as the rule regarding calls from interrupts

to the FreeRTOS APIs is observed (see also the FreeRTOS documentation).

By the way, did you try the solution proposed by me?

I see no reason that it doesn't solve your problem.

You only have to take care not to use this delay in interrupt handlers. But who would insert delays in an interrupt handler anyway?

And yes, you are right that most ST HAL drivers are not (yet) thread aware

(in fact, there is a mention of this in the file stm32f4xx_hal_def.h, check the USE_RTOS define).

So if you really want to do it properly, then you have to modify the drivers using FreeRTOS semaphores and queues

between interrupt handlers and background driver functions.

It's what I did e.g. for the USB CDC Device implementation as well as for UARTs.

The fact that the USE_RTOS was defined at all, may give us a slight hope that ST will sometimes later issue also HAL drivers that are RTOS aware.

Only time will tell...

Hi Lix,

Thanks again for those explanations.

Yes, I did try your solution but it does not work for me.

You mention " Normally, the systick is set to prio 5" but I noticed it is set to 15

(both reading SCB->SHP from debugger and checking source code as described below).

Did you initialize it by yourself to that value, and in that case how are you sure there are no side effect?

I concur with yourself that "all initializations of SysTick out of FreeRTOS should be eliminated" which is why I am reluctant to modify it.

****** explanantion of systick prio set to 15 ****

This is based on free rtos port from ST

From port.c around line 336 in xPortStartScheduler( void )

/* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;

Going through the various defines, we can find that both portNVIC_PENDSV_PRI and portNVIC_SYSTICK_PRI

are based upon configKERNEL_INTERRUPT_PRIORITY, itself based on configLIBRARY_LOWEST_INTERRUPT_PRIORITY

which is set to 15 (effectively the lowest priority / highest priority number)

They are not based on configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY (value of 5)

****** end explanantion of systick prio set to 15 ****

If Systick prio was set to 5 and my driver interrupt set to higher value than 5 (lower prio)

then I think that both your proposed solution and the ST provided HAL driver timeout would work.

Regarding another possibility I did already protect the I2C driver with semaphores and queues to make them RTOS safe for my application.

As you mentionned I also hope we will get RTOS aware HAL drivers

And to your question " But who would insert delays in an interrupt handler anyway?",

one answer is (but may be not the only one) the STM32F4xx_I2C_hal.c handlers provided by ST.

You are right that the SysTick is set to prio 15, and this is true also for the stock FreeRTOS distribution for ARM.

I was confused by the configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY define which is indeed set to 5. But this is another story.

That being said, the truth is that there are many interrupt handlers in the HAL library that are not RTOS compliant,

and unfortunately for this cases there is no other alternative than to write your our own driver.

I jumped on HAL quite recently (about one month ago) and I am still discovering its shortcomings.

I am amazed at how many interrupt handlers do delays in interrupt!

As an example, I wrote my own UART interrupt handler (still based on HAL)

using queues for transmit and receive to communicate between interrupt and background code.

So I would do the same for I2C, as there are indeed calls to HAL_Delay() in the I2C interrupt handler.

Just use a semaphore and transfer most of the processing out of the interrupt handler

(i.e. deferred interrupt handling, see the FreeRTOS user guide).

Thanks for your comments.

I concur with you about the shortcomings of the HAL drivers and the need to rewrite them to be user friendly in general

(no wait for event loops or call for delay, no un-needed interrupt -or rather user configurable based on handle content-

like the half transfer one in DMA) and FreeRTOS aware.

Overall the HAL driver concept is great but the implementation requires significant improvements to make it effective.

I would appreciate if someone from ST would comment on the timefrane for improving the HAL drivers

(i.e., making them RTOS aware) and for the freeRTOS port to take advantage of them.

uint32_t HAL_GetTick( void )
{
if ( SysTick->CTRL & SysTick_CTRL_TICKINT_Msk ) // Interrupt is Enabled
{
if ( SCB->ICSR & SCB_ICSR_PENDSTSET_Msk ) // Interrupt is Blocked
{
SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk; // Clear Pend Bit
uwTick++;
}
}
else if ( SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk ) // Read and Clear COUNTFLAG
uwTick++; // Interrupt is Disabled return uwTick; }

STM32CubeF4 FreeRTOS Examples don't work correctly with HAL_GetTick的更多相关文章

  1. Trimmomatic安装与使用

    默认参数: java -jar trimmomatic-0.30.jar PE s_1_1_sequence.txt.gz s_1_2_sequence.txt.gzlane1_forward_pai ...

  2. TOMCAT-报错The BASEDIR environment variable is not defined correctly

    <span style="font-size:18px;">The BASEDIR environment variable is not defined correc ...

  3. (转载)SQL Reporting Services (Expression Examples)

    https://msdn.microsoft.com/en-us/library/ms157328(v=SQL.100).aspx Expressions are used frequently in ...

  4. 【TOMCAT启动异常】The BASEDIR environment variable is not defined correctly

    <span style="font-size:18px;">The BASEDIR environment variable is not defined correc ...

  5. FreeRTOS如何结束和重新启动调度程序

    大多数主机或桌面系统(比如Linux,Mac或Windows)都有一个正常的用例,你可以在早上启动操作系统,然后在晚上关闭它,然后你就离开机器.嵌入式系统是不同的:他们没有参加,他们应该“永远”运行. ...

  6. nRF52832 SDK15.3.0 基于ble_app_uart demo FreeRTOS移植

    参考资料:https://blog.csdn.net/u010860832/article/details/86235993 这里把移植经验记录下来,供有需要的同学参考,有不对的地方也请大家批评指正. ...

  7. 在Amazon FreeRTOS V10中使用运行时统计信息

    在MCU on Eclipse网站上看到Erich Styger在8月2日发的博文,一篇关于在Amazon FreeRTOS V10中使用运行时统计信息的文章,本人觉得很有启发,特将其翻译过来以备参考 ...

  8. FreeRTOS的内存管理

    FreeRTOS提供了几个内存堆管理方案,有复杂的也有简单的.其中最简单的管理策略也能满足很多应用的要求,比如对安全要求高的应用,这些应用根本不允许动态内存分配的. FreeRTOS也允许你自己实现内 ...

  9. Think you can pronounce these 10 words correctly? You might be

    Think you can pronounce these 10 words correctly?  You might be surprised! Share Tweet Share Tagged ...

随机推荐

  1. 001_fpm打包命令详解

    使用fpm来制作rpm包 2017/2/22 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ...

  2. 009_【OS X和iOS系统学习笔记】 OS X架构

    1.OS X是整个操作系统的集体名称,而Darwin是其中的一个组件. 2.Darwin是操作系统的类UNIX核心,本身由内核.XNU和运行时组成. 3.uname指令:可以得到有关架构的详细信息以及 ...

  3. 几种list排序方法

    package com.lgx.jdk8.part02; import java.util.*; import java.util.stream.Collectors; /** * Comparato ...

  4. 移动端点击300ms延迟

    转载自:http://www.jianshu.com/p/6e2b68a93c88 一.移动端300ms点击延迟 一般情况下,如果没有经过特殊处理,移动端浏览器在派发点击事件的时候,通常会出现300m ...

  5. oracle中循环读出一个表的信息插入到另外一个表中

    declare cursor TAGENTMENUd is select * from TAGENTMENU where 1=1; -- 获取游标begin --遍历查询出的表 (注意 tn是整条记录 ...

  6. Mockito 简明教程

    什么是 Mock 测试 Mock 测试就是在测试过程中,对于某些不容易构造(如 HttpServletRequest 必须在Servlet 容器中才能构造出来)或者不容易获取比较复杂的对象(如 JDB ...

  7. .NetCore WebApi利用Swagger文档实现选择文件上传

    介绍 实现这个功能主要还是依赖过滤器 在Swagger中利用 IOperationFilter 操作来实现文件上传 与之前处理结合Idr4授权一样的处理方式,不同的是授权处理的是Security,而文 ...

  8. .NetCore下B/S结构 初探基于遗传学算法的中学自动排课走班(二)

    分析下染色体基因 这里用 老师 课程 班级 教室 周天 上下晚 课时作为染色体编码我封装了如下类 /// <summary> /// NP 授课事件 由教室.课程.班级 时间片段构成 li ...

  9. rabbitmq 相关

    Exchange 在上一节我们看到生产者将消息投递到Queue中,实际上这在RabbitMQ中这种事情永远都不会发生.实际的情况是,生产者将消息发送到Exchange(交换器,下图中的X),由Exch ...

  10. 【LOJ】#2184. 「SDOI2015」星际战争

    题解 直接二分然后建图跑网络流看看是否合法即可 就是源点向每个激光武器连一条二分到的时间×激光武器每秒攻击值的边 每个激光武器向能攻击的装甲连一条边 每个装甲向汇点连一条装甲值的边 代码 #inclu ...