fix freertos kernel compatibility
This commit is contained in:
parent
02e1de09ff
commit
b27b45fb9a
4
.gitignore
vendored
4
.gitignore
vendored
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
picotool
|
picotool
|
||||||
sdk
|
sdk
|
||||||
freertos
|
freertos*
|
||||||
|
|
||||||
build
|
build
|
||||||
toolchain
|
toolchain
|
||||||
|
|
||||||
|
*.orig
|
||||||
20
Makefile
20
Makefile
@ -4,7 +4,7 @@ SDK_VERSION := 2.1.0
|
|||||||
PICOTOOL := $(INSTALL_PATH)/picotool/$(SDK_VERSION)/build/picotool
|
PICOTOOL := $(INSTALL_PATH)/picotool/$(SDK_VERSION)/build/picotool
|
||||||
|
|
||||||
export PICO_SDK_PATH=$(INSTALL_PATH)/sdk/$(SDK_VERSION)
|
export PICO_SDK_PATH=$(INSTALL_PATH)/sdk/$(SDK_VERSION)
|
||||||
# if using a different platform or arch, set ot here
|
# if using a different platform or arch, set it here
|
||||||
export PICO_PLATFORM=rp2350
|
export PICO_PLATFORM=rp2350
|
||||||
|
|
||||||
# project name, need to be passed as make input (ex: make project name=test)
|
# project name, need to be passed as make input (ex: make project name=test)
|
||||||
@ -13,6 +13,7 @@ name := ""
|
|||||||
install:
|
install:
|
||||||
@./scripts/install_sdk.bash $(SDK_VERSION)
|
@./scripts/install_sdk.bash $(SDK_VERSION)
|
||||||
@./scripts/install_picotool.bash $(SDK_VERSION)
|
@./scripts/install_picotool.bash $(SDK_VERSION)
|
||||||
|
@./scripts/install_freertos.bash
|
||||||
|
|
||||||
info:
|
info:
|
||||||
@$(PICOTOOL) info -a
|
@$(PICOTOOL) info -a
|
||||||
@ -20,7 +21,22 @@ info:
|
|||||||
project:
|
project:
|
||||||
@./scripts/scaffold_project.bash $(name) $(SDK_VERSION)
|
@./scripts/scaffold_project.bash $(name) $(SDK_VERSION)
|
||||||
|
|
||||||
compile:
|
.check-name:
|
||||||
|
ifeq ($(strip $(name)), "")
|
||||||
|
@echo "error: project name must be set, ex: name=<project_name>"
|
||||||
|
@false
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(shell test -d $(name) && echo "ok"),)
|
||||||
|
@echo "error: project $(name) does not exist"
|
||||||
|
@false
|
||||||
|
endif
|
||||||
|
|
||||||
|
format: .check-name
|
||||||
|
@test -f "$(shell find /usr/bin/ -name astyle)" && astyle --style=java --indent=spaces=4 -K -xC120 $(name)/*.c
|
||||||
|
|
||||||
|
compile: format
|
||||||
|
rm -f ${name}/build/CMakeCache.txt
|
||||||
@(test -d ${name} && mkdir -p ${name}/build && cd ${name}/build && cmake .. && make -j$(nproc) && echo "project compile successfully") || echo "error: unable to compile project: $(name)"
|
@(test -d ${name} && mkdir -p ${name}/build && cd ${name}/build && cmake .. && make -j$(nproc) && echo "project compile successfully") || echo "error: unable to compile project: $(name)"
|
||||||
|
|
||||||
push: compile
|
push: compile
|
||||||
|
|||||||
@ -13,92 +13,88 @@
|
|||||||
* See http://www.freertos.org/a00110.html.
|
* See http://www.freertos.org/a00110.html.
|
||||||
*----------------------------------------------------------*/
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
#define configUSE_PREEMPTION 1
|
// Scheduler Configuration
|
||||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
#define configUSE_PREEMPTION 1 // 1: Preemptive scheduler, 0: Cooperative scheduler
|
||||||
#define configUSE_IDLE_HOOK 0
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 // Use optimized task selection if available
|
||||||
#define configUSE_TICK_HOOK 0
|
#define configUSE_IDLE_HOOK 0 // 1: Use Idle hook function
|
||||||
#define configCPU_CLOCK_HZ ((unsigned long)150000000) // RP2350 default clock is 150 MHz
|
#define configUSE_TICK_HOOK 0 // 1: Use Tick hook function
|
||||||
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
|
#define configIDLE_SHOULD_YIELD 1 // 1: Idle task yields to same priority tasks
|
||||||
#define configMAX_PRIORITIES 5
|
|
||||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 256 )
|
|
||||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 16 * 1024 ) )
|
|
||||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
|
||||||
#define configUSE_TRACE_FACILITIES 0
|
|
||||||
#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 1
|
|
||||||
#define configUSE_MALLOC_FAILED_HOOK 0
|
|
||||||
#define configUSE_APPLICATION_TASK_TAG 0
|
|
||||||
#define configUSE_COUNTING_SEMAPHORES 1
|
|
||||||
#define configGENERATE_RUN_TIME_STATS 0
|
|
||||||
|
|
||||||
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
// System Clock Configuration
|
||||||
|
#define configCPU_CLOCK_HZ ((unsigned long)150000000) // CPU frequency: 150 MHz for RP2350
|
||||||
|
#define configTICK_RATE_HZ ((TickType_t)1000) // RTOS tick frequency (1000 Hz = 1ms tick)
|
||||||
|
|
||||||
#define configENABLE_FPU 0
|
// Task Configuration
|
||||||
#define configENABLE_TRUSTZONE 0
|
#define configMAX_PRIORITIES 5 // Maximum number of priority levels
|
||||||
|
#define configMINIMAL_STACK_SIZE ((unsigned short)256) // Minimum stack size in words
|
||||||
|
#define configMAX_TASK_NAME_LEN (16) // Maximum length of task names
|
||||||
|
|
||||||
/* Co-routine definitions. */
|
// Memory Configuration
|
||||||
#define configUSE_CO_ROUTINES 0
|
#define configTOTAL_HEAP_SIZE ((size_t)(16 * 1024)) // Total RTOS heap size (16 KB)
|
||||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
#define configSUPPORT_DYNAMIC_ALLOCATION 1 // 1: Enable dynamic memory allocation
|
||||||
|
|
||||||
/* Software timer definitions. */
|
// Synchronization Primitives
|
||||||
#define configUSE_TIMERS 1
|
#define configUSE_MUTEXES 1 // 1: Enable mutexes
|
||||||
#define configTIMER_TASK_PRIORITY ( 2 )
|
#define configUSE_RECURSIVE_MUTEXES 1 // 1: Enable recursive mutexes
|
||||||
#define configTIMER_QUEUE_LENGTH 10
|
#define configUSE_COUNTING_SEMAPHORES 1 // 1: Enable counting semaphores
|
||||||
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
|
#define configQUEUE_REGISTRY_SIZE 8 // Number of queues/semaphores that can be registered
|
||||||
|
|
||||||
#define configENABLE_MPU 0
|
// Debugging and Diagnostics
|
||||||
|
#define configUSE_TRACE_FACILITIES 0 // 1: Enable trace/debug facilities
|
||||||
|
#define configCHECK_FOR_STACK_OVERFLOW 2 // Stack overflow checking method (0=off, 1=method1, 2=method2)
|
||||||
|
#define configUSE_MALLOC_FAILED_HOOK 0 // 1: Use memory allocation failure hook
|
||||||
|
#define configUSE_APPLICATION_TASK_TAG 0 // 1: Enable task tagging
|
||||||
|
#define configGENERATE_RUN_TIME_STATS 0 // 1: Generate run-time statistics
|
||||||
|
|
||||||
/* Set the following definitions to 1 to include the API function, or zero
|
// Timer Configuration
|
||||||
to exclude the API function. */
|
#define configUSE_TIMERS 1 // 1: Enable software timers
|
||||||
#define INCLUDE_vTaskPrioritySet 1
|
#define configTIMER_TASK_PRIORITY (2) // Timer service task priority
|
||||||
#define INCLUDE_uxTaskPriorityGet 1
|
#define configTIMER_QUEUE_LENGTH 10 // Timer command queue length
|
||||||
#define INCLUDE_vTaskDelete 1
|
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) // Timer task stack size
|
||||||
#define INCLUDE_vTaskCleanUpResources 0
|
|
||||||
#define INCLUDE_vTaskSuspend 1
|
|
||||||
#define INCLUDE_vTaskDelayUntil 1
|
|
||||||
#define INCLUDE_vTaskDelay 1
|
|
||||||
#define INCLUDE_xTaskGetSchedulerState 1
|
|
||||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
|
||||||
#define INCLUDE_uxTaskGetStackHighWaterMark 0
|
|
||||||
#define INCLUDE_xTaskGetIdleTaskHandle 0
|
|
||||||
#define INCLUDE_eTaskGetState 0
|
|
||||||
#define INCLUDE_xSemaphoreGetMutexHolder 0
|
|
||||||
#define INCLUDE_xTimerPendFunctionCall 1
|
|
||||||
#define INCLUDE_xQueueGetMutexHolder 0
|
|
||||||
#define INCLUDE_xEventGroupSetBitFromISR 1
|
|
||||||
#define INCLUDE_xTimerPendFunctionCall 1
|
|
||||||
|
|
||||||
/* Cortex-M specific definitions. */
|
// Co-routine Configuration
|
||||||
|
#define configUSE_CO_ROUTINES 0 // 1: Enable co-routines
|
||||||
|
#define configMAX_CO_ROUTINE_PRIORITIES (2) // Maximum co-routine priorities
|
||||||
|
|
||||||
|
// Hardware Specific Configuration
|
||||||
|
#define configENABLE_FPU 1 // 1: Enable Floating Point Unit
|
||||||
|
#define configENABLE_TRUSTZONE 0 // 1: Enable TrustZone
|
||||||
|
#define configENABLE_MPU 0 // 1: Enable Memory Protection Unit (defined twice in original)
|
||||||
|
#define configRUN_FREERTOS_SECURE_ONLY 1 // 1: Run in secure mode only
|
||||||
|
#define configUSE_16_BIT_TICKS 0 // 0: Use 32-bit ticks, 1: Use 16-bit ticks
|
||||||
|
|
||||||
|
// API Inclusion Configuration
|
||||||
|
#define INCLUDE_vTaskPrioritySet 1 // Include task priority set API
|
||||||
|
#define INCLUDE_uxTaskPriorityGet 1 // Include task priority get API
|
||||||
|
#define INCLUDE_vTaskDelete 1 // Include task delete API
|
||||||
|
#define INCLUDE_vTaskCleanUpResources 0 // Include task cleanup API
|
||||||
|
#define INCLUDE_vTaskSuspend 1 // Include task suspend API
|
||||||
|
#define INCLUDE_vTaskDelayUntil 1 // Include delay until API
|
||||||
|
#define INCLUDE_vTaskDelay 1 // Include delay API
|
||||||
|
#define INCLUDE_xTaskGetSchedulerState 1 // Include scheduler state API
|
||||||
|
#define INCLUDE_xTaskGetCurrentTaskHandle 1 // Include current task handle API
|
||||||
|
#define INCLUDE_uxTaskGetStackHighWaterMark 0 // Include stack high water mark API
|
||||||
|
#define INCLUDE_xTaskGetIdleTaskHandle 0 // Include idle task handle API
|
||||||
|
#define INCLUDE_eTaskGetState 0 // Include task state API
|
||||||
|
#define INCLUDE_xSemaphoreGetMutexHolder 0 // Include mutex holder API
|
||||||
|
#define INCLUDE_xTimerPendFunctionCall 1 // Include timer pend function call API (defined twice in original)
|
||||||
|
#define INCLUDE_xQueueGetMutexHolder 0 // Include queue mutex holder API
|
||||||
|
#define INCLUDE_xEventGroupSetBitFromISR 1 // Include event group set bit from ISR API
|
||||||
|
|
||||||
|
// Cortex-M Interrupt Configuration
|
||||||
#ifdef __NVIC_PRIO_BITS
|
#ifdef __NVIC_PRIO_BITS
|
||||||
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
|
#define configPRIO_BITS __NVIC_PRIO_BITS // Use CMSIS defined priority bits
|
||||||
#define configPRIO_BITS __NVIC_PRIO_BITS
|
|
||||||
#else
|
#else
|
||||||
#define configPRIO_BITS 3 /* 7 priority levels */
|
#define configPRIO_BITS 3 // 7 priority levels (default)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The lowest interrupt priority that can be used in a call to a "set priority"
|
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x7 // Lowest interrupt priority
|
||||||
function. */
|
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 // Highest priority for FreeRTOS API calls
|
||||||
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x7
|
|
||||||
|
|
||||||
/* 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))
|
#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))
|
#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
|
// Assertion Definition
|
||||||
header file. */
|
#define configASSERT(x) if((x) == 0) { taskDISABLE_INTERRUPTS(); for(;;); } // Basic assert implementation
|
||||||
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
|
|
||||||
|
|
||||||
#endif /* FREERTOS_CONFIG_H */
|
#endif /* FREERTOS_CONFIG_H */
|
||||||
28
scripts/install_freertos.bash
Executable file
28
scripts/install_freertos.bash
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
######################################################
|
||||||
|
#
|
||||||
|
# Install FreeRTOS Raspberry Pi Kernel.
|
||||||
|
# src: https://github.com/raspberrypi/FreeRTOS-Kernel
|
||||||
|
#
|
||||||
|
# ex: ./install_freertos.bash
|
||||||
|
#
|
||||||
|
######################################################
|
||||||
|
|
||||||
|
if [[ -z ${INSTALL_PATH} ]]
|
||||||
|
then
|
||||||
|
INSTALL_PATH=${PWD}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d ${INSTALL_PATH}/freertos ]]
|
||||||
|
then
|
||||||
|
echo "installing freertos..."
|
||||||
|
git clone https://github.com/raspberrypi/FreeRTOS-Kernel ${INSTALL_PATH}/freertos
|
||||||
|
if [[ $? != 0 ]]
|
||||||
|
then
|
||||||
|
echo "error: unable to clone freertos"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "freertos installation completed"
|
||||||
@ -12,9 +12,11 @@ project(simple_led C CXX ASM)
|
|||||||
|
|
||||||
pico_sdk_init()
|
pico_sdk_init()
|
||||||
|
|
||||||
set(FREERTOS_SRC_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../freertos/FreeRTOSv202411.00/FreeRTOS/Source)
|
set(FREERTOS_SRC_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../freertos)
|
||||||
set(FREERTOS_CONFIG_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../config)
|
set(FREERTOS_CONFIG_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../config)
|
||||||
|
|
||||||
|
include(${FREERTOS_SRC_DIRECTORY}/portable/ThirdParty/GCC/RP2350_ARM_NTZ/FreeRTOS_Kernel_import.cmake)
|
||||||
|
|
||||||
# add_library(FreeRTOS STATIC
|
# add_library(FreeRTOS STATIC
|
||||||
# ${FREERTOS_SRC_DIRECTORY}/event_groups.c
|
# ${FREERTOS_SRC_DIRECTORY}/event_groups.c
|
||||||
# ${FREERTOS_SRC_DIRECTORY}/list.c
|
# ${FREERTOS_SRC_DIRECTORY}/list.c
|
||||||
@ -31,7 +33,7 @@ set(FREERTOS_CONFIG_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../config)
|
|||||||
include_directories(
|
include_directories(
|
||||||
${FREERTOS_CONFIG_DIRECTORY}
|
${FREERTOS_CONFIG_DIRECTORY}
|
||||||
${FREERTOS_SRC_DIRECTORY}/include
|
${FREERTOS_SRC_DIRECTORY}/include
|
||||||
${FREERTOS_SRC_DIRECTORY}/portable/GCC/ARM_CM33_NTZ/non_secure
|
${FREERTOS_SRC_DIRECTORY}/portable/ThirdParty/GCC/RP2350_ARM_NTZ/non_secure
|
||||||
)
|
)
|
||||||
|
|
||||||
set(FREERTOS_SOURCES
|
set(FREERTOS_SOURCES
|
||||||
@ -45,8 +47,9 @@ set(FREERTOS_SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(FREERTOS_PORT_FILES
|
set(FREERTOS_PORT_FILES
|
||||||
${FREERTOS_SRC_DIRECTORY}/portable/GCC/ARM_CM33_NTZ/non_secure/port.c
|
${FREERTOS_SRC_DIRECTORY}/portable/ThirdParty/GCC/RP2350_ARM_NTZ/non_secure/port.c
|
||||||
${FREERTOS_SRC_DIRECTORY}/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c
|
${FREERTOS_SRC_DIRECTORY}/portable/ThirdParty/GCC/RP2350_ARM_NTZ/non_secure/portasm.c
|
||||||
|
${FREERTOS_SRC_DIRECTORY}/portable/ThirdParty/GCC/RP2350_ARM_NTZ/non_secure/mpu_wrappers_v2_asm.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(simple_led main.c ${FREERTOS_SOURCES} ${FREERTOS_PORT_FILES})
|
add_executable(simple_led main.c ${FREERTOS_SOURCES} ${FREERTOS_PORT_FILES})
|
||||||
@ -57,10 +60,11 @@ pico_set_program_version(simple_led "0.1")
|
|||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
simple_led
|
simple_led
|
||||||
pico_stdlib
|
pico_stdlib
|
||||||
|
hardware_exception
|
||||||
# FreeRTOS
|
# FreeRTOS
|
||||||
)
|
)
|
||||||
|
|
||||||
pico_enable_stdio_uart(simple_led 0)
|
pico_enable_stdio_uart(simple_led 1)
|
||||||
pico_enable_stdio_usb(simple_led 1)
|
pico_enable_stdio_usb(simple_led 1)
|
||||||
|
|
||||||
pico_add_extra_outputs(simple_led)
|
pico_add_extra_outputs(simple_led)
|
||||||
|
|||||||
@ -1,92 +1,55 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "pico/stdlib.h"
|
|
||||||
#include <FreeRTOS.h>
|
#include <FreeRTOS.h>
|
||||||
|
#include <pico/printf.h>
|
||||||
|
#include <pico/stdlib.h>
|
||||||
|
#include <pico/time.h>
|
||||||
|
#include <semphr.h>
|
||||||
#include <task.h>
|
#include <task.h>
|
||||||
#include <queue.h>
|
|
||||||
|
|
||||||
#ifndef LED_DELAY_MS
|
|
||||||
#define LED_DELAY_MS 500
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GPIO_15 15
|
#define GPIO_15 15
|
||||||
#define GPIO_13 13
|
#define GPIO_13 13
|
||||||
|
|
||||||
void blink_success(bool in_task) {
|
enum status { STOP, RUNNING, FAILED, UNKNOWN };
|
||||||
gpio_put(PICO_DEFAULT_LED_PIN, true);
|
|
||||||
if (in_task)
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
|
||||||
else
|
|
||||||
sleep_ms(500);
|
|
||||||
gpio_put(PICO_DEFAULT_LED_PIN, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void blink_failed(bool in_task) {
|
|
||||||
for (;;) {
|
|
||||||
gpio_put(PICO_DEFAULT_LED_PIN, true);
|
|
||||||
if (in_task)
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
|
||||||
else
|
|
||||||
sleep_ms(500);
|
|
||||||
|
|
||||||
gpio_put(PICO_DEFAULT_LED_PIN, false);
|
|
||||||
if (in_task)
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
|
||||||
else
|
|
||||||
sleep_ms(500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void blink_default_led(void) {
|
|
||||||
#ifdef PICO_DEFAULT_LED_PIN
|
|
||||||
while (true) {
|
|
||||||
gpio_put(PICO_DEFAULT_LED_PIN, true);
|
|
||||||
// sleep_ms(LED_DELAY_MS);
|
|
||||||
vTaskDelay(LED_DELAY_MS / portTICK_PERIOD_MS);
|
|
||||||
gpio_put(PICO_DEFAULT_LED_PIN, false);
|
|
||||||
// sleep_ms(1000);
|
|
||||||
vTaskDelay(LED_DELAY_MS / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void run_health() {
|
|
||||||
BaseType_t res = xTaskCreate(
|
|
||||||
blink_default_led,
|
|
||||||
"healthcheck",
|
|
||||||
configMINIMAL_STACK_SIZE,
|
|
||||||
NULL,
|
|
||||||
configMAX_PRIORITIES - 1U,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
if (res != pdPASS) {
|
|
||||||
printf("error: unable to launch healthcheck task, code error: %d\n", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the application state.
|
||||||
|
*/
|
||||||
typedef struct state state;
|
typedef struct state state;
|
||||||
struct state {
|
struct state {
|
||||||
|
SemaphoreHandle_t lock;
|
||||||
|
|
||||||
int counter;
|
int counter;
|
||||||
int bs;
|
|
||||||
bool can_incr;
|
bool can_incr;
|
||||||
|
|
||||||
clock_t push_clock;
|
absolute_time_t push_clock;
|
||||||
bool on_reset;
|
bool on_reset;
|
||||||
bool is_reset;
|
bool is_reset;
|
||||||
|
|
||||||
|
int status;
|
||||||
};
|
};
|
||||||
|
|
||||||
static state global_state = (state) {
|
/**
|
||||||
|
* Parameters available to be passed in task function.
|
||||||
|
*/
|
||||||
|
typedef struct params params;
|
||||||
|
struct params {
|
||||||
|
uint gpio;
|
||||||
|
uint32_t delays_ms;
|
||||||
|
bool in_task;
|
||||||
|
state *s;
|
||||||
|
};
|
||||||
|
|
||||||
|
static state global_state = {
|
||||||
.counter = 0,
|
.counter = 0,
|
||||||
.can_incr = true,
|
.can_incr = true,
|
||||||
.on_reset = false,
|
.on_reset = false,
|
||||||
.is_reset = false,
|
.is_reset = false,
|
||||||
|
.status = RUNNING,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void init_state(state *s) {
|
||||||
|
s->lock = xSemaphoreCreateMutex();
|
||||||
|
}
|
||||||
|
|
||||||
void incr_counter(state *s) {
|
void incr_counter(state *s) {
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
if (s->can_incr) {
|
if (s->can_incr) {
|
||||||
@ -112,15 +75,37 @@ void set_push_clock(state *s) {
|
|||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
if (s->push_clock)
|
if (s->push_clock)
|
||||||
return;
|
return;
|
||||||
s->push_clock = clock();
|
s->push_clock = get_absolute_time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_status(state *s, int status) {
|
||||||
|
if (s != NULL) {
|
||||||
|
if (xSemaphoreTake(s->lock, (TickType_t)10) == pdTRUE) {
|
||||||
|
s->status = status;
|
||||||
|
xSemaphoreGive(s->lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
blink_failed(PICO_DEFAULT_LED_PIN, 200, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_status(state *s) {
|
||||||
|
if (s != NULL) {
|
||||||
|
if (xSemaphoreTake(s->lock, (TickType_t)10) == pdTRUE) {
|
||||||
|
int res = s->status;
|
||||||
|
xSemaphoreGive(s->lock);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
blink_failed(PICO_DEFAULT_LED_PIN, 200, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_resetting(state *s) {
|
bool is_resetting(state *s) {
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
clock_t c = clock();
|
absolute_time_t end = get_absolute_time();
|
||||||
double exec_time = (double)(c - s->push_clock) / CLOCKS_PER_SEC;
|
uint64_t elapsed_ms = absolute_time_diff_us(s->push_clock, end) / 1000;
|
||||||
if (exec_time >= 2)
|
if (elapsed_ms >= 2000)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -132,71 +117,128 @@ void reset(state *s) {
|
|||||||
s->is_reset = true;
|
s->is_reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void led_control() {
|
void blink_success(uint gpio, uint32_t delay_ms, bool in_task) {
|
||||||
while (1) {
|
gpio_put(gpio, true);
|
||||||
// return low level when the button is pressed
|
if (in_task)
|
||||||
if (!gpio_get(GPIO_13)) {
|
vTaskDelay(pdMS_TO_TICKS(delay_ms));
|
||||||
// sleep_ms(20); // avoid "bounce" phenomenon (buffeting)
|
else
|
||||||
vTaskDelay(20 / portTICK_PERIOD_MS);
|
sleep_ms(delay_ms);
|
||||||
if (!gpio_get(GPIO_13)) {
|
gpio_put(gpio, false);
|
||||||
if (global_state.is_reset)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
set_push_clock(&global_state);
|
|
||||||
if (is_resetting(&global_state)) {
|
|
||||||
gpio_put(GPIO_15, true);
|
|
||||||
// sleep_ms(500);
|
|
||||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
|
||||||
gpio_put(GPIO_15, false);
|
|
||||||
// sleep_ms(500);
|
|
||||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
|
||||||
gpio_put(GPIO_15, true);
|
|
||||||
// sleep_ms(500);
|
|
||||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
|
||||||
gpio_put(GPIO_15, false);
|
|
||||||
// sleep_ms(500);
|
|
||||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
|
||||||
gpio_put(GPIO_15, true);
|
|
||||||
// sleep_ms(500);
|
|
||||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
|
||||||
gpio_put(GPIO_15, false);
|
|
||||||
|
|
||||||
reset(&global_state);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
incr_counter(&global_state);
|
void blink_failed(uint gpio, uint32_t delay_ms, bool in_task) {
|
||||||
if (can_push(&global_state))
|
for (;;) {
|
||||||
gpio_put(GPIO_15, true);
|
gpio_put(gpio, false);
|
||||||
continue;
|
if (in_task)
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(delay_ms));
|
||||||
|
else
|
||||||
|
sleep_ms(delay_ms);
|
||||||
|
|
||||||
|
gpio_put(gpio, true);
|
||||||
|
if (in_task)
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(delay_ms));
|
||||||
|
else
|
||||||
|
sleep_ms(delay_ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global_state.is_reset) {
|
void healtchheck(void *const vParameters) {
|
||||||
global_state.on_reset = false;
|
params *p = (params *const)vParameters;
|
||||||
global_state.is_reset = false;
|
for (;;) {
|
||||||
}
|
if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING ||
|
||||||
global_state.push_clock = 0;
|
get_status(p->s) != RUNNING)
|
||||||
set_can_incr(&global_state, true);
|
gpio_put(p->gpio, false);
|
||||||
gpio_put(GPIO_15, false);
|
else
|
||||||
|
gpio_put(p->gpio, true);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(p->delays_ms));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_led_control() {
|
void run_health(state *s) {
|
||||||
BaseType_t res = xTaskCreate(
|
static params p = {
|
||||||
led_control,
|
.delays_ms = 50,
|
||||||
"led_controller",
|
.gpio = PICO_DEFAULT_LED_PIN,
|
||||||
configMINIMAL_STACK_SIZE,
|
.in_task = true,
|
||||||
NULL,
|
};
|
||||||
configMAX_PRIORITIES - 1U,
|
p.s = s;
|
||||||
NULL
|
|
||||||
);
|
TaskHandle_t t;
|
||||||
|
BaseType_t res =
|
||||||
|
xTaskCreate(healtchheck, "healthcheck", configMINIMAL_STACK_SIZE,
|
||||||
|
(void *const)&p, configMAX_PRIORITIES - 1U, &t);
|
||||||
|
|
||||||
if (res != pdPASS) {
|
if (res != pdPASS) {
|
||||||
printf("error: unable to launch led control task, code error: %d\n", res);
|
stdio_printf("error: unable to launch healthcheck task, code error: %d\n",
|
||||||
|
res);
|
||||||
|
blink_failed(PICO_DEFAULT_LED_PIN, 200, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_control(void *const vParameters) {
|
||||||
|
params *p = (params *const)vParameters;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// return low level when the button is pressed
|
||||||
|
if (!gpio_get(GPIO_13)) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(20)); // avoid "bounce" phenomenon (buffeting)
|
||||||
|
if (!gpio_get(GPIO_13)) {
|
||||||
|
if (p->s->is_reset)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
set_push_clock(p->s);
|
||||||
|
if (is_resetting(p->s)) {
|
||||||
|
set_status(p->s, STOP);
|
||||||
|
reset(p->s);
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
gpio_put(GPIO_15, true);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(200));
|
||||||
|
|
||||||
|
gpio_put(GPIO_15, false);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(200));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
incr_counter(p->s);
|
||||||
|
if (can_push(p->s))
|
||||||
|
gpio_put(GPIO_15, true);
|
||||||
|
else
|
||||||
|
set_status(p->s, STOP);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p->s->is_reset) {
|
||||||
|
set_status(p->s, RUNNING);
|
||||||
|
p->s->on_reset = false;
|
||||||
|
p->s->is_reset = false;
|
||||||
|
}
|
||||||
|
p->s->push_clock = 0;
|
||||||
|
set_can_incr(p->s, true);
|
||||||
|
gpio_put(GPIO_15, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_led_control(state *s) {
|
||||||
|
static params p;
|
||||||
|
p.s = s;
|
||||||
|
|
||||||
|
BaseType_t res =
|
||||||
|
xTaskCreate(led_control, "led_controller", configMINIMAL_STACK_SIZE,
|
||||||
|
(void *const)&p, configMAX_PRIORITIES - 1U, NULL);
|
||||||
|
|
||||||
|
if (res != pdPASS) {
|
||||||
|
stdio_printf("error: unable to launch led control task, code error: %d\n",
|
||||||
|
res);
|
||||||
|
blink_failed(PICO_DEFAULT_LED_PIN, 200, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize needed GPIO.
|
||||||
|
*/
|
||||||
void init_gpio() {
|
void init_gpio() {
|
||||||
#ifdef PICO_DEFAULT_LED_PIN
|
#ifdef PICO_DEFAULT_LED_PIN
|
||||||
gpio_init(PICO_DEFAULT_LED_PIN);
|
gpio_init(PICO_DEFAULT_LED_PIN);
|
||||||
@ -210,42 +252,41 @@ void init_gpio() {
|
|||||||
gpio_set_dir(GPIO_13, GPIO_IN);
|
gpio_set_dir(GPIO_13, GPIO_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_scheduler_init(void *pvParameters) {
|
/**
|
||||||
for (;;) {
|
* Callback when unable to initialize task (not enough stask memory).
|
||||||
BaseType_t state = xTaskGetSchedulerState();
|
* Increase `uxStackDepth` arg when creating task if needed.
|
||||||
if (state == taskSCHEDULER_RUNNING)
|
*/
|
||||||
blink_success(true);
|
|
||||||
blink_success(true);
|
|
||||||
// vTaskDelay(pdMS_TO_TICKS(500));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName) {
|
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName) {
|
||||||
blink_failed(false);
|
blink_failed(PICO_DEFAULT_LED_PIN, 100, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
/**
|
||||||
{
|
* A simple application to play with leds with FreeRTOS.
|
||||||
|
* Yes, FreeRTOS is overkill for this kind of application
|
||||||
|
* but it's cool to see how easyly it can be integrated and
|
||||||
|
* easy to use for concurrent tasks.
|
||||||
|
*
|
||||||
|
* Hardware:
|
||||||
|
* - a push button switch
|
||||||
|
* - a red led
|
||||||
|
* - 2 10k ohm resistors
|
||||||
|
* - 1 200 ohm resistor
|
||||||
|
*
|
||||||
|
* When the Pico is on, the default led is on (acts as a healthcheck).
|
||||||
|
* You can then push the button and see the red led lights on.
|
||||||
|
* After 10 pushed, the red light lights off and the default led too.
|
||||||
|
* To reset the application, holds the button ~2 secs, the red light will
|
||||||
|
* blink two time and the application will be started again.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int main() {
|
||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
init_gpio();
|
init_gpio();
|
||||||
|
|
||||||
// TaskHandle_t health_task = run_health();
|
init_state(&global_state);
|
||||||
// TaskHandle_t led_task = run_led_control();
|
|
||||||
|
|
||||||
BaseType_t res = xTaskCreate(
|
run_health(&global_state);
|
||||||
check_scheduler_init,
|
run_led_control(&global_state);
|
||||||
"check_init",
|
|
||||||
256,
|
|
||||||
NULL,
|
|
||||||
configMAX_PRIORITIES - 1,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
if (res != pdPASS)
|
|
||||||
blink_failed(false);
|
|
||||||
else
|
|
||||||
blink_success(false);
|
|
||||||
|
|
||||||
vTaskStartScheduler();
|
vTaskStartScheduler();
|
||||||
|
|
||||||
blink_failed(false);
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user