当前位置:网站首页>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;
}
边栏推荐
- Oracle checkpoint queue - Analysis of the principle of instance crash recovery
- Experienced inductance manufacturers tell you what makes the inductance noisy. Inductance noise is a common inductance fault. If the used inductance makes noise, you don't have to worry. You just need
- Blocking of concurrency control
- Common interview questions of JVM manufacturers
- Text组件新增内容通过tag_config设置前景色、背景色
- 科技云报道:算力网络,还需跨越几道坎?
- Form artifact
- K210 learning notes (IV) k210 runs multiple models at the same time
- Concurrency control of performance tuning methodology
- Matlab draws a cute fat doll
猜你喜欢
Leetcode simple question ring and rod
Database tuning solution
Countdown to 92 days, the strategy for the provincial preparation of the Blue Bridge Cup is coming~
ICMP 介绍
Overview of database recovery
database mirroring
Drawing HSV color wheel with MATLAB
[Yugong series] go teaching course in July 2022 004 go code Notes
Wonderful review of the digital Expo | highlight scientific research strength, and Zhongchuang computing power won the digital influence enterprise award
Technology cloud report: how many hurdles does the computing power network need to cross?
随机推荐
了解 Android Kotlin 中 DataStore 的基本概念以及为什么应该停止在 Android 中使用 SharedPreferences
Blocking of concurrency control
Summary of El and JSTL precautions
Hysbz 2243 staining (tree chain splitting)
Shell script, awk uses if, for process control
The difference between MVVM and MVC
AD637使用筆記
Cross end solutions to improve development efficiency
A substring with a length of three and different characters in the leetcode simple question
【愚公系列】2022年7月 Go教学课程 004-Go代码注释
MMAP learning
U盘的文件无法删除文件怎么办?Win11无法删除U盘文件解决教程
Implementation technology of recovery
Daily question brushing record (XIV)
Database tuning solution
poj 3237 Tree(树链拆分)
Livelocks and deadlocks of concurrency control
Codeforces 12D ball tree array simulation 3 sorting elements
Comment développer un plug - in d'applet
DataGrid directly edits and saves "design defects"