Created
June 21, 2022 08:28
-
-
Save sdbbs/b1410cd45106e0c0ee599f7fcdbb8f90 to your computer and use it in GitHub Desktop.
rp2040_fros_tmrisr_ex
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rp2040_fros_tmrisr_ex |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.13) | |
# also include .h files from the current source directory | |
SET(CMAKE_INCLUDE_CURRENT_DIR ON) | |
# Pull in SDK (must be before project) | |
set(PICO_PLATFORM rp2040) | |
include(pico_sdk_import.cmake) | |
# Pull in FreeRTOS | |
# explicit FREERTOS path - use "mixed" mode for MINGW64 Windows paths (with `C:` drive identifier, but with forward slash) | |
set(FREERTOS_KERNEL_PATH "C:/src/rp2040_pico/FreeRTOS-Kernel-SMP") | |
include(FreeRTOS_Kernel_import.cmake) | |
# note that FreeRTOS_Kernel_import.cmake does not print message if FREERTOS_KERNEL_PATH set explicitly, | |
# so let's print it out here (so we don't change the "vanilla" FreeRTOS_Kernel_import.cmake file): | |
message("The FREERTOS_KERNEL_PATH is '${FREERTOS_KERNEL_PATH}'") | |
message("The FREERTOS_KERNEL_RP2040_RELATIVE_PATH is '${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}'") | |
project(rp2040_fros_tmrisr_ex C CXX ASM) | |
set(CMAKE_C_STANDARD 11) | |
set(CMAKE_CXX_STANDARD 17) | |
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.0") | |
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.3.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}") | |
endif() | |
# Initialize the SDK | |
pico_sdk_init() | |
add_executable(rp2040_fros_tmrisr_ex | |
main.c | |
) | |
target_compile_definitions(rp2040_fros_tmrisr_ex PRIVATE | |
PICO_STDIO_STACK_BUFFER_SIZE=64 # use a small printf on stack buffer | |
) | |
add_compile_options(-Wall | |
-Wno-format # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int | |
-Wno-unused-function # we have some for the docs that aren't called | |
-Wno-maybe-uninitialized | |
) | |
# pull in common dependencies and additional uart hardware support | |
target_link_libraries(rp2040_fros_tmrisr_ex | |
FreeRTOS-Kernel | |
FreeRTOS-Kernel-Heap1 | |
pico_stdlib | |
pico_multicore | |
hardware_uart | |
) | |
# create map/bin/hex file etc. | |
pico_add_extra_outputs(rp2040_fros_tmrisr_ex) | |
# this will hopefully enable `printf` printouts via USB Serial ports | |
pico_enable_stdio_usb(rp2040_fros_tmrisr_ex 1) | |
# # enable usb output, disable uart output? | |
pico_enable_stdio_uart(rp2040_fros_tmrisr_ex 0) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FREERTOS_CONFIG_H | |
#define FREERTOS_CONFIG_H | |
// #pragma message("FREERTOS_CONFIG_H included!") | |
/* Use Pico SDK ISR handlers */ | |
#define vPortSVCHandler isr_svcall | |
#define xPortPendSVHandler isr_pendsv | |
#define xPortSysTickHandler isr_systick | |
/*----------------------------------------------------------- | |
* Application specific definitions. | |
* | |
* These definitions should be adjusted for your particular hardware and | |
* application requirements. | |
* | |
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE | |
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. | |
* | |
* See http://www.freertos.org/a00110.html | |
*----------------------------------------------------------*/ | |
/* Scheduler Related */ | |
#define configUSE_PREEMPTION 1 | |
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 | |
#define configUSE_TICKLESS_IDLE 0 | |
#define configCPU_CLOCK_HZ 133000000 | |
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) | |
#define configMAX_PRIORITIES 32 | |
#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 256 | |
#define configMAX_TASK_NAME_LEN 16 | |
#define configUSE_16_BIT_TICKS 0 | |
#define configIDLE_SHOULD_YIELD 1 | |
#define configUSE_TASK_NOTIFICATIONS 1 | |
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 3 | |
/* Synchronization Related */ | |
#define configUSE_MUTEXES 1 | |
#define configUSE_RECURSIVE_MUTEXES 1 | |
#define configUSE_APPLICATION_TASK_TAG 0 | |
#define configUSE_COUNTING_SEMAPHORES 1 | |
#define configQUEUE_REGISTRY_SIZE 8 | |
#define configUSE_QUEUE_SETS 1 | |
#define configUSE_TIME_SLICING 1 | |
#define configUSE_NEWLIB_REENTRANT 0 | |
#define configENABLE_BACKWARD_COMPATIBILITY 0 | |
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 | |
/* System */ | |
#define configSTACK_DEPTH_TYPE uint32_t | |
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t | |
/* Memory allocation related definitions. */ | |
#define configSUPPORT_STATIC_ALLOCATION 0 | |
#define configSUPPORT_DYNAMIC_ALLOCATION 1 | |
#define configTOTAL_HEAP_SIZE (128*1024) | |
#define configAPPLICATION_ALLOCATED_HEAP 0 | |
/* Hook function related definitions. */ | |
#define configUSE_IDLE_HOOK 0 | |
#define configUSE_TICK_HOOK 0 | |
#define configCHECK_FOR_STACK_OVERFLOW 2 | |
#define configUSE_MALLOC_FAILED_HOOK 1 | |
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 | |
/* Run time and task stats gathering related definitions. */ | |
#define configGENERATE_RUN_TIME_STATS 0 | |
#define configUSE_TRACE_FACILITY 1 | |
#define configUSE_STATS_FORMATTING_FUNCTIONS 1 // must be 1 in addition to configUSE_TRACE_FACILITY so we get vTaskList function | |
/* Co-routine related definitions. */ | |
#define configUSE_CO_ROUTINES 0 | |
#define configMAX_CO_ROUTINE_PRIORITIES 1 | |
/* Software timer related definitions. */ | |
#define configUSE_TIMERS 1 | |
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) | |
#define configTIMER_QUEUE_LENGTH 10 | |
#define configTIMER_TASK_STACK_DEPTH 1024 | |
/* Interrupt nesting behaviour configuration. */ | |
/* | |
#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor] | |
#define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application] | |
#define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application] | |
*/ | |
//#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0b01000000 // causes recompile, but not sure if it makes a difference on RP2040 at all | |
/* SMP port only */ | |
#define configNUM_CORES 2 | |
#define configTICK_CORE 0 // "Core in which tick should run" | |
#define configRUN_MULTIPLE_PRIORITIES 1 // must be 1 to use core affinity/"core exclusion" | |
#define configUSE_CORE_AFFINITY 1 // "configUSE_CORE_AFFINITY must be defined as 1 | |
// for vTaskCoreAffinitySet to be available." | |
/* RP2040 specific */ | |
#define configSUPPORT_PICO_SYNC_INTEROP 1 | |
#define configSUPPORT_PICO_TIME_INTEROP 1 | |
#include <assert.h> | |
/* Define to trap errors during development. */ | |
#define configASSERT(x) assert(x) | |
/* Set the following definitions to 1 to include the API function, or zero | |
to exclude the API function. */ | |
/* Optional functions - most linkers will remove unused functions anyway. */ | |
#define INCLUDE_vTaskPrioritySet 1 | |
#define INCLUDE_uxTaskPriorityGet 1 | |
#define INCLUDE_vTaskDelete 1 | |
#define INCLUDE_vTaskSuspend 1 | |
#define INCLUDE_xResumeFromISR 1 | |
#define INCLUDE_vTaskDelayUntil 1 | |
#define INCLUDE_vTaskDelay 1 | |
#define INCLUDE_xTaskGetSchedulerState 1 | |
#define INCLUDE_xTaskGetCurrentTaskHandle 1 | |
#define INCLUDE_uxTaskGetStackHighWaterMark 1 | |
#define INCLUDE_xTaskGetIdleTaskHandle 1 | |
#define INCLUDE_eTaskGetState 1 | |
#define INCLUDE_xEventGroupSetBitFromISR 1 | |
#define INCLUDE_xTimerPendFunctionCall 1 | |
#define INCLUDE_xTaskAbortDelay 1 | |
#define INCLUDE_xTaskGetHandle 1 | |
#define INCLUDE_xTaskResumeFromISR 1 | |
#define INCLUDE_xQueueGetMutexHolder 1 | |
/* A header file that defines trace macro can be included here. */ | |
#endif /* FREERTOS_CONFIG_H */ | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// made vs. pico-sdk commit 2062372; FreeRTOS smp branch commit a97741a08 | |
#include <inttypes.h> //PRIu64 | |
/* (FreeRTOS) Kernel includes. */ | |
#include <FreeRTOS.h> // Must come first. (this also includes the FreeRTOSConfig.h file in this dir) | |
#include <task.h> // RTOS task related API prototypes. // TaskHandle_t | |
#include <stdio.h> // as in pico-examples/hello_world/usb/hello_usb.c | |
#include "pico/stdlib.h" | |
#include "pico/multicore.h" // multicore_launch_core1 | |
#include "hardware/clocks.h" // clk_sys | |
#include "hardware/irq.h" // Pico SDK: UART0_IRQ, UART1_IRQ | |
#include "hardware/structs/rosc.h" // rosc_hw | |
#include <string.h> | |
// GP2 (pin 3) to duplicate the PICO_DEFAULT_LED_PIN, so we can capture it on scope | |
#define ISR_COPY_PIN 1 | |
#define LED_COPY_PIN 2 | |
// forward declares: | |
static void prvSetupHardware( void ); | |
static void setup_timer_isr( void ); | |
static void init_freertos_tasks( void ); | |
#define ALARM_NUM 2 | |
#define ALARM_IRQ TIMER_IRQ_2 | |
//~ #define USE_HARDWARE_ALARM_API | |
#ifndef USE_HARDWARE_ALARM_API | |
static void __not_in_flash_func(timer_alarm_isr)(void); | |
#else | |
static void __not_in_flash_func(timer_alarm_isr)(uint timer); | |
#endif | |
static void __not_in_flash_func(restart_timer_alarm)(void); | |
void led_task( void* pvParameters ); | |
volatile uint8_t timer_counter = 0; | |
volatile uint16_t last_data_result = 0; | |
// note: by default, configMAX_SYSCALL_INTERRUPT_PRIORITY is not defined at all: | |
#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY | |
#pragma message " configMAX_SYSCALL_INTERRUPT_PRIORITY is NOT defined!" | |
#endif | |
int main(void) { | |
prvSetupHardware(); | |
init_freertos_tasks(); | |
// Start the tasks and timers running. | |
vTaskStartScheduler(); | |
// should never reach here (FreeRTOS-SMP-Demos/FreeRTOS/Demo/CORTEX_M0+_RP2040/OnEitherCore/main.c) | |
panic_unsupported(); | |
//while(1){}; | |
} | |
////////////////////////////////////////////////////// | |
#ifndef USE_HARDWARE_ALARM_API | |
static void __not_in_flash_func(timer_alarm_isr)(void) { | |
#else | |
static void __not_in_flash_func(timer_alarm_isr)(uint timer) { | |
#endif | |
BaseType_t xHigherPriorityTaskWoken = pdFALSE; | |
gpio_put(ISR_COPY_PIN, 1); | |
// Clear the alarm irq | |
hw_clear_bits(&timer_hw->intr, 1u << ALARM_NUM); | |
timer_counter = (timer_counter + 1) % 10; | |
uint8_t randomnum = 0; | |
for (uint8_t i = 0; i < 8; i++) { | |
randomnum |= (rosc_hw->randombit << i); | |
} | |
last_data_result = (timer_counter << 8) | randomnum; | |
restart_timer_alarm(); | |
gpio_put(ISR_COPY_PIN, 0); | |
// switch context if necessary | |
if( xHigherPriorityTaskWoken ) { | |
// Actual macro used here is port specific. | |
//taskYIELD_FROM_ISR (); | |
portYIELD_FROM_ISR(xHigherPriorityTaskWoken); | |
} | |
//portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); | |
} | |
static void __not_in_flash_func(restart_timer_alarm)(void) { | |
static const uint32_t delay_us = 250; | |
#ifndef USE_HARDWARE_ALARM_API | |
// Alarm is only 32 bits so if trying to delay more | |
// than that need to be careful and keep track of the upper | |
// bits | |
uint64_t target = timer_hw->timerawl + delay_us; | |
// Write the lower 32 bits of the target time to the alarm which | |
// will arm it | |
timer_hw->alarm[ALARM_NUM] = (uint32_t) target; | |
#else | |
hardware_alarm_set_target(ALARM_NUM, make_timeout_time_us( delay_us ) ); | |
#endif | |
} | |
////////////////////////////////////////////////////// | |
// as in FreeRTOS-SMP-Demos\FreeRTOS\Demo\CORTEX_M0+_RP2040\OnEitherCore\main.c | |
static void prvSetupHardware( void ) { | |
set_sys_clock_pll(1596000000, 6, 2); // change sys clk to 133 MHz | |
// Set up PICO_DEFAULT_LED_PIN as output | |
gpio_init(PICO_DEFAULT_LED_PIN); | |
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); | |
gpio_put(PICO_DEFAULT_LED_PIN, 0); | |
// debug pins | |
gpio_init(ISR_COPY_PIN); | |
gpio_set_dir(ISR_COPY_PIN, GPIO_OUT); | |
gpio_put(ISR_COPY_PIN, 0); | |
gpio_init(LED_COPY_PIN); | |
gpio_set_dir(LED_COPY_PIN, GPIO_OUT); | |
gpio_put(LED_COPY_PIN, 0); | |
setup_timer_isr(); | |
// Set up USB serial port (printf over USB serial port) | |
stdio_init_all(); | |
} | |
static void setup_timer_isr( void ) { | |
// set up timer hw interrupt // pico-examples/blob/master/timer/timer_lowlevel/timer_lowlevel.c | |
// Enable the interrupt for our alarm (the timer outputs 4 alarm irqs) | |
hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM); | |
#ifndef USE_HARDWARE_ALARM_API | |
// Set irq handler for alarm irq // pico-examples/blob/master/timer/timer_lowlevel/timer_lowlevel.c | |
irq_set_exclusive_handler(ALARM_IRQ, timer_alarm_isr); | |
#else | |
hardware_alarm_claim(ALARM_NUM); // FreeRTOS/Demo/CORTEX_M0+_RP2040/Standard/IntQueueTimer.c | |
hardware_alarm_set_callback(ALARM_NUM, timer_alarm_isr); | |
#endif | |
// Enable the alarm irq - not here, from a task! | |
//irq_set_enabled(ALARM_IRQ, true); | |
// "Hardware priorities range from 0 (highest priority) to 255 (lowest priority) though only the top 2 bits are significant on ARM Cortex-M0+." | |
// attempt to assign a higher priority (lower priority number); available are: 0b11000000 = 192 = 0xc0; 0b10000000 = 128 = 0x80; 0b01000000 = 64 = 0x40; 0b00000000 = 0 = 0x00; | |
irq_set_priority(ALARM_IRQ, 0b01000000); | |
} | |
static void init_freertos_tasks( void ) { | |
// NOTE: FreeRTOS own "Tmr Svc" already has priority configMAX_PRIORITIES-1! | |
// should probably use less than that for our tasks: | |
TaskHandle_t xLedTaskHandle = NULL; // see https://www.freertos.org/a00125.html | |
// Create the task | |
xTaskCreate( | |
led_task, // The function that implements the task. | |
"LED_Task", // Text name for the task, just to help debugging. | |
configMINIMAL_STACK_SIZE, // The size (in words) of the stack that should be created for the task. | |
NULL, // A parameter that can be passed into the task. Not used here | |
1, // The priority to assign to the task. tskIDLE_PRIORITY (which is 0) is | |
// the lowest priority. configMAX_PRIORITIES-1 is the highest priority. | |
//NULL // Used to obtain a handle to the created task. When not used here, set to NULL. | |
&xLedTaskHandle // Used to obtain a handle to the created task. | |
); | |
configASSERT( xLedTaskHandle ); | |
vTaskSetTaskNumber(xLedTaskHandle, 1); | |
// run led_task on cpu core 1 | |
vTaskCoreAffinitySet( xLedTaskHandle, 0b10 ); | |
} | |
void led_task( void* pvParameters ) { | |
// start the timer interrupts and the timer | |
if (!(irq_is_enabled(ALARM_IRQ))) { | |
irq_set_enabled(ALARM_IRQ, true); | |
restart_timer_alarm(); | |
} | |
while (true) { | |
gpio_put(PICO_DEFAULT_LED_PIN, 1); | |
gpio_put(LED_COPY_PIN, 1); | |
vTaskDelay(500); // ms | |
gpio_put(PICO_DEFAULT_LED_PIN, 0); | |
gpio_put(LED_COPY_PIN, 0); | |
vTaskDelay(500); // ms | |
} | |
} | |
#if ( configCHECK_FOR_STACK_OVERFLOW > 0 ) | |
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ) { | |
configASSERT(0); | |
} | |
#endif | |
#if ( configUSE_MALLOC_FAILED_HOOK > 0 ) | |
void vApplicationMallocFailedHook( void ) { | |
configASSERT(0); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment