STM32 Freertos提供ISR的二进制信号
我已经使用STM32CubeMX生成了STM32F103的RTOS-CMSIS_V1项目,并定义了四个任务如下:
osThreadDef(defaultTask, StartDefaultTask, osPriorityLow, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* definition and creation of normal */
osThreadDef(normal, StartTask02, osPriorityNormal, 0, 128);
normalHandle = osThreadCreate(osThread(normal), NULL);
/* definition and creation of high */
osThreadDef(high, StartTask03, osPriorityAboveNormal, 0, 128);
highHandle = osThreadCreate(osThread(high), NULL);
/* definition and creation of low */
osThreadDef(low, StartTask04, osPriorityBelowNormal, 0, 128);
lowHandle = osThreadCreate(osThread(low), NULL);
一个二进制信号:
osSemaphoreDef(binsem);
binsemHandle = osSemaphoreCreate(osSemaphore(binsem), 1);
和一个计时器,该计时器每1秒生成中断。 任务功能和中断服务例程:
void StartTask02(void const * argument)
{
for (;;) {
sprintf(buffer, "normal waiting for semaphore\r\n");
printout();
if (xSemaphoreTake(binsemHandle, portMAX_DELAY)) {
sprintf(buffer, "normal begin\r\n");
printout();
sprintf(buffer, "normal end\r\n");
printout();
}
osDelay(1000);
}
}
void StartTask03(void const * argument)
{
for (;;) {
sprintf(buffer, "high begin\r\n");
printout();
sprintf(buffer, "high end\r\n");
printout();
osDelay(1000);
}
}
void StartTask04(void const * argument)
{
for (;;) {
sprintf(buffer, "low begin\r\n");
printout();
sprintf(buffer, "low end\r\n\r\n");
printout();
osDelay(1000);
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM1) {
static BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(binsemHandle, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
if (htim->Instance == TIM4) {
HAL_IncTick();
}
}
问题是当我运行代码时,中断只执行一次,而没有任何任务正在运行。如果我评论XsemaphoregiveFromisr(binsemhandle,null);
所有任务(由于信号量检查的正常,除非正常,并且每秒都会被激活。 tim4
用作时间基础,tim1
中断的默认优先级为14
。 基于 this 解决方案我检查了config> configKernel_inter_inter_interrupt_priority
,并且已定义为15&lt&lt&lt&lt&lt&lt ;< 4
。 并且也基于 this 解决方案,code> configmax_syscall_inter_interrupt_priority
设置为5&lt&lt ;< 4
。但是,将tim1
中断为15、240、255等的优先级也无济于事。
在任务之间给出和占用信号是没有问题的。
另外,我使用xsemaphoregivefromisr
在tim1_irq_handler()
函数中进行了测试,而不是回调,但没有运气。使用XTASKNOTIFYGIVE
而不是信号量也无法使用。
编辑,
因此我将计时器中断优先级设置为7,并使用configassert()
进行检查,并且没有错误。打印寄存器的值还提供了值112,即7<< 4
。
/* Initialize interrupts */
//MX_NVIC_Init();
/* USER CODE BEGIN 2 */
NVIC_SetPriority(TIM1_IRQn, 7);
NVIC_EnableIRQ(TIM1_IRQn);
sprintf(buffer, "%u\r\n", NVIC->IP[TIM1_IRQn]);
printout();
configASSERT(NVIC->IP[TIM1_IRQn] == 112);
这是freertosconfig.h
内核和最大优先级值的文件定义:
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
并且根据此页面和下图
计时器应该能够从ISR调用Freertos API函数。
在ISR回调函数中,评论XsemaphoregiveFromisr()
时,所有任务和中断工作。但是不进行评估会导致崩溃,这意味着不允许通过ISR调用Freertos API函数的计时器中断。
我在这里想念什么?
I've generated a RTOS-cmsis_v1 project for stm32f103 using stm32cubemx and defined four tasks as below:
osThreadDef(defaultTask, StartDefaultTask, osPriorityLow, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* definition and creation of normal */
osThreadDef(normal, StartTask02, osPriorityNormal, 0, 128);
normalHandle = osThreadCreate(osThread(normal), NULL);
/* definition and creation of high */
osThreadDef(high, StartTask03, osPriorityAboveNormal, 0, 128);
highHandle = osThreadCreate(osThread(high), NULL);
/* definition and creation of low */
osThreadDef(low, StartTask04, osPriorityBelowNormal, 0, 128);
lowHandle = osThreadCreate(osThread(low), NULL);
a binary semaphore:
osSemaphoreDef(binsem);
binsemHandle = osSemaphoreCreate(osSemaphore(binsem), 1);
and a timer which generates an interrupt every 1 second.
Task functions and interrupt service routine:
void StartTask02(void const * argument)
{
for (;;) {
sprintf(buffer, "normal waiting for semaphore\r\n");
printout();
if (xSemaphoreTake(binsemHandle, portMAX_DELAY)) {
sprintf(buffer, "normal begin\r\n");
printout();
sprintf(buffer, "normal end\r\n");
printout();
}
osDelay(1000);
}
}
void StartTask03(void const * argument)
{
for (;;) {
sprintf(buffer, "high begin\r\n");
printout();
sprintf(buffer, "high end\r\n");
printout();
osDelay(1000);
}
}
void StartTask04(void const * argument)
{
for (;;) {
sprintf(buffer, "low begin\r\n");
printout();
sprintf(buffer, "low end\r\n\r\n");
printout();
osDelay(1000);
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM1) {
static BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(binsemHandle, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
if (htim->Instance == TIM4) {
HAL_IncTick();
}
}
The problem is when I run the code, the interrupt executes only once and none of the task are running. If I comment out the xSemaphoreGiveFromISR(binsemHandle, NULL);
all tasks (except normal, because of the semaphore check) run and also interrupt gets activated every second.TIM4
is used as time base and the default priority of TIM1
interrupt was 14
.
Based on this solution I checked the value of configKERNEL_INTERRUPT_PRIORITY
and it's defined as 15 << 4
.
And also based on this solution, the value of configMAX_SYSCALL_INTERRUPT_PRIORITY
is set to 5 << 4
. But changing the priority level of TIM1
interrupt to 15, 240, 255, and etc didn't help either.
Giving and taking semaphores between tasks has no problem.
Also I tested using xSemaphoreGiveFromISR
in TIM1_IRQ_Handler()
function instead of the callback, but no luck. Using xTaskNotifyGive
instead of semaphore didn't work either.
Edit
So I set my timer interrupt priority to 7 and checked it using configASSERT()
and no errors. Printing the value of the register also gives the value 112 which is 7<<4
.
/* Initialize interrupts */
//MX_NVIC_Init();
/* USER CODE BEGIN 2 */
NVIC_SetPriority(TIM1_IRQn, 7);
NVIC_EnableIRQ(TIM1_IRQn);
sprintf(buffer, "%u\r\n", NVIC->IP[TIM1_IRQn]);
printout();
configASSERT(NVIC->IP[TIM1_IRQn] == 112);
and here are FreeRTOSconfig.h
file definitions for kernel and max priority values:
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
and according to this page, and the diagram below
the timer should be able to call freertos API functions from ISR.
When commenting out the xSemaphoreGiveFromISR()
in the ISR callback function, all tasks and the interrupt work. But un-commenting it results in a crash, which means the timer interrupt is not allowed to call freertos API functions fro ISR.
WHAT AM I MISSING HERE??
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好的!因此,问题在于,在启动
main.c
文件之前,我可以启用计时器中断:因此,移动
hal_tim_base_start_it(&amp; amp; htim1)之后;
函数freertos.c
并将其放置在信号量定义之后,一切正常(甚至从ISR)。我遇到了一些文档,在弗雷托斯文档中提到了这一点,但我没有对此表示关注,现在找不到它在哪里。如果找到文档,我将在此处添加一个链接。
OK! So the problem was that I was enabling the timer interrupt BEFORE starting the scheduler in the
main.c
file:So after moving the
HAL_TIM_Base_Start_IT(&htim1);
function tofreertos.c
and putting it AFTER the semaphore definition, everything works fine (even printing from ISR).I came across some document mentioning this in freeRTOS documentation but I didn't pay attentions to it and now I can't find where it was. I'll add a link to it here if I found the document.
这也是获取任务通知工作的方法。
调用
hal_tim_base_start_it()
OSKERNELSTART()
之后。This is also the way to get task notifications to work.
Call
HAL_TIM_Base_Start_IT()
AFTERosKernelStart()
.