stm32stm32cubemx freertoss system ticker 优先级为什么最低

查看: 50|回复: 0
基于STM32的FREERTOS应用的几个常见问题
1、怎样将 FreeRTOS 移植到不同的Cortex-M 内核?
答:若需将 FreeRTOS 移植到正确的Cortex-M 产品,您必须从正确的目录导入 “port.c”文件。例如,若微控制器是带有IAR 工具的 Cortex-M0 内核,则您必须从“FreeRTOS\Source\portable\IAR\ARM_CM0” 获取 port.c。
2、FreeRTOS 使用需要ROM/RAM?答:这取决于您的编译器、代码架构,以及RTOS 内核配置。一般来说, RTOS 内核本身需要大约 5到 10 K 字节 ROM 空间。如果创建的线程或队列数增加,RAM 使用量就会上升。
3、怎样设置 CPU 时钟?答:CPU 时钟由 FreeRTOSConfig.h 中的 configCPU_CLOCK_HZ 定义,比如在STM32CubeF4固件内它由 SystemCoreClock 提供,表示 HCLK 时钟 (AHB 总线),通过调用SystemClock_Config() 函数配置 RCC 时钟时会设置此值。
<font color="#、怎样设置中断优先级?答:任何使用 RTOS API 函数的中断服务程序,其优先级必须手动设置为大于等于FreeRTOSConfig.h 文件中configMAX_SYSCALL_INTERRUPT_PRIORITY 的设置值。这确保其中断逻辑优先级低于等于configMAX_SYSCALL_INTERRUPT_PRIORITY设置的优先级。
<font color="#、怎样使用非 SysTick 时钟生成时间片中断?答:用户可选择性地自己提供时间片中断源,方法是使用非SysTick 的定时器生成中断:? 提供 vPortSetupTimerInterrupt() 的实现,它会以FreeRTOSConfig.h文件中定义的configTICK_RATE_HZ常量指定的频率产生中断。? 将 xPortSysTickHandler() 配置为定时器中断的处理程序,确保xPortSysTickHandler()在FreeRTOSConfig.h 中未映射至 SysTick_Handler(),或在 port.c 中未被命名为SysTick_Handler()。
<font color="#、怎样启用无时间片空闲模式?答:FreeRTOS 无时间片模式 (低功耗)通过进入睡眠模式并停止周期性的时间片中断来降低MCU 功耗。在 FreeRTOSConfig.h 中,将 configUSE_TICKLESS_IDLE 定义为 1,即可启用此功能。当使用非 SysTick 定时器生成时间片中断时,也可启用无时间片空闲模式。用户必须添加下列动作至上一个问题所述内容:? 在 FreeRTOSConfig.h 中,将 configUSE_TICKLESS_IDLE 设为 2。? 根据 FreeRTOS 相关文档说明,定义portSUPPRESS_TICKS_AND_SLEEP()。
<font color="#、在做基于STM32的FREERTOS应用中出现比较频繁的问题是什么?答:应属STACK溢出和中断优先级相关的问题。
以为内容取自于ST官方的一篇关于具有RTOS的STM32Cube开发应用的用户手册UM1722,该手册较为详细了介绍了如下内容。本文内容只是其中的FAQ部分。
Powered byfreertos移植到STM32L中的问题
[问题点数:40分,结帖人sunmetec]
freertos移植到STM32L中的问题
[问题点数:40分,结帖人sunmetec]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。& & & 最近在使用FreeRTOS的时候,突然发现程序在运行了几分钟之后所有的任务都不再调用了,只有几个中断能正常使用,看来是系统挂掉了,连续测试了几次想找出问题,可是这个真的有点不知所措。
& & &我先看了下文档里的常见错误,发现和我现在有关系的也就堆栈大小的设置和中断嵌套优先级的设置了,不过我这几个任务都是比较简单的,没有太多的变量,那么现在设置的堆栈大小是够的,不然也不会运行一段时间才奔溃,应该一运行就会奔溃的。那么把问题就集中到了中断嵌套优先级里,我尝试了把&configKERNEL_INTERRUPT_PRIORITY = 15/configMAX_SYSCALL_INTERRUPT_PRIORITY = 10结果程序比之前更不如,直接进入了HardFault异常,那么只能看看相关的说明和解释了。
& & 看了下文档里的介绍,configKERNEL_INTERRUPT_PRIORITY 是设置系统心跳时钟的中断优先级,configMAX_SYSCALL_INTERRUPT_PRIORITY是设置中断安全版本FreeRTOS API 可以运行的最高中断优先级。且建立一个全面的中断嵌套模型需要设置 configMAX_SYSCALL_INTERRUPT_PRIRITY
为比configKERNEL_INTERRUPT_PRIORITY 更高的优先级。而基于Cortex-M3中断优先级的特点,优先级是数值越低优先级越高,即0是最高优先级,255是最低优先级。貌似我设置的和这个不冲突啊,没办法去google去,找到了一个解释:
configMAX_SYSCALL_INTERRUPT_PRIORITY needs to be a raw priority value as it is written to the NVIC priority registers in the Cortex-M3 device, as documented in the ARM manuals. The priorities of 0..15 are not real Cortex-M3 priorities, and are simplified priorities for use in some library calls (because the real priorities are so complex on Cortex-M devices).
If you want a simplified priority of 8, then you need to set configMAX_SYSCALL_INTERRUPT_PRIORITY to 0x8n, where n can be any value, but by convention, and for future proofing in case future STM32 parts implement more priority bits, should be set to f. Therefore, the priority you want is 0x8f.
&the code app-faults at "svc 0" in vPortStartFirstTask&
Presumably a hard fault because you are attempting a call to effectively a synchronous interrupt while simultaneously having that interrupt masked out.
& & 看到这里的解释我知道了问题,原来我之前那样的设置是相当于无效的,出问题时肯定的了,优先级设置原来是0xbx,才相当于11的优先级,原来/* equivalent to 0xb0, or priority 11. */这段注释是这个意思,不过一般看到这个注释还真联系不起来,还好找到原因了,下面测试下任务是不是还会挂掉。
& & 下面这个图是一个RTOS中断优先级的说明,如果系统的优先级比configMAX_SYSCALL_INTERRUPT_PRIORITY高,则这些中断可以直接触发,不会被RTOS延时,如果优先级比其低,则有可能被RTOS延时。
阅读(...) 评论()《FreeRTOS On STM32》自己写个linux风格的串口api - 推酷
《FreeRTOS On STM32》自己写个linux风格的串口api
尝试移植uC/OS-II到stm32f103c8小板上一直不成功,还是先用freertos完成想做的东西再说,但是他的api实在是受不了……
那么就自己在stm32的library和freertos的api之上写个linux-posix风格的api吧,等弄完了之后再从freertos的底层优化,也把stm32的库优化。
从linux的usr/include中可以看到很多的标准头文件:unistd.h,termios.h,semaphore.h,pthread.h,fcntl.h。我的目的是提供和linux一样的使用方式,而不是一个完整的posix层,所以暂时先实现用文件io读写串口。
在linux下打开串口的代码为:
//use serial as tty
int tty = open(&/dev/ttyS0&, O_RDWR);
tcgetattr(tty, &opt);
cfsetspeed(&opt, B115200);
opt.c_iflag = 0;
opt.c_oflag = 0;
opt.c_cflag &= ~PARENB; //disable parity bit
opt.c_cflag &= ~CSIZE;
//clear size
opt.c_cflag |= CS8;
//8 bits size.
opt.c_cflag &= ~CSTOPB; //only one stop bit
opt.c_lflag = 0;
opt.c_cc[VMIN]
opt.c_cc[VTIME] = 1;//?
tcsetattr(tty, TCSANOW, &opt);
先从linux的头文件中提取数据结构和文件api
#define NCCS 32
struct termios {
tcflag_t c_
/* input mode flags */
tcflag_t c_
/* output mode flags */
tcflag_t c_
/* control mode flags */
tcflag_t c_
/* local mode flags */
/* line discipline */
cc_t c_cc[NCCS];
/* control characters */
speed_t c_
/* input speed */
speed_t c_
/* output speed */
speed_t cfgetospeed(const struct termios *termios_p);
speed_t cfgetispeed(const struct termios *termios_p);
int cfsetispeed(struct termios* termios_p, speed_t speed);
int cfsetospeed(struct termios* termios_p, speed_t speed);
int cfsetspeed(struct termios* termios_p, speed_t speed);
int tcgetattr(int fd, struct termios* termios_p);
int tcsetattr(int fd, int optional_actions, const struct termios* termios_p);
接下来就是封装stm32库的api了,因为stm32的外设挂到两个总线了APB1、APB2,所以用函数指针来封装这个差异,保证主要代码不考虑这个差别,也可以防止人为的失误:
static int _usart_open(USART_OpenTypeDef* p)
USART_InitTypeDef USART_InitS
GPIO_InitTypeDef GPIO_InitS
NVIC_InitTypeDef NVIC_InitS
/* Create the queues used to hold Rx/Tx characters. */
*(p-&rxq) = xQueueCreate(USART_QUEUE_LENGTH,
(unsigned portBASE_TYPE)sizeof(signed portCHAR));
if(*(p-&rxq) == serINVALID_QUEUE) {
return -1;
*(p-&txq) = xQueueCreate(USART_QUEUE_LENGTH + 1,
(unsigned portBASE_TYPE)sizeof(signed portCHAR));
if (*(p-&txq) == serINVALID_QUEUE) {
return -1;
/* Enable USART clock */
p-&pf_usart_clock(p-&clock_usart, ENABLE);
p-&pf_gpio_clock(p-&clock_gpio, ENABLE);
/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Pin
= p-&gpio_
GPIO_InitStructure.GPIO_Mode
= GPIO_Mode_IN_FLOATING;
GPIO_Init(p-&gpio, &GPIO_InitStructure);
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin
= p-&gpio_
GPIO_InitStructure.GPIO_Speed
= GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode
= GPIO_Mode_AF_PP;
GPIO_Init(p-&gpio, &GPIO_InitStructure);
/* Configure USART behavior */
USART_InitStructure.USART_BaudRate
USART_InitStructure.USART_WordLength
= USART_WordLength_8b;
USART_InitStructure.USART_StopBits
= USART_StopBits_1;
USART_InitStructure.USART_Parity
= USART_Parity_N
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_N
USART_InitStructure.USART_Mode
= USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_Clock
= USART_Clock_D
USART_InitStructure.USART_CPOL
= USART_CPOL_L
USART_InitStructure.USART_CPHA
= USART_CPHA_2E
USART_InitStructure.USART_LastBit
= USART_LastBit_D
USART_Init(p-&usart, &USART_InitStructure);
/* Init _usart_termios struct */
p-&termios_p-&c_ispeed = B9600;
p-&termios_p-&c_ospeed = B9600;
p-&termios_p-&c_cflag
= CS8 | ~CSTOPB | ~PARENB;
/* Enable USART interrupt */
USART_ITConfig(p-&usart, USART_IT_RXNE, ENABLE);
/* Configure USART interrupt setting */
NVIC_InitStructure.NVIC_IRQChannel
NVIC_InitStructure.NVIC_IRQChannelCmd
NVIC_InitStructure.NVIC_IRQChannelSubPriority
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =
configLIBRARY_KERNEL_INTERRUPT_PRIORITY;
NVIC_Init(&NVIC_InitStructure);
/* Enable USART */
USART_Cmd(p-&usart, ENABLE);
再实现设置用的api:
static void _usart_config(USART_InitTypeDef* USART_InitStructure,
const struct termios* termios_p)
/* Configure USART1 behavior */
speed = _macro_to_speed(termios_p-&c_ospeed);
USART_InitStructure-&USART_BaudRate
/* Configure Word Length */
if (termios_p-&c_cflag & CS8) {
USART_InitStructure-&USART_WordLength
= USART_WordLength_8b;
/* Configure Stop bits */
if (termios_p-&c_cflag & CSTOPB) {
USART_InitStructure-&USART_StopBits = USART_StopBits_2;
USART_InitStructure-&USART_StopBits = USART_StopBits_1;
/* Configure parity */
if (!(termios_p-&c_cflag & PARENB)) {
USART_InitStructure-&USART_Parity
= USART_Parity_No;
} else if (termios_p-&c_cflag & PARODD) {
USART_InitStructure-&USART_Parity
= USART_Parity_O
USART_InitStructure-&USART_Parity
= USART_Parity_E
/* Default settings */
USART_InitStructure-&USART_HardwareFlowControl =
USART_HardwareFlowControl_N
USART_InitStructure-&USART_Mode
= USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure-&USART_Clock
= USART_Clock_D
USART_InitStructure-&USART_CPOL
= USART_CPOL_L
USART_InitStructure-&USART_CPHA
= USART_CPHA_2E
USART_InitStructure-&USART_LastBit
= USART_LastBit_D
int tcsetattr(int fd, int optional_actions, const struct termios* termios_p)
USART_TypeDef*
USART_InitTypeDef USART_InitS
/* Backup */
switch(fd) {
case USART1_FILENO:
_usart1_termios = *termios_p;
uart = USART1;
case USART2_FILENO:
_usart2_termios = *termios_p;
uart = USART2;
case USART3_FILENO:
_usart3_termios = *termios_p;
uart = USART3;
return -1;
/* Disable USART1 */
USART_Cmd(uart, DISABLE);
/* Convert termios to STM32 USART Configure */
_usart_config(&USART_InitStructure, termios_p);
USART_Init(uart, &USART_InitStructure);
/* Enable USART1 */
USART_Cmd(uart, ENABLE);
开始封装标准api:
int open(const char* pathname, int flags)
USART_OpenTypeD
if (strcmp(pathname, &/dev/ttyS0&) == 0) {
p.termios_p
= &_usart1_
= &_usart1_tx_
= &_usart1_rx_
= USART1_GPIO_PAD;
= USART1_GPIO_RX;
= USART1_GPIO_TX;
p.pf_usart_clock
= RCC_APB2PeriphClockC
p.clock_usart
= RCC_APB2Periph_USART1;
p.pf_gpio_clock
= RCC_APB2PeriphClockC
p.clock_gpio
= USART1_GPIO_CLK;
p.irq_channel
= USART1_IRQC
_usart_open(&p);
return USART1_FILENO;
if (strcmp(pathname, &/dev/ttyS1&) == 0) {
p.termios_p
= &_usart2_
= &_usart2_tx_
= &_usart2_rx_
= USART2_GPIO_PAD;
= USART2_GPIO_RX;
= USART2_GPIO_TX;
p.pf_usart_clock
= RCC_APB1PeriphClockC
p.clock_usart
= RCC_APB1Periph_USART2;
p.pf_gpio_clock
= RCC_APB2PeriphClockC
p.clock_gpio
= USART2_GPIO_CLK;
p.irq_channel
= USART2_IRQC
_usart_open(&p);
return USART2_FILENO;
if (strcmp(pathname, &/dev/ttyS2&) == 0) {
p.termios_p
= &_usart3_
= &_usart3_tx_
= &_usart3_rx_
= USART3_GPIO_PAD;
= USART3_GPIO_RX;
= USART3_GPIO_TX;
p.pf_usart_clock
= RCC_APB1PeriphClockC
p.clock_usart
= RCC_APB1Periph_USART3;
p.pf_gpio_clock
= RCC_APB2PeriphClockC
p.clock_gpio
= USART3_GPIO_CLK;
p.irq_channel
= USART3_IRQC
_usart_open(&p);
return USART3_FILENO;
return -1;
ssize_t read(int fd, void* buf, size_t count)
int i = 0;
int8_t* p = (int8_t*)
xQueueHandle h = NULL;
switch (fd) {
case USART1_FILENO:
h = _usart1_rx_
case USART2_FILENO:
h = _usart2_rx_
case USART3_FILENO:
h = _usart3_rx_
return -1;
//block untill read first char.
while (!xQueueReceive(h, p, USART_BLOCK_TIME)) {
//receive other chars if need
for (i = 1;i &i++,p++) {
if (!xQueueReceive(h, p, USART_NO_BLOCK)) {
ssize_t write(int fd, const void* buf, size_t count)
int i = 0;
int8_t* p = (int8_t*)
USART_TypeDef*
xQueueHandle h = NULL;
switch (fd) {
case USART1_FILENO:
h = _usart1_tx_
usart = USART1;
case USART2_FILENO:
h = _usart2_tx_
usart = USART2;
case USART3_FILENO:
h = _usart3_tx_
usart = USART3;
return -1;
//send to tx queue
for (i = 0;i &i++,p++) {
if(!xQueueSend(h, p, USART_NO_BLOCK)) {
//enable transmit buffer empty interrupt.
if (i & 0) {
USART_ITConfig(usart, USART_IT_TXE, ENABLE);
目前通过FT232的USB转串口通信正常,yeah。
This work is licensed under a
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致FREERTOS下的按键处理方式讨论 - 生态系统和中间件 - 意法半导体STM32/STM8技术社区
后使用快捷导航没有帐号?
查看: 1783|回复: 16
FREERTOS下的按键处理方式讨论
主题帖子积分
本帖最后由 netlhx 于
21:51 编辑
最近学习FREERTOS,研究了一下按键处理的方式,提出来供讨论。
该方法有如下特色:
1. 基于信号量方式,比查询方式效率更高
2. 可灵活调整按键时长,可实现常规按键、任意时长按键
3. 结合信号量还可实现组合按键。
下面是代码部分,比较简单,就不解释了
osSemaphoreId key0PressedBinSemH
&&/* Create the semaphores(s) */
&&/* definition and creation of key0PressedBinSem */
&&osSemaphoreDef(key0PressedBinSem);
&&key0PressedBinSemHandle = osSemaphoreCreate(osSemaphore(key0PressedBinSem), 1);
/* StartCheckKeyPressedTask function */
void StartCheckKeyPressedTask(void const * argument)
{
&&/* USER CODE BEGIN StartCheckKeyPressedTask */
& & & & //static uint8_t key0Pressed = 0;
& & & & static uint16_t count = 0;
& & & &
&&/* Infinite loop */
&&for(;;)
&&{
& & & & & & & & if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == GPIO_PIN_RESET)
& & & & & & & & {
& & & & & & & & & & & & //key0Pressed = 1;
& & & & & & & & & & & & count ++;
& & & & & & & & & & & &
& & & & & & & & }
& & & & & & & & else
& & & & & & & & {
& & & & & & & & & & & & //key0Pressed = 0;
& & & & & & & & & & & & count = 0;
& & & & & & & & }
& & & & & & & & if(count & 40)
& & & & & & & & {
& & & & & & & & & & & & count = 0;
& & & & & & & & & & & & osSemaphoreRelease(key0PressedBinSemHandle);
& & & & & & & & }
& & osDelay(50);
&&}
&&/* USER CODE END StartCheckKeyPressedTask */
}
/* StartKey0PressedTask function */
void StartKey0PressedTask(void const * argument)
{
&&/* USER CODE BEGIN StartKey0PressedTask */
& & & & osSemaphoreWait(key0PressedBinSemHandle, 0);
&&/* Infinite loop */
&&for(;;)
&&{
& & & & & & & & osSemaphoreWait(key0PressedBinSemHandle, osWaitForever);
& & & & & & & & HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);
& & osDelay(1);
&&}
&&/* USER CODE END StartKey0PressedTask */
}复制代码
注意调整count值的比较量,就可以实现不同按键时长的选择,代码中实现的是2秒的延时。
主题帖子积分
高级会员, 积分 705, 距离下一级还需 295 积分
高级会员, 积分 705, 距离下一级还需 295 积分
过来抢沙发
主题帖子积分
金牌会员, 积分 1121, 距离下一级还需 1879 积分
金牌会员, 积分 1121, 距离下一级还需 1879 积分
不错,先记号一下
主题帖子积分
金牌会员, 积分 1275, 距离下一级还需 1725 积分
金牌会员, 积分 1275, 距离下一级还需 1725 积分
标记下,正要学习这方面的
主题帖子积分
金牌会员, 积分 2122, 距离下一级还需 878 积分
金牌会员, 积分 2122, 距离下一级还需 878 积分
主题帖子积分
论坛元老, 积分 3543, 距离下一级还需 9996456 积分
论坛元老, 积分 3543, 距离下一级还需 9996456 积分
还没开始学习,希望楼主多共享经验
主题帖子积分
金牌会员, 积分 2541, 距离下一级还需 459 积分
金牌会员, 积分 2541, 距离下一级还需 459 积分
如何解决快速按键的缓冲问题呢?
用队列是否更好呢?
主题帖子积分
如何解决快速按键的缓冲问题呢?
用队列是否更好呢?
快速按键用队列应该会好一些
主题帖子积分
论坛元老, 积分 3821, 距离下一级还需 9996178 积分
论坛元老, 积分 3821, 距离下一级还需 9996178 积分
帮顶一下。。。。。。。。
主题帖子积分
用队列是杀鸡用牛刀呀
站长推荐 /1
2016年度 STM32全国巡回研讨会将于日至23日于全国12城市举办,届时将为您呈现STM32最新的产品线和系统解决方案
>>>>报名参加
Tel: 3-8056
备案号: 苏ICP备号-2
Powered by

我要回帖

更多关于 freertos 优先级高低 的文章

 

随机推荐