【问题标题】:Problems configuring duration of FreeRTOS timer tick配置 FreeRTOS 计时器滴答持续时间的问题
【发布时间】:2021-08-17 17:03:46
【问题描述】:

我决定尝试使用带有 Arduino Uno (ATmega 328p) 的 FreeRTOS 并从定时器挂钩闪烁 LED。但是,似乎我在 FreeRTOS 中设置了错误的计时器,并且找不到错误。我认为 LED 会每 1 秒开/关一次(频率为 1 kHz,计数器限制为 1000),但大约是 14 秒。有什么问题?

这是我的 main.c

#include <avr/io.h>
#include "FreeRTOS.h"
#include "task.h"

#define hookTICK_CALLS_BEFORE_POST    ( 1000 )

void vApplicationTickHook( void );

static uint16_t uxCallCounter = 0;
void vApplicationTickHook( void ){
    uxCallCounter++;
    if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST ){
        uxCallCounter = 0;
        PORTD ^= 1 << 2;
    }
}   


int main(void)
{
    DDRD |= 1 << 2;
    /* Replace with your application code */
    vTaskStartScheduler();
    while (1) 
    {
    }
}

这是 FreeRTOSConfig.h

#define configUSE_PREEMPTION        1
#define configUSE_IDLE_HOOK         0
#define configUSE_TICK_HOOK         1
#define configCPU_CLOCK_HZ          ( ( unsigned long ) 8000000 ) /*According to fuses, 0xFF 0xDA 0xFD mean using external oscillator at 16MHz with internal set to 8MHz */
#define configTICK_RATE_HZ          ( (portTickType ) 1000 )
#define configMAX_PRIORITIES        ( 4 )
#define configMINIMAL_STACK_SIZE    ( ( unsigned short ) 85 )
#define configTOTAL_HEAP_SIZE       ( (size_t ) ( 1500 ) )
#define configMAX_TASK_NAME_LEN     ( 8 )
#define configUSE_TRACE_FACILITY    0
#define configUSE_16_BIT_TICKS      1
#define configIDLE_SHOULD_YIELD     0
#define configQUEUE_REGISTRY_SIZE   0

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES       0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet        0
#define INCLUDE_uxTaskPriorityGet       0
#define INCLUDE_vTaskDelete             1
#define INCLUDE_vTaskCleanUpResources   0
#define INCLUDE_vTaskSuspend            0
#define INCLUDE_vTaskDelayUntil         1
#define INCLUDE_vTaskDelay              1

构建选项(Atmel studio 7)

-x c -funsigned-char -funsigned-bitfields -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\include" -I"../FreeRTOS" -I"../FreeRTOS/Source/include" -I"../FreeRTOS/Source/Portable/Thirdparty/GCC/ATmega"  -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -Wall -mmcu=atmega328p -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\gcc\dev\atmega328p" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" 

【问题讨论】:

  • 没有显示初始化代码,所以我们不知道什么你实际设置的频率[以及什么你想要的滴答频率]。显然,它比您认为的频率低 14 倍。代替修复它,如何(例如):#define hookTICK_CALLS_BEFORE_POST ( 1000 / 14 )
  • freeRTOS 和 2k uC 没有太大意义。 IMO 购买 STM32 Nucleo 板并在 ARM Cortex 机器上开始使用 freeRTOS
  • 我使用 AVR 进行调试:我只是更了解 avr 汇编器,因此我可以更轻松地跟踪编译器优化。所以我可以更确定我没有搞砸 const/static/volatile。

标签: c avr freertos


【解决方案1】:

一些 AVR 使用看门狗定时器作为滴答源(参见 atmega328pb 示例),而其他 AVR 使用 Timer0(参见 atmega323 示例)。这取决于 MCU 是否具有带中断功能的增强型 WDT。 FreeRTOS\Source\portable\ThirdParty\GCC\ATmega\portmacro.h 第 89 行 FreeRTOS\Source\portable\ThirdParty\GCC\ATmega\port.c 第 46 行和 FreeRTOS\Source\portable\ThirdParty\GCC\ 中提供了详细信息ATmega\readme.md

如果使用 WDT,定时器滴答频率在 portmacro.h 中配置(默认为 15ms,最小周期也是如此),不受 configTICK_RATE_HZ 值的影响。要切换到 TIMER0(预配置),只需将字符串 #if defined(WDIE) && defined(WDIF) ... #endif 替换为 #define portUSE_TIMER0 。使用 -DportUSE_TIMER0 -UportUSE_WDTO 作为全局编译器键不起作用。您可以使用其他计时器,请参阅 port.c 等了解 Timer0 的配置方式。

当我如上所述切换到 Timer0 并在 FreeRTOSConfig.h 中进行更改时

#define configCPU_CLOCK_HZ          ( ( unsigned long ) 16000000 )
#define configTICK_RATE_HZ          ( ( TickType_t ) 1000 )

并在 main.c 中使 uxCallCounter 不稳定,我得到了我想要的行为。滴答误差 #define hookTICK_CALLS_BEFORE_POST ( 50000 ) 滴答周期为 47.9 秒)与外部振荡器文档匹配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多