当前位置:网站首页>Platformio create libopencm3 + FreeRTOS project
Platformio create libopencm3 + FreeRTOS project
2022-07-05 22:11:00 【IOsetting】
PlatformIO: libopencm3 + FreeRTOS
The following steps are based on common Bluepill STM32F103C8T6, Also applicable to other libopencm3 Supported by MCU model
Scheme 1 : Copy only the files you need
- stay PlatformIO in , Board choice Bluepill F103C8, Framework choice libopencm3, Create project
- In the project lib Create a new directory FreeRTOS
- Unzip the latest FreeRTOS
- Copy FreeRTOS/Source/ Under the table of contents , except portable All other files and directories except directory , to lib/FreeRTOS Next
- Copy FreeRTOS/Source/portable/GCC/ARM_CM3 All files in the directory (port.c, portmacro.h), to lib/FreeRTOS Next
- Copy FreeRTOS/Source/portable/Common All files in the directory (mpu_wrappers.c), to lib/FreeRTOS Next
- Copy FreeRTOS/Source/portable/MemMang Under the table of contents heap_4.c, to lib/FreeRTOS Next
- Copy FreeRTOSConfig.h, to lib/FreeRTOS/include Next
- To write src/main.c
After completion, the directory structure should be
├── include
│ └── README
├── lib
│ ├── FreeRTOS
│ │ ├── croutine.c
│ │ ├── event_groups.c
│ │ ├── heap_4.c
│ │ ├── include
│ │ │ ├── atomic.h
│ │ │ ├── croutine.h
│ │ │ ├── deprecated_definitions.h
│ │ │ ├── event_groups.h
│ │ │ ├── FreeRTOSConfig.h
│ │ │ ├── FreeRTOS.h
│ │ │ ├── list.h
│ │ │ ├── message_buffer.h
│ │ │ ├── mpu_prototypes.h
│ │ │ ├── mpu_wrappers.h
│ │ │ ├── portable.h
│ │ │ ├── projdefs.h
│ │ │ ├── queue.h
│ │ │ ├── semphr.h
│ │ │ ├── stack_macros.h
│ │ │ ├── StackMacros.h
│ │ │ ├── stdint.readme
│ │ │ ├── stream_buffer.h
│ │ │ ├── task.h
│ │ │ └── timers.h
│ │ ├── list.c
│ │ ├── mpu_wrappers.c
│ │ ├── port.c
│ │ ├── portmacro.h
│ │ ├── queue.c
│ │ ├── stream_buffer.c
│ │ ├── tasks.c
│ │ └── timers.c
│ └── README
├── platformio.ini
├── README.md
├── src
│ └── main.c
└── test
└── README
Option two : complete FreeRTOS, Use library.json
- stay PlatformIO in , Board choice Bluepill F103C8, Framework choice libopencm3, Create project
- In the project lib Create a new directory FreeRTOS
- Unzip the latest FreeRTOS
- Copy FreeRTOS/Source/ All files in the directory to lib/FreeRTOS Next
- Copy FreeRTOS/Source/portable/GCC/ARM_CM3 Under the table of contents portmacro.h to lib/FreeRTOS Next , because library.json Multiple... Are not supported yet include route
- Copy FreeRTOSConfig.h, to lib/FreeRTOS Next
- lib/FreeRTOS Add below library.json
- To write src/main.c
library.json The contents are as follows , Include only what you need c file
{
"name": "FreeRTOS",
"version": "10.4.6",
"build": {
"srcFilter": [
"+<*.c>",
"+<portable/GCC/ARM_CM3/port.c>",
"+<portable/MemMang/heap_4.c>"
]
}
}
If it's multi-core MCU, Need to include again mpu_wrappers.c, about F103C8 Not really
"+<portable/Common/mpu_wrappers.c>",
After completion, the directory structure is
├── include
│ └── README
├── lib
│ ├── FreeRTOS
│ │ ├── croutine.c
│ │ ├── event_groups.c
│ │ ├── FreeRTOSConfig.h
│ │ ├── include
│ │ ├── library.json
│ │ ├── list.c
│ │ ├── miniprintf.c
│ │ ├── miniprintf.h
│ │ ├── portable
│ │ ├── portmacro.h
│ │ ├── queue.c
│ │ ├── stream_buffer.c
│ │ ├── tasks.c
│ │ └── timers.c
│ └── README
├── platformio.ini
├── README.md
├── src
│ └── main.c
└── test
└── README
FreeRTOSConfig.h Function name fits
stay libopencm3/lib/cm3/vector.c in , Defined .sv_call,.pend_sv and .systick Processing function of ,
/* Those are defined only on CM3 or CM4 */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
.memory_manage_fault = mem_manage_handler,
.bus_fault = bus_fault_handler,
.usage_fault = usage_fault_handler,
.debug_monitor = debug_monitor_handler,
#endif
.sv_call = sv_call_handler,
.pend_sv = pend_sv_handler,
.systick = sys_tick_handler,
.irq = {
IRQ_HANDLERS
}
};
These function names are similar to FreeRTOS The function names in are inconsistent , It needs to be associated . Using macro replacement is more efficient than using function forwarding , So in FreeRTOSConfig.h The following definitions need to be added , otherwise FreeRTOS Not working properly
/** * In libopencm3/lib/cm3/vector.c, these 3 handlers(right side) are for .sv_call,.pend_sv and .systick * These macro will rename the methods in port.c to make it work, more efficient than wrapped by method */
#define vPortSVCHandler sv_call_handler
#define xPortPendSVHandler pend_sv_handler
#define xPortSysTickHandler sys_tick_handler
Sample code
Use Queue Of UART Send and receive
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/cm3/nvic.h>
#define mainECHO_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
static QueueHandle_t uart_txq; // TX queue for UART
/* * Handler in case our application overflows the stack */
void vApplicationStackOverflowHook(
TaskHandle_t xTask __attribute__((unused)),
char *pcTaskName __attribute__((unused))) {
for (;;);
}
void usart1_isr(void) {
uint8_t data;
/* Check if we were called because of RXNE. */
if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
((USART_SR(USART1) & USART_SR_RXNE) != 0)) {
/* Retrieve the data from the peripheral. */
data = usart_recv(USART1);
xQueueSendFromISR(uart_txq, &data, NULL);
}
}
static void gpio_setup(void) {
// GPIO PB12,PC13:
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_GPIOC);
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
// Turn LED off
gpio_set(GPIOB, GPIO12);
gpio_set(GPIOC, GPIO13);
rcc_periph_clock_enable(RCC_GPIOA);
gpio_set_mode(GPIOA,GPIO_MODE_OUTPUT_50_MHZ,GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,GPIO_USART1_TX);
gpio_set_mode(GPIOA,GPIO_MODE_OUTPUT_50_MHZ,GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,GPIO11);
gpio_set_mode(GPIOA,GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT,GPIO_USART1_RX);
gpio_set_mode(GPIOA,GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT,GPIO12);
}
/********************************************************************* * Configure and initialize USART1: *********************************************************************/
static void
uart_setup(void) {
rcc_periph_clock_enable(RCC_USART1);
usart_set_baudrate(USART1,115200);
usart_set_databits(USART1,8);
usart_set_stopbits(USART1,USART_STOPBITS_1);
usart_set_mode(USART1,USART_MODE_TX_RX);
usart_set_parity(USART1,USART_PARITY_NONE);
usart_set_flow_control(USART1,USART_FLOWCONTROL_NONE);
usart_enable(USART1);
nvic_enable_irq(NVIC_USART1_IRQ);
usart_enable_rx_interrupt(USART1);
// Create a queue for data to transmit from UART
uart_txq = xQueueCreate(256,sizeof(char));
}
static void uart_puts(const char *s) {
for ( ; *s; ++s ) {
// blocks when queue is full
xQueueSend(uart_txq,s,portMAX_DELAY);
}
}
/********************************************************************* * USART Task: *********************************************************************/
static void uart_task(void *args __attribute__((unused))) {
char ch;
for (;;) {
// Receive char to be TX
if ( xQueueReceive(uart_txq,&ch,500) == pdPASS ) {
// if not tx data buffer empty
while ( !usart_get_flag(USART1,USART_SR_TXE) )
taskYIELD(); // Yield until ready
usart_send(USART1,ch);
}
// Toggle LED to show signs of life
gpio_toggle(GPIOB,GPIO12);
gpio_toggle(GPIOC,GPIO13);
}
}
/********************************************************************* * Demo Task: * Simply queues up two line messages to be TX, one second * apart. *********************************************************************/
static void demo_task(void *args __attribute__((unused))) {
for (;;) {
uart_puts("Now this is a message..\n\r");
uart_puts(" sent via FreeRTOS queues.\n\n\r");
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
/********************************************************************* * Main program & scheduler: *********************************************************************/
int main(void) {
rcc_clock_setup_in_hse_8mhz_out_72mhz(); // CPU clock is 72 MHz
gpio_setup();
uart_setup();
xTaskCreate(uart_task,"UART",100,NULL,configMAX_PRIORITIES-1,NULL);
xTaskCreate(demo_task,"DEMO",100,NULL,configMAX_PRIORITIES-2,NULL);
vTaskStartScheduler();
for (;;);
return 0;
}
边栏推荐
- Microservice link risk analysis
- Leetcode simple question: find the nearest point with the same X or Y coordinate
- Did you brush the real title of the blue bridge cup over the years? Come here and teach you to counter attack!
- 【愚公系列】2022年7月 Go教学课程 004-Go代码注释
- What if the files on the USB flash disk cannot be deleted? Win11 unable to delete U disk file solution tutorial
- Evolution of large website architecture and knowledge system
- Drawing HSV color wheel with MATLAB
- 了解 Android Kotlin 中 DataStore 的基本概念以及为什么应该停止在 Android 中使用 SharedPreferences
- Daily question brushing record (XIV)
- The real situation of programmers
猜你喜欢
What if win11 is missing a DLL file? Win11 system cannot find DLL file repair method
Wonderful review of the digital Expo | highlight scientific research strength, and Zhongchuang computing power won the digital influence enterprise award
装饰器学习01
[Yugong series] go teaching course 003-ide installation and basic use in July 2022
Oracle triggers
Win11缺少dll文件怎么办?Win11系统找不到dll文件修复方法
多家呼吸机巨头产品近期被一级召回 呼吸机市场仍在增量竞争
Unique occurrence times of leetcode simple questions
Leetcode simple question: find the nearest point with the same X or Y coordinate
Web3为互联网带来了哪些改变?
随机推荐
The simple problem of leetcode is to split a string into several groups of length K
Matlab | app designer · I used Matlab to make a real-time editor of latex formula
Leetcode simple question check whether all characters appear the same number of times
如何开发引入小程序插件
Implementing Lmax disruptor queue from scratch (IV) principle analysis of multithreaded producer multiproducersequencer
Server optimization of performance tuning methodology
Oracle triggers
Countdown to 92 days, the strategy for the provincial preparation of the Blue Bridge Cup is coming~
等到产业互联网时代真正发展成熟,我们将会看待一系列的新产业巨头的出现
Talking about MySQL index
Win11缺少dll文件怎么办?Win11系统找不到dll文件修复方法
科技云报道:算力网络,还需跨越几道坎?
Advantages and disadvantages of the "Chris Richardson microservice series" microservice architecture
AD637使用笔记
A long's perception
Livelocks and deadlocks of concurrency control
Analyse des risques liés aux liaisons de microservices
了解 Android Kotlin 中 DataStore 的基本概念以及为什么应该停止在 Android 中使用 SharedPreferences
The new content of the text component can be added through the tag_ Config set foreground and background colors
从零开始实现lmax-Disruptor队列(四)多线程生产者MultiProducerSequencer原理解析