配置 FreeRTOS 计时器滴答持续时间的问题
Problems configuring duration of FreeRTOS timer tick
我决定尝试将 FreeRTOS 与 Arduino Uno (ATmega 328p) 结合使用,并使计时器挂钩的 LED 闪烁。但是,似乎我在 FreeRTOS 中设置了错误的计时器,并且找不到错误。我认为 LED 每 1 秒会变为 on/off(频率为 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.0\Packs\atmel\ATmega_DFP.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.0\Packs\atmel\ATmega_DFP.6.364\gcc\dev\atmega328p" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"
一些 AVR 使用看门狗定时器作为节拍源(参见 atmega328pb 示例),而其他使用 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 可变,我得到了我想要的行为。滴答误差 <5%(#define hookTICK_CALLS_BEFORE_POST ( 50000 )
滴答周期为 47.9 秒)与外部振荡器文档相匹配。
我决定尝试将 FreeRTOS 与 Arduino Uno (ATmega 328p) 结合使用,并使计时器挂钩的 LED 闪烁。但是,似乎我在 FreeRTOS 中设置了错误的计时器,并且找不到错误。我认为 LED 每 1 秒会变为 on/off(频率为 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.0\Packs\atmel\ATmega_DFP.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.0\Packs\atmel\ATmega_DFP.6.364\gcc\dev\atmega328p" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"
一些 AVR 使用看门狗定时器作为节拍源(参见 atmega328pb 示例),而其他使用 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 可变,我得到了我想要的行为。滴答误差 <5%(#define hookTICK_CALLS_BEFORE_POST ( 50000 )
滴答周期为 47.9 秒)与外部振荡器文档相匹配。