相关文章
FreeRTOS qemu mps2-an385 bsp 移植制作 :环境搭建篇
FreeRTOS qemu mps2-an385 bsp 移植制作 :系统启动篇
FreeRTOS qemu mps2-an385 bsp 移植制作 :系统运行篇
开发环境
-
Win10 64位 + VS Code,ssh 远程连接 ubuntu
-
VMware Workstation Pro 16 + Ubuntu 20.04
-
FreeRTOSv202212.01(备注:可以在 github 获取最新版本)
-
qemu qemu-system-arm mps2-an385 开发板,qemu 版本 QEMU emulator version 4.2.1 或更高
-
arm gcc 交叉编译工具链:当前使用 gcc 编译环境, gcc-arm-11.2-2022.02-x86_64-arm-none-eabi, gcc version 11.2.1 20220111
前言
-
前面的 FreeRTOS qemu mps2-an385 bsp 移植制作 :环境搭建篇 大体讲了一下环境搭建,初步配置了工程目录
-
FreeRTOS qemu mps2-an385 bsp 移植制作 :系统启动篇 配置了 VS Code gdb 调试环境,初步让MCU 启动,进入了启动入口函数
FreeRTOS qemu mps2-an385 bsp 移植制作 :系统运行篇 实现了 FreeRTOS 的运行,创建一个task 并成功运行
- 本篇继续优化,增加串口驱动,让系统运行时打印串口信息
串口驱动
-
qemu mps2-an385 的串口驱动相对简单,当前串口打印只需要关心串口的输出,串口的中断输入,待后续增加 shell 终端功能时再处理
-
创建
qemu_mps2/driver/drv_uart.c
,内容如下:
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "drv_uart.h"
#include "CMSDK_CM3.h"
#define DBG_BUFF_MAX_LEN 256
static char rt_log_buf[DBG_BUFF_MAX_LEN] = { 0 };
/* qemu uart dirver class */
struct uart_instance
{
const char *name;
CMSDK_UART_TypeDef *handle;
IRQn_Type irq_num;
int uart_index;
};
static struct uart_instance uart0_handle = { 0 };
static void uart_putc(uint8_t c)
{
uart0_handle.handle->DATA = c;
}
static int serial_put(const char *data, int length)
{
int size;
size = length;
while (length)
{
uart_putc(*data);
++ data;
-- length;
}
return size - length;
}
/* debug print */
int os_printf(const char *fmt, ...)
{
int length;
va_list args;
va_start(args, fmt);
length = vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
serial_put(rt_log_buf, length);
return length;
}
void UART0RX_Handler(void)
{
uint32_t irq_status = 0x00;
irq_status = uart0_handle.handle->INTCLEAR;
uart0_handle.handle->INTCLEAR = irq_status;
}
int uart_init(void)
{
uart0_handle.handle = CMSDK_UART0;
uart0_handle.uart_index = UART0RX_IRQn;
uart0_handle.name = "uart0";
uart0_handle.handle->BAUDDIV = 16; /* 115200bps */
uart0_handle.handle->CTRL = CMSDK_UART_CTRL_RXIRQEN_Msk | CMSDK_UART_CTRL_RXEN_Msk | CMSDK_UART_CTRL_TXEN_Msk;
NVIC_EnableIRQ(uart0_handle.irq_num);
uart0_handle.handle->STATE = 0;
return 0;
}
-
这里借助 C 库 函数
vsnprintf
,实现格式化输出,实现比较的简单,类似于printf
功能 -
创建
qemu_mps2/driver/drv_uart.h
串口头文件
#ifndef __DRV_UART_H__
#define __DRV_UART_H__
#include <stdint.h>
int uart_init(void);
int os_printf(const char *fmt, ...);
#endif //__DRV_UART_H__
修改 main.c 增加串口打印
- 在
qemu_mps2/application/main.c
中,再创建一个 task,注意 栈空间可以适当的加大,防止栈溢出引发异常
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>
#include <string.h>
#include "drv_uart.h"
#define TASK_TEST_PRIORITY (tskIDLE_PRIORITY + 6)
#define TASK_TEST2_PRIORITY (tskIDLE_PRIORITY + 8)
static void task_test_entry(void *pvParameters)
{
uint32_t cnt = 0;
os_printf("%s : enter\r\n", __func__);
while (1)
{
vTaskDelay(1000);
os_printf("%s : cnt %d\r\n", __func__, cnt++);
}
}
static void task_test2_entry(void *pvParameters)
{
uint32_t cnt = 0;
os_printf("%s : enter\r\n", __func__);
while (1)
{
vTaskDelay(2000);
os_printf("%s : cnt %d\r\n", __func__, cnt++);
}
}
void main( void )
{
uart_init();
os_printf("%s : enter\r\n", __func__);
xTaskCreate(task_test_entry, "task_test", 512, NULL, TASK_TEST_PRIORITY, NULL);
xTaskCreate(task_test2_entry, "task_test2", 512, NULL, TASK_TEST2_PRIORITY, NULL);
vTaskStartScheduler();
for( ;; );
}
- 串口输出信息
- 串口输出正常,两个任务轮流输出
小结
-
本篇主要实现
qemu mps2-an385
的串口输出打印功能,借助 C 库函数简单实现 -
后续可以增加串口的 shell 终端功能,到时候会利用起来串口的接收处理