Не работает переключение задач при удержании кнопки в программе, построенной в CoIDE

Программа билдится в CoIDE, но не работает переключение задач. При удерживании кнопки должна переключаться задача, то есть сначала горели 3 светодиода ( при нажатие выключались и обратно включались, а после удерживании кнопки должна переключиться задача, должна запуститься другая задачу ( например, бегущий огонёк по часовой стрелке.
Желательно написать рабочий новый код.

#include "stm32f30x.h"
#include "stm32f30x_gpio.h"
#include "stm32f30x_rcc.h"
#include "portmacro.h"
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

/* LED Configuration */
#define LED_RED_PE9     GPIO_Pin_9
#define LED_BLUE_PE8    GPIO_Pin_8
#define LED_ORANGE_PE10 GPIO_Pin_10
#define LED_GREEN_PE15  GPIO_Pin_15
#define LED_GREEN_PE11  GPIO_Pin_11
#define LED_ORANGE_PE14 GPIO_Pin_14
#define LED_BLUE_PE12   GPIO_Pin_12
#define LED_RED_PE13    GPIO_Pin_13

/* Define ALL_LEDS constant */
#define ALL_LEDS (LED_RED_PE9 | LED_BLUE_PE8 | LED_ORANGE_PE10 | \
                 LED_GREEN_PE15 | LED_GREEN_PE11 | LED_ORANGE_PE14 | \
                 LED_BLUE_PE12 | LED_RED_PE13)

/* Traffic Light Configuration */
#define RED1     GPIO_Pin_9    // PE9 (LD3)
#define YELLOW1  GPIO_Pin_8    // PE8 (LD4)
#define GREEN1   GPIO_Pin_10   // PE10 (LD5)
#define RED2     GPIO_Pin_13   // PE13 (LD10)
#define YELLOW2  GPIO_Pin_12   // PE12 (LD9)
#define GREEN2   GPIO_Pin_11   // PE11 (LD7)

#define USER_BUTTON     GPIO_Pin_0  // PA0
#define BUTTON_PORT     GPIOA

/* Timing Parameters */
#define DEBOUNCE_DELAY_MS 100
#define INITIAL_DELAY 250
#define DELAY_INCREMENT 50
#define MAX_DELAY 1000
#define MIN_DELAY 50
#define NORMAL_DELAY_MS 2000
#define BLINK_DELAY_MS 500

/* Message Types */
typedef enum {
    BUTTON_PRESSED,
    BUTTON_LONG_PRESS,
    MODE_SWITCH,
    SPEED_CHANGE,
    DIRECTION_CHANGE,
    TRAFFIC_MODE_CHANGE
} MessageType_t;

typedef struct {
    MessageType_t type;
    uint32_t value;
} ButtonMessage_t;

/* Global Variables */
xQueueHandle xMessageQueue = NULL;
xTaskHandle xCurrentModeTaskHandle = NULL;
xTaskHandle xStaticModeTaskHandle = NULL;
xTaskHandle xRunningModeTaskHandle = NULL;
xTaskHandle xDirectionChangeTaskHandle = NULL;
xTaskHandle xSpeedControlTaskHandle = NULL;
xTaskHandle xTrafficLightTaskHandle = NULL;

volatile uint8_t direction = 1;
volatile uint16_t current_delay = INITIAL_DELAY;
volatile uint8_t emergency_mode = 0;

/* Function Prototypes */
void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void vHardwareInit(void);
void vSwitchMode(xTaskHandle newModeTask);

/* Helper Functions */
void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
    if(GPIO_ReadOutputDataBit(GPIOx, GPIO_Pin) == Bit_SET) {
        GPIO_ResetBits(GPIOx, GPIO_Pin);
    } else {
        GPIO_SetBits(GPIOx, GPIO_Pin);
    }
}

void vHardwareInit(void) {
    GPIO_InitTypeDef gpio;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    gpio.GPIO_Mode = GPIO_Mode_OUT;
    gpio.GPIO_OType = GPIO_OType_PP;
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    gpio.GPIO_Pin = ALL_LEDS | RED1 | YELLOW1 | GREEN1 | RED2 | YELLOW2 | GREEN2;
    GPIO_Init(GPIOE, &gpio);

    gpio.GPIO_Mode = GPIO_Mode_IN;
    gpio.GPIO_PuPd = GPIO_PuPd_UP;
    gpio.GPIO_Pin = USER_BUTTON;
    GPIO_Init(GPIOA, &gpio);

    GPIO_ResetBits(GPIOE, ALL_LEDS | RED1 | YELLOW1 | GREEN1 | RED2 | YELLOW2 | GREEN2);
}

void vSwitchMode(xTaskHandle newModeTask) {
    if(xCurrentModeTaskHandle != NULL) {
        vTaskSuspend(xCurrentModeTaskHandle);
    }
    xCurrentModeTaskHandle = newModeTask;
    vTaskResume(newModeTask);
}

/* Task Implementations */
void vButtonTask(void *pvParameters) {
    portTickType xPressTime;
    uint8_t last_button_state = 1;
    ButtonMessage_t message;

    while(1) {
        uint8_t button_state = GPIO_ReadInputDataBit(BUTTON_PORT, USER_BUTTON);

        if(last_button_state && !button_state) {
            xPressTime = xTaskGetTickCount();
        }
        else if(!last_button_state && button_state) {
            portTickType duration = (xTaskGetTickCount() - xPressTime) * portTICK_RATE_MS;

            if(duration < 1000) {
                message.type = BUTTON_PRESSED;
                message.value = 0;
                xQueueSend(xMessageQueue, &message, 0);
            } else {
                message.type = MODE_SWITCH;
                message.value = 0;
                xQueueSend(xMessageQueue, &message, 0);
            }
        }

        last_button_state = button_state;
        vTaskDelay(DEBOUNCE_DELAY_MS / portTICK_RATE_MS);
    }
}

void vStaticModeTask(void *pvParameters) {
    ButtonMessage_t message;

    while(1) {
        if(xQueueReceive(xMessageQueue, &message, portMAX_DELAY) == pdPASS) {
            if(message.type == BUTTON_PRESSED) {
                GPIO_ToggleBits(GPIOE, LED_RED_PE9 | LED_BLUE_PE8 | LED_ORANGE_PE10);
            }
            else if(message.type == MODE_SWITCH) {
                GPIO_ResetBits(GPIOE, LED_RED_PE9 | LED_BLUE_PE8 | LED_ORANGE_PE10);
                vSwitchMode(xRunningModeTaskHandle);
            }
        }
    }
}

void vRunningModeTask(void *pvParameters) {
    const uint16_t leds[] = {LED_RED_PE9, LED_BLUE_PE8, LED_ORANGE_PE10,
                            LED_GREEN_PE15, LED_GREEN_PE11, LED_ORANGE_PE14,
                            LED_BLUE_PE12, LED_RED_PE13};
    uint8_t current_led = 0;
    ButtonMessage_t message;

    while(1) {
        if(xQueueReceive(xMessageQueue, &message, 0) == pdPASS) {
            if(message.type == MODE_SWITCH) {
                GPIO_ResetBits(GPIOE, ALL_LEDS);
                vSwitchMode(xDirectionChangeTaskHandle);
            }
        }

        GPIO_ResetBits(GPIOE, leds[current_led]);
        current_led = (current_led + 1) % 8;
        GPIO_SetBits(GPIOE, leds[current_led]);
        vTaskDelay(current_delay / portTICK_RATE_MS);
    }
}

void vDirectionChangeTask(void *pvParameters) {
    const uint16_t leds[] = {LED_RED_PE9, LED_BLUE_PE8, LED_ORANGE_PE10,
                            LED_GREEN_PE15, LED_GREEN_PE11, LED_ORANGE_PE14,
                            LED_BLUE_PE12, LED_RED_PE13};
    uint8_t current_led = 0;
    ButtonMessage_t message;

    while(1) {
        if(xQueueReceive(xMessageQueue, &message, 0) == pdPASS) {
            if(message.type == BUTTON_PRESSED) {
                direction = !direction; // Изменение направления по нажатию кнопки
            }
            else if(message.type == MODE_SWITCH) {
                GPIO_ResetBits(GPIOE, ALL_LEDS);
                vSwitchMode(xSpeedControlTaskHandle);
            }
        }

        GPIO_ResetBits(GPIOE, leds[current_led]);
        current_led = direction ? ((current_led + 1) % 8) : ((current_led == 0) ? 7 : (current_led - 1));
        GPIO_SetBits(GPIOE, leds[current_led]);
        vTaskDelay(current_delay / portTICK_RATE_MS);
    }
}

void vSpeedControlTask(void *pvParameters) {
    ButtonMessage_t message;

    while(1) {
        if(xQueueReceive(xMessageQueue, &message, portMAX_DELAY) == pdPASS) {
            if(message.type == BUTTON_PRESSED) {
                current_delay = (current_delay + DELAY_INCREMENT > MAX_DELAY) ? MIN_DELAY : (current_delay + DELAY_INCREMENT);
            }
            else if(message.type == MODE_SWITCH) {
                GPIO_ResetBits(GPIOE, ALL_LEDS);
                vSwitchMode(xTrafficLightTaskHandle);
            }
        }
    }
}

void vTrafficLightTask(void *pvParameters) {
    ButtonMessage_t message;
    const portTickType xNormalDelay = NORMAL_DELAY_MS / portTICK_RATE_MS;
    const portTickType xBlinkDelay = BLINK_DELAY_MS / portTICK_RATE_MS;

    while(1) {
        if(xQueueReceive(xMessageQueue, &message, 0) == pdPASS) {
            if(message.type == BUTTON_PRESSED) {
                emergency_mode = !emergency_mode;
                GPIO_ResetBits(GPIOE, RED1 | YELLOW1 | GREEN1 | RED2 | YELLOW2 | GREEN2);
            }
            else if(message.type == MODE_SWITCH) {
                GPIO_ResetBits(GPIOE, RED1 | YELLOW1 | GREEN1 | RED2 | YELLOW2 | GREEN2);
                vSwitchMode(xStaticModeTaskHandle);
            }
        }

        if(!emergency_mode) {
            /* Normal traffic light sequence */
            GPIO_SetBits(GPIOE, RED1 | GREEN2);
            vTaskDelay(xNormalDelay);

            GPIO_ResetBits(GPIOE, RED1 | GREEN2);
            GPIO_SetBits(GPIOE, YELLOW1 | YELLOW2);
            vTaskDelay(xNormalDelay/4);

            GPIO_ResetBits(GPIOE, YELLOW1 | YELLOW2);
            GPIO_SetBits(GPIOE, GREEN1 | RED2);
            vTaskDelay(xNormalDelay);

            GPIO_ResetBits(GPIOE, GREEN1 | RED2);
            GPIO_SetBits(GPIOE, YELLOW1 | YELLOW2);
            vTaskDelay(xNormalDelay/4);
        } else {
            /* Emergency blinking mode */
            GPIO_ToggleBits(GPIOE, YELLOW1 | YELLOW2);
            vTaskDelay(xBlinkDelay);
        }
    }
}

int main(void) {
    vHardwareInit();

    xMessageQueue = xQueueCreate(10, sizeof(ButtonMessage_t));

    /* Create all tasks */
    xTaskCreate(vButtonTask, (signed char*)"Button", configMINIMAL_STACK_SIZE, NULL, 6, NULL);
    xTaskCreate(vStaticModeTask, (signed char*)"Static", configMINIMAL_STACK_SIZE, NULL, 5, &xStaticModeTaskHandle);
    xTaskCreate(vRunningModeTask, (signed char*)"Running", configMINIMAL_STACK_SIZE, NULL, 4, &xRunningModeTaskHandle);
    xTaskCreate(vDirectionChangeTask, (signed char*)"Direction", configMINIMAL_STACK_SIZE, NULL, 3, &xDirectionChangeTaskHandle);
    xTaskCreate(vSpeedControlTask, (signed char*)"SpeedCtrl", configMINIMAL_STACK_SIZE, NULL, 2, &xSpeedControlTaskHandle);
    xTaskCreate(vTrafficLightTask, (signed char*)"Traffic", configMINIMAL_STACK_SIZE, NULL, 1, &xTrafficLightTaskHandle);

    /* Start with static mode */
    xCurrentModeTaskHandle = xStaticModeTaskHandle;
    vTaskSuspend(xRunningModeTaskHandle);
    vTaskSuspend(xDirectionChangeTaskHandle);
    vTaskSuspend(xSpeedControlTaskHandle);
    vTaskSuspend(xTrafficLightTaskHandle);

    vTaskStartScheduler();

    while(1);
}

Пишите, мы не против.
ЗЫ. Писать светодиодики в Free RTOS - верх маразма, хуже чем пушкой по воробьям.

1 лайк

Разрешите доложить!
Не имеем возможности, т.к. нет отладочной платы под STM32F3xx и симулятора!
Разрешите купить!

1 лайк

Emil FreeRTOS так и не освоил, а правда что за нее платят по 300к+ в месяц ?)))
интересно что ответят другие, особенно бывалые! надо будет почитать)

Кто? Где? И меня возьмите! Ну пожалуйста!

Удобная вещь, при условии что жирный МК и не умеете / не желаете разделять задачи проекта в одном цикле.
И начинаются проблемы, когда необходимо точные интервалы выдерживать, особенно периферии.

А вот такую кто использовал? Как?

на хх.ру дней 10-15 назад смотрел, (Cortex- xxx + freertos + куча всего по мелочи, много объявлений было штук 10 с зп 250к+) сейчас уже не вижу, кто то видимо уже занял места))) а еще алабуга вроде платит норм, еще и берут с обучением…

хотелось бы освоить наверное, но у меня должны окупиться предыдущие зания сначала, а пока что просто выполнять код на 2 ядрах хватает)))

Это у которой девиз “Если ты для себя выходные видишь на рыбалке или отдыхе, то нам не по пути!” ?

1 лайк

не знаю… я знаю то что другим понравилось эксплуатировать народ, раз все привыкли…
https://hh.ru/vacancy/108207579 а зп обычная мировая…

Лет 10 назад пытался. Тогда мало портов было. Поэтому остановился на FreeRTOS. А сейчас уже пару лет не выходило новых релизов, но это не точно.

@BABOS да, моя информация подтверждена: нет отпусков, частые переработки, график по 12 часов 5 или 6 дней в неделю.
В общем лохотрон. Отжимают из людей соки и выкидывают.

1 лайк

Мне не зашло, хрень, побаловался и забыл.

Кто или что мешает?

Вы забыли написать в чём Ваша проблема и задать вопрос(ы) если есть.