相关文章
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 移植制作 :环境搭建篇 大体讲了一下环境搭建,初步配置了工程目录
-
本篇继续优化,然后配置 VS Code gdb 调试,让系统启动起来
目录调整
- 本篇为了系统的介绍 FreeRTOS 的整个移植过程,暂时使用现有的 FreeRTOS Demo,所以
main.c
暂时写个 空的 main 函数即可
- main.c
#include <FreeRTOS.h>
#include <FreeRTOSConfig.h>int main(void)
{return 0;
}
FreeRTOS hook 函数
-
在 BSP 移植时,需要用户实现一些系统钩子函数(Hook),可以全部改为空函数
-
新建 port.c 文件,放在
qemu_mps2/application/port.c
#include <FreeRTOS.h>
#include <task.h>
#include <FreeRTOSConfig.h>void vAssertCalled(void)
{while (1);
}void vApplicationTickHook(void)
{
}void vApplicationIdleHook(void)
{
}void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize)
{
}void vApplicationGetTimerTaskMemory(StaticTask_t ** ppxTimerTaskTCBBuffer,StackType_t ** ppxTimerTaskStackBuffer,uint32_t * pulTimerTaskStackSize)
{
}void vApplicationMallocFailedHook(void)
{
}
Makefile 构建文件
-
当前使用 gcc 交叉编译的方式,所以创建 Makefile,
qemu_mps2/Makefile
,用于 make 编译构建 -
产物:
qemu_mps2.elf
OUTPUT_DIR := ./output
IMAGE := qemu_mps2.elfKERNEL_ROOT = ./..
#CROSS_COMPILE := /home/rtt/linux/tools/gcc-arm-none-eabi-10-2020-q4-major/bin
CROSS_COMPILE = /home/zhangsz/linux/tools/gcc-arm-11.2-2022.02-x86_64-arm-none-eabi/bin/CC = $(CROSS_COMPILE)/arm-none-eabi-gcc
LD = $(CROSS_COMPILE)/arm-none-eabi-gcc
SIZE = $(CROSS_COMPILE)/arm-none-eabi-size
MAKE = makeCFLAGS += $(INCLUDE_DIRS) -nostartfiles -ffreestanding -mthumb -mcpu=cortex-m3 \-Wall -msoft-float -g -O0 -ffunction-sections -fdata-sections \-std=gnu99 \LDFLAGS=-mthumb \-mcpu=cortex-m3 \-mlittle-endian \-ffreestanding \-specs=nano.specs \-specs=nosys.specs \-specs=rdimon.specs \-T$(LINK_SCRIPTS) \-Wl,-Map=qemu_mps2.mapKERNEL_DIR = $(KERNEL_ROOT)/Source
KERNEL_PORT_DIR += $(KERNEL_DIR)/portable/GCC/ARM_CM3INCLUDE_DIRS += -I$(KERNEL_DIR)/include \-I$(KERNEL_DIR)/portable/GCC/ARM_CM3SOURCE_FILES += $(KERNEL_DIR)/tasks.c
SOURCE_FILES += $(KERNEL_DIR)/list.c
SOURCE_FILES += $(KERNEL_DIR)/queue.c
SOURCE_FILES += $(KERNEL_DIR)/timers.c
SOURCE_FILES += $(KERNEL_DIR)/event_groups.c
SOURCE_FILES += $(KERNEL_DIR)/stream_buffer.c
SOURCE_FILES += $(KERNEL_DIR)/portable/MemMang/heap_4.c
SOURCE_FILES += $(KERNEL_DIR)/portable/GCC/ARM_CM3/port.cDEMO_ROOT = $(KERNEL_ROOT)
DEMO_PROJECT = $(DEMO_ROOT)/qemu_mps2
INCLUDE_DIRS += -I$(DEMO_PROJECT) \-I$(DEMO_PROJECT)/application \-I$(DEMO_PROJECT)/CMSIS/Core/Include \-I$(DEMO_PROJECT)/CMSDK_CM3/IncludeSOURCE_FILES += $(DEMO_PROJECT)/application/main.c
SOURCE_FILES += $(DEMO_PROJECT)/CMSDK_CM3/Source/system_CMSDK_CM3.c
SOURCE_FILES += $(DEMO_PROJECT)/application/port.cASM_OBJS = $(DEMO_PROJECT)/CMSDK_CM3/Source/GCC/startup_CMSDK_CM3.oAPP_OBJS=$(patsubst %.c, %.o, $(SOURCE_FILES))LINK_SCRIPTS = $(DEMO_PROJECT)/CMSDK_CM3/Source/GCC/gcc_arm.ldall: app@echo "---- build end ----".c.o:$(CC) -c $^ -o $@ $(CFLAGS).S.o:$(CC) -c $^ -o $@ $(CFLAGS)app : $(APP_OBJS) $(ASM_OBJS)$(CC) $^ -o $(IMAGE) $(LDFLAGS)clean :rm -f $(APP_OBJS)rm -f $(ASM_OBJS)rm -f $(IMAGE)export CFLAGS CC
编译
- 进入 bsp
qemu_mps2
目录下,可以通过make
命令进行编译
device 设置
- 初次编译会报错,需要定义 芯片的型号
- 解决方法:
qemu_mps2/CMSDK_CM3/Source/system_CMSDK_CM3.c
中添加#define CMSDK_CM3
#ifndef CMSDK_CM3
#define CMSDK_CM3
#endif
FreeRTOS 的 Hook 函数未定义
- 这里需要上面创建的
port.c
实现几个未定义的hook 函数,可以为空,然后让 port.c 加入Makefile,参与编译
启动文件
-
编译通过了,可以开始调试了,这里开始讲一下 启动文件
-
MCU 第一个执行的不是 main 函数,而是复位:
Reset_Handler
-
当前 qemu
mps2-an385
启动文件是:qemu_mps2/CMSDK_CM3/Source/GCC/startup_CMSDK_CM3.S
-
像 STM32,除了系统的启动文件,还有一个 时钟配置相关的文件,当前 qemu
mps2-an385
的是qemu_mps2/CMSDK_CM3/Source/system_CMSDK_CM3.c
链接脚本
- 嵌入式开发,需要了解基本的链接脚本,当前 qemu
mps2-an385
的链接脚本使用qemu_mps2/CMSDK_CM3/Source/GCC/gcc_arm.ld
VS Code gdb 调试
-
在没有任何驱动的支持下, 编译后的 文件是否可以执行呢?其实 启动文件与链接脚本,已经让 MCU 可以启动了
-
VS Code gdb 调试配置文件,VS Code 调试按钮,如果没有就创建一个
.vscode/launch.json
{// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387"version": "0.2.0","configurations": [{"name": "qemu_mps2","type": "cppdbg","request": "launch","program": "${workspaceFolder}/qemu_mps2/qemu_mps2.elf","cwd": "${workspaceFolder}",//"miDebuggerPath": "/home/rtt/tools/gcc-arm-none-eabi-7-2018-q2-update/bin/arm-none-eabi-gdb-py","miDebuggerPath": "/home/zhangsz/linux/tools/gcc-arm-11.2-2022.02-x86_64-arm-none-eabi/bin/arm-none-eabi-gdb","miDebuggerServerAddress": "localhost:1234","stopAtEntry": true,//"preLaunchTask": "Run QEMU"}]
}
qemu 启动与调试脚本
- 新建 qemu.sh ,并设置执行权限:
chmod +x qemu.sh
#!/bin/bash
qemu-system-arm -machine mps2-an385 \-cpu cortex-m3 \-kernel ./qemu_mps2.elf \-monitor none \-nographic
- 新建
qemu-debug.sh
,并设置执行权限:chmod +x qemu-debug.sh
#!/bin/bash
qemu-system-arm -machine mps2-an385 \-cpu cortex-m3 \-kernel ./qemu_mps2.elf \-monitor none \-nographic \-s -S
-
备注:当前 FreeRTOS 无法正常运行,所以执行
./qemu.sh
没有任何的反应,会卡住 -
执行
./qemu-debug.sh
,此时进入 调试模式,卡住 -
点击 VS Code 调试按钮,进入调试
-
正常启动时,会进入
qemu_mps2/CMSDK_CM3/Source/GCC/startup_CMSDK_CM3.S
的Reset_Handler
函数,这个 系统的启动入口,第一个执行的函数 -
开始执行
SystemInit
,这个函数在qemu_mps2/CMSDK_CM3/Source/system_CMSDK_CM3.c
-
此时调试按 【单步】,可以进入
SystemInit
,
-
点击 调试 工具 的 【单步】,或者 快捷键【F11】
-
开发板启动了
小结
-
本篇注意讲解 启动文件、连接脚本、FreeRTOS 启动前期的 开发板启动、VS Code gdb 调试
-
系统环境准备好,接下来就可以开始 FreeRTOS 的相关适配、驱动的适配(当前主要是串口)