Добрый день. Проблема в следующей задаче:
Код:
void ButtonTask(void* pvParameters) {
(void)pvParameters;
vTaskDelay(100);
while(1) {
// 1. Ждем, пока кнопка БУДЕТ НАЖАТА
while(BUTTON() == 0) { // BUTTON() == 0 значит "отпущена"
vTaskDelay(10);
}
// Здесь: кнопка НАЖАТА (BUTTON() == 1)
// 2. Антидребезг
vTaskDelay(20);
// 3. Подтверждаем, что кнопка все еще НАЖАТА
if(BUTTON() != 0) { // BUTTON() != 0 значит "нажата"
//LED3_ON();
xSemaphoreGive(xButtonSemaphore);
// 4. Ждем, пока кнопка БУДЕТ ОТПУЩЕНА
while(BUTTON() != 0) { // Ждем BUTTON() == 0
vTaskDelay(10);
}
//LED3_OFF();
}
}
}
Если строки с //LED3_OFF(); и //LED3_ON(); заккоментированы, то при нажатии на кнопку нет переключения состояния светодиода в задаче LedTask. Если расскомментирована хотя бы одна строка из этой пары то всё работает корректно. Из-за чего это может быть? Пробовал в уловиях циклов использовать volatile переменную получавшую значение из макроса BUTTON(), но всё тщетно. Как я понимаю дело в оптимизациях компилятора?
Приложу тулчейн:
Код:
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(arm_toolchain "Not Defined" CACHE PATH "Path to the arm toolchain folder.")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
if(UNIX)
set(CMAKE_C_COMPILER /usr/bin/arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER /usr/bin/arm-none-eabi-gcc)
set(ARM_SIZE ${arm_toolchain}/bin/arm-none-eabi-size CACHE INTERNAL "")
elseif(WIN32)
set(CMAKE_C_COMPILER ${arm_toolchain}/bin/arm-none-eabi-gcc.exe CACHE INTERNAL "")
set(CMAKE_CXX_COMPILER ${arm_toolchain}/bin/arm-none-eabi-g++.exe CACHE INTERNAL "")
set(ARM_SIZE ${arm_toolchain}/bin/arm-none-eabi-size.exe CACHE INTERNAL "")
endif()
set(CMAKE_C_FLAGS_DEBUG "-g3 -Og -DDEBUG")
set(CMAKE_C_FLAGS_RELEASE "-Os -DNDEBUG")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "")
set(CMAKE_CXX_FLAGS_DEBUG "-g3 -Og -DDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-Os -DNDEBUG")
set(CMAKE_C_COMPILER_WORKS TRUE)
set(CMAKE_CXX_COMPILER_WORKS TRUE)
set(CMAKE_ASM_COMPILER_WORKS TRUE)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
А так же приложу основные файлы
main.cpp
Код:
#include "main.hpp"
SemaphoreHandle_t xButtonSemaphore = NULL;
#ifdef __cplusplus
extern "C" {
#endif
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
{
(void)xTask;
(void)pcTaskName;
LED0_ON();
LED1_ON();
LED2_ON();
LED3_ON();
while(1);
}
void vApplicationMallocFailedHook(void)
{
LED0_ON();
LED1_ON();
LED2_ON();
LED3_ON();
while(1);
}
void vApplicationIdleHook(void)
{
//LED_ON();
//LED_OFF();
}
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize)
{
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE];
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
#if configUSE_TIMERS == 1
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize)
{
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH];
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
#endif
#ifdef __cplusplus
}
#endif
void ButtonTask(void* pvParameters) {
(void)pvParameters;
vTaskDelay(100);
while(1) {
// 1. Ждем, пока кнопка БУДЕТ НАЖАТА
while(BUTTON() == 0) { // BUTTON() == 0 значит "отпущена"
vTaskDelay(10);
}
// Здесь: кнопка НАЖАТА (BUTTON() == 1)
// 2. Антидребезг
vTaskDelay(20);
// 3. Подтверждаем, что кнопка все еще НАЖАТА
if(BUTTON() != 0) { // BUTTON() != 0 значит "нажата"
//LED3_ON();
xSemaphoreGive(xButtonSemaphore);
// 4. Ждем, пока кнопка БУДЕТ ОТПУЩЕНА
while(BUTTON() != 0) { // Ждем BUTTON() == 0
vTaskDelay(10);
}
//LED3_OFF();
}
}
}
void LedTask(void* pvParameters){
(void)pvParameters;
vTaskDelay(100);
while(1){
if(xSemaphoreTake(xButtonSemaphore, 1) == pdPASS){
LED1_TOGGLE();
}
vTaskDelay(1);
}
}
extern "C" int main(void)
{
INIT();
xButtonSemaphore = xSemaphoreCreateBinary();
if(xButtonSemaphore == NULL){LED2_ON();}
xTaskCreate(
ButtonTask,
"Button",
100,
NULL,
1,
NULL
);
xTaskCreate(
LedTask,
"Led",
100,
NULL,
1,
NULL
);
vTaskStartScheduler();
while(1)
{
LED0_ON();
LED1_ON();
LED2_ON();
LED3_ON();
}
return 0;
}
main.hpp
Код:
#pragma once
#include "stm32f4xx.h"
#include "init.hpp"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#include "semphr.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LED0_ON() (GPIOC->BSRR = GPIO_BSRR_BS13) // PC13 ON
#define LED0_OFF() (GPIOC->BSRR = GPIO_BSRR_BR13) // PC13 OFF
#define LED0_TOGGLE() (GPIOC->ODR ^= GPIO_ODR_ODR_13) // PC13 TOGGLE
#define LED1_ON() (GPIOA->BSRR = GPIO_BSRR_BS_0) // PA0 ON
#define LED1_OFF() (GPIOA->BSRR = GPIO_BSRR_BR_0) // PA0 OFF
#define LED1_TOGGLE() (GPIOA->ODR ^= GPIO_ODR_ODR_0) // PA0 TOGGLE
#define LED2_ON() (GPIOA->BSRR = GPIO_BSRR_BS_1) // PA1 ON
#define LED2_OFF() (GPIOA->BSRR = GPIO_BSRR_BR_1) // PA1 OFF
#define LED2_TOGGLE() (GPIOA->ODR ^= GPIO_ODR_ODR_1) // PA1 TOGGLE
#define LED3_ON() (GPIOA->BSRR = GPIO_BSRR_BS_2) // PA2 ON
#define LED3_OFF() (GPIOA->BSRR = GPIO_BSRR_BR_2) // PA2 OFF
#define LED3_TOGGLE() (GPIOA->ODR ^= GPIO_ODR_ODR_2) // PA2 TOGGLE
#define BUTTON() ((!(GPIOA->IDR & GPIO_IDR_ID3_Msk))) // Returns 1 if button is pressed
void ButtonTask(void* pvParameters);
void LedTask(void* pvParameters);
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName);
void vApplicationMallocFailedHook(void);
void vApplicationIdleHook(void);
#ifdef __cplusplus
}
#endif
FreeRTOSConfig.h
Код:
/* Ensure stdint is only used by the compiler, and not the assembler. */
#ifdef __ICCARM__
#include <stdint.h>
#endif
#include "system_stm32f4xx.h"
#define configSUPPORT_STATIC_ALLOCATION 1
//#define configUSE_TICKLESS_IDLE 0
#define configUSE_TIME_SLICING 1
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ (SystemCoreClock)
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES (5)
#define configMINIMAL_STACK_SIZE ((unsigned short)128)
#define configTOTAL_HEAP_SIZE ((size_t)(10 * 1024))
#define configMAX_TASK_NAME_LEN (10)
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 0
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES (2)
/* Software timer definitions. */
#define configUSE_TIMERS 0
#define configTIMER_TASK_PRIORITY (2)
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2)
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4 /* 15 priority levels */
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#define configASSERT(x) \
if ((x) == 0) \
{ \
taskDISABLE_INTERRUPTS(); \
for (;;) \
; \
}
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#endif /* FREERTOS_CONFIG_H */
Добавлено after 1 hour 3 minutes 7 seconds:Дизассемблер задачи
Код:
08000450 <ButtonTask>:
8000450: b508 push {r3, lr}
8000452: 2064 movs r0, #100 @ 0x64
8000454: f000 fcee bl 8000e34 <vTaskDelay>
8000458: e002 b.n 8000460 <ButtonTask+0x10>
800045a: 200a movs r0, #10
800045c: f000 fcea bl 8000e34 <vTaskDelay>
8000460: 4b10 ldr r3, [pc, #64] @ (80004a4 <ButtonTask+0x54>)
8000462: 691b ldr r3, [r3, #16]
8000464: f013 0f08 tst.w r3, #8
8000468: d1f7 bne.n 800045a <ButtonTask+0xa>
800046a: 2014 movs r0, #20
800046c: f000 fce2 bl 8000e34 <vTaskDelay>
8000470: 4b0c ldr r3, [pc, #48] @ (80004a4 <ButtonTask+0x54>)
8000472: 691b ldr r3, [r3, #16]
8000474: f013 0f08 tst.w r3, #8
8000478: d1f2 bne.n 8000460 <ButtonTask+0x10>
800047a: 2300 movs r3, #0
800047c: 461a mov r2, r3
800047e: 4619 mov r1, r3
8000480: 4809 ldr r0, [pc, #36] @ (80004a8 <ButtonTask+0x58>)
8000482: 6800 ldr r0, [r0, #0]
8000484: f001 f832 bl 80014ec <xQueueGenericSend>
8000488: e002 b.n 8000490 <ButtonTask+0x40>
800048a: 200a movs r0, #10
800048c: f000 fcd2 bl 8000e34 <vTaskDelay>
8000490: 4b04 ldr r3, [pc, #16] @ (80004a4 <ButtonTask+0x54>)
8000492: 691b ldr r3, [r3, #16]
8000494: f013 0f08 tst.w r3, #8
8000498: d0f7 beq.n 800048a <ButtonTask+0x3a>
800049a: 4b02 ldr r3, [pc, #8] @ (80004a4 <ButtonTask+0x54>)
800049c: f44f 2280 mov.w r2, #262144 @ 0x40000
80004a0: 619a str r2, [r3, #24]
80004a2: e7dd b.n 8000460 <ButtonTask+0x10>
80004a4: 40020000 .word 0x40020000
80004a8: 2000027c .word 0x2000027c
080004ac <LedTask>:
80004ac: b508 push {r3, lr}
80004ae: 2064 movs r0, #100 @ 0x64
80004b0: f000 fcc0 bl 8000e34 <vTaskDelay>
80004b4: e007 b.n 80004c6 <LedTask+0x1a>
80004b6: 4a09 ldr r2, [pc, #36] @ (80004dc <LedTask+0x30>)
80004b8: 6953 ldr r3, [r2, #20]
80004ba: f083 0301 eor.w r3, r3, #1
80004be: 6153 str r3, [r2, #20]
80004c0: 2001 movs r0, #1
80004c2: f000 fcb7 bl 8000e34 <vTaskDelay>
80004c6: 2300 movs r3, #0
80004c8: 2201 movs r2, #1
80004ca: 4619 mov r1, r3