【5】AT32F437 OpenHarmony轻量系统移植教程(2)

server/2024/9/23 20:04:26/

开源地址:https://gitee.com/AT32437_OpenHarmony

学习本文档的意义

1.学习移植OpenHarmony轻量系统到AT32全系列mcu上,本文档移植的具体型号为AT32F437ZMT7

2.学习OpenHarmony轻量系统开发

3.适配vprintf, vfprintf, printf, snprintf 和sprintf

1.首先获取AT32F437的底层驱动源代码(Firmware Library),我们需要从官方托管的gitee仓库AT32F435_437_Firmware_Library获取

2.找到at32f435_437_board.c文件,注释掉__io_putchar函数,使用fputc函数

// #if defined (__GNUC__) && defined (__clang__)
//   #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
// #else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
// #endif

再注释掉setvbuf函数,这个函数影响适配适配printf

/*** @brief  initialize uart* @param  baudrate: uart baudrate* @retval none*/
void uart_print_init(uint32_t baudrate)
{gpio_init_type gpio_init_struct;// #if defined (__GNUC__) && !defined (__clang__)
//   setvbuf(stdout, NULL, _IONBF, 0);               //printf函数有关
// #endif/* enable the uart and gpio clock */crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE);crm_periph_clock_enable(PRINT_UART_TX_GPIO_CRM_CLK, TRUE);

3.在/device/board/artery_board/atstartf437/liteos_m/config.gni新增_malloc_r, _realloc_r, _reallocf_r, _free_r, _memalign_r, 和 _malloc_usable_size_r函数的wrap链接选项。

board_ld_flags = [ # 链接选项,与厂商Makefile中的LDFLAGS变量对应。"-Xlinker","--gc-sections",# 需要的Linker 配置"--specs=nano.specs", # 为了使用printf函数"--specs=nosys.specs", # 为了使用printf函数"-Wl,--wrap=_calloc_r","-Wl,--wrap=_malloc_r","-Wl,--wrap=_realloc_r","-Wl,--wrap=_reallocf_r","-Wl,--wrap=_free_r","-Wl,--wrap=_memalign_r","-Wl,--wrap=_malloc_usable_size_r",
]

4.然后重写printf和sprintf函数,具体实现查看dprintf.c

#include <stdarg.h>
#include <stdio.h>
#include "securec.h"
#include "los_interrupt.h"unsigned int intSave = 0;//print函数的buffer大小
#define BUFSIZE  512 static void dputs(char const *s, int (*pFputc)(int n, FILE *cookie), void *cookie)
{intSave = LOS_IntLock();while (*s) {pFputc(*s++, cookie);}LOS_IntRestore(intSave);
}int printf(const char *__restrict __format, ...)
{char buf[BUFSIZE] = { 0 };int len;va_list ap;va_start(ap, __format);len = vsnprintf_s(buf, sizeof(buf), BUFSIZE - 1, __format, ap);va_end(ap);if(len > 0) {dputs(buf, fputc, 0);} else {dputs("printf error!\n", fputc, 0);}return len;
}

5.在main.c的main.c里面初始化串口打印函数uart_print_init

3.适配vprintf, vfprintf, printf, snprintf 和sprintf

1.首先获取AT32F437的底层驱动源代码(Firmware Library),我们需要从官方托管的gitee仓库AT32F435_437_Firmware_Library获取

2.找到at32f435_437_board.c文件,注释掉__io_putchar函数,使用fputc函数

// #if defined (__GNUC__) && defined (__clang__)
//   #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
// #else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
// #endif

再注释掉setvbuf函数,这个函数影响适配适配printf

/*** @brief  initialize uart* @param  baudrate: uart baudrate* @retval none*/
void uart_print_init(uint32_t baudrate)
{gpio_init_type gpio_init_struct;// #if defined (__GNUC__) && !defined (__clang__)
//   setvbuf(stdout, NULL, _IONBF, 0);               //printf函数有关
// #endif/* enable the uart and gpio clock */crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE);crm_periph_clock_enable(PRINT_UART_TX_GPIO_CRM_CLK, TRUE);

3.在/device/board/artery_board/atstartf437/liteos_m/config.gni新增_malloc_r, _realloc_r, _reallocf_r, _free_r, _memalign_r, 和 _malloc_usable_size_r函数的wrap链接选项。

board_ld_flags = [ # 链接选项,与厂商Makefile中的LDFLAGS变量对应。"-Xlinker","--gc-sections",# 需要的Linker 配置"--specs=nano.specs", # 为了使用printf函数"--specs=nosys.specs", # 为了使用printf函数"-Wl,--wrap=_calloc_r","-Wl,--wrap=_malloc_r","-Wl,--wrap=_realloc_r","-Wl,--wrap=_reallocf_r","-Wl,--wrap=_free_r","-Wl,--wrap=_memalign_r","-Wl,--wrap=_malloc_usable_size_r",
]

4.然后重写printf和sprintf函数,具体实现查看dprintf.c

#include <stdarg.h>
#include <stdio.h>
#include "securec.h"
#include "los_interrupt.h"unsigned int intSave = 0;//print函数的buffer大小
#define BUFSIZE  512 static void dputs(char const *s, int (*pFputc)(int n, FILE *cookie), void *cookie)
{intSave = LOS_IntLock();while (*s) {pFputc(*s++, cookie);}LOS_IntRestore(intSave);
}int printf(const char *__restrict __format, ...)
{char buf[BUFSIZE] = { 0 };int len;va_list ap;va_start(ap, __format);len = vsnprintf_s(buf, sizeof(buf), BUFSIZE - 1, __format, ap);va_end(ap);if(len > 0) {dputs(buf, fputc, 0);} else {dputs("printf error!\n", fputc, 0);}return len;
}

5.在main.c的main.c里面初始化串口打印函数uart_print_init

alt text

4.添加at32f437驱动库

前面提到首先获取AT32F437的底层驱动源代码(Firmware Library),我们需要从官方托管的gitee仓库AT32F435_437_Firmware_Library获取。

把原厂的驱动文件放置在device\soc\artery\at32f4xx\libraries和device\soc\artery\at32f4xx\liteos_m目录下面,为了消除编译报错需要进行一些修改

1.device/soc/artery/at32f4xx/liteos_m/include/at32f435_437.h中typedef int32_t INT32;typedef uint32_t UINT32;注释掉


//typedef int32_t  INT32;
typedef int16_t  INT16;
typedef int8_t   INT8;
//typedef uint32_t UINT32;

2.device/soc/artery/at32f4xx/liteos_m/include/at32f435_437.h中,FALSE修改为AT_FALSE,TRUE修改为AT_TRUE,避开宏的重定义

typedef enum {AT_FALSE = 0, AT_TRUE = !AT_FALSE} confirm_state; 

3.device/soc/artery/at32f4xx/libraries/drivers/inc/at32f435_437_def.h中注释掉


//#define UNUSED(x)                        (void)x /* to avoid gcc/g++ warnings */

4.device/soc/artery/at32f4xx/libraries/drivers/src/at32f435_437_crm.c中注释DUMMY_NOP();这个函数

/*** @brief  select system clock source* @param  value*         this parameter can be one of the following values:*         - CRM_SCLK_HICK*         - CRM_SCLK_HEXT*         - CRM_SCLK_PLL* @retval none*/
void crm_sysclk_switch(crm_sclk_type value)
{CRM->cfg_bit.sclksel = value;//DUMMY_NOP();
}

5.device/soc/artery/at32f4xx/liteos_m/include/at32f435_437_board.h中 添加 #define AT_START_F437_V1

6.device/soc/artery/at32f4xx/liteos_m/include/at32f435_437.h中相关宏为修改AT32F437ZMT7,相关代码如下

/*** tip: to avoid modifying this file each time you need to switch between these*      devices, you can define the device in your toolchain compiler preprocessor.*/#define AT32F437xx/*** define with package*/#define AT32F437Zx/*** define with memory density*/#define AT32F437xM

7.device/soc/artery/at32f4xx/liteos_m/include/at32f435_437_conf.h中添加

alt text

#if !defined  TRUE
#define TRUE  AT_TRUE
#endif
#if !defined  FALSE
#define FALSE AT_FALSE
#endif

8.所有的at32437驱动文件都要包含头文件#include "los_compiler.h",为了解决UNUSED没有定义的问题

alt text

5.内核子系统适配

在vendor\artery\AT-START-F437\config.json添加内核子系统及相关配置,如下所示:

    "subsystems": [ {"subsystem": "kernel","components": [{"component": "liteos_m"}]}],

4.添加at32f437驱动库

前面提到首先获取AT32F437的底层驱动源代码(Firmware Library),我们需要从官方托管的gitee仓库AT32F435_437_Firmware_Library获取。

把原厂的驱动文件放置在device\soc\artery\at32f4xx\libraries和device\soc\artery\at32f4xx\liteos_m目录下面,为了消除编译报错需要进行一些修改

1.device/soc/artery/at32f4xx/liteos_m/include/at32f435_437.h中typedef int32_t INT32;typedef uint32_t UINT32;注释掉


//typedef int32_t  INT32;
typedef int16_t  INT16;
typedef int8_t   INT8;
//typedef uint32_t UINT32;

2.device/soc/artery/at32f4xx/liteos_m/include/at32f435_437.h中,FALSE修改为AT_FALSE,TRUE修改为AT_TRUE,避开宏的重定义

typedef enum {AT_FALSE = 0, AT_TRUE = !AT_FALSE} confirm_state; 

3.device/soc/artery/at32f4xx/libraries/drivers/inc/at32f435_437_def.h中注释掉


//#define UNUSED(x)                        (void)x /* to avoid gcc/g++ warnings */

4.device/soc/artery/at32f4xx/libraries/drivers/src/at32f435_437_crm.c中注释DUMMY_NOP();这个函数

/*** @brief  select system clock source* @param  value*         this parameter can be one of the following values:*         - CRM_SCLK_HICK*         - CRM_SCLK_HEXT*         - CRM_SCLK_PLL* @retval none*/
void crm_sysclk_switch(crm_sclk_type value)
{CRM->cfg_bit.sclksel = value;//DUMMY_NOP();
}

5.device/soc/artery/at32f4xx/liteos_m/include/at32f435_437_board.h中 添加 #define AT_START_F437_V1

6.device/soc/artery/at32f4xx/liteos_m/include/at32f435_437.h中相关宏为修改AT32F437ZMT7,相关代码如下

/*** tip: to avoid modifying this file each time you need to switch between these*      devices, you can define the device in your toolchain compiler preprocessor.*/#define AT32F437xx/*** define with package*/#define AT32F437Zx/*** define with memory density*/#define AT32F437xM

7.device/soc/artery/at32f4xx/liteos_m/include/at32f435_437_conf.h中添加

image.png

#if !defined  TRUE
#define TRUE  AT_TRUE
#endif
#if !defined  FALSE
#define FALSE AT_FALSE
#endif

8.所有的at32437驱动文件都要包含头文件#include "los_compiler.h",为了解决UNUSED没有定义的问题

image.png

5.内核子系统适配

在vendor\artery\AT-START-F437\config.json添加内核子系统及相关配置,如下所示:

    "subsystems": [ {"subsystem": "kernel","components": [{"component": "liteos_m"}]}],

http://www.ppmy.cn/server/120960.html

相关文章

Android外接USB扫码枪

前言 公司的设备以前接入的都是串口的扫码头&#xff0c;优点是直接通过串口读取流里面的数据就OK了&#xff0c;缺点是你需要知道每一款扫码器的型号以获取波特率及Android设备的串口地址。因为现在usb扫码器越来越方便且即插即用&#xff0c;不需要额外供电以及价格便宜等特…

【60天备战2024年11月软考高级系统架构设计师——第21天:系统架构设计原则——高内聚低耦合】

在软件架构设计中&#xff0c;“高内聚低耦合”是至关重要的设计原则&#xff0c;它能够提高系统的可维护性、可扩展性和灵活性。理解并实践这一原则可以帮助系统架构师在设计过程中构建出健壮的系统。 什么是高内聚&#xff1f; 高内聚指的是模块内部的功能相关性强&#xf…

【Docker】基于docker compose部署artifactory-cpp-ce服务

基于docker compose部署artifactory-cpp-ce服务 1 环境准备2 必要文件创建与编写3 拉取镜像-创建容器并后台运行4 访问JFog Artifactory 服务 1 环境准备 docker 以及其插件docker compose &#xff0c;我使用的版本如下图所示&#xff1a; postgresql 的jdbc驱动, 我使用的是…

【艾思科蓝】“从零到一:使用IntelliJ IDEA打造你的梦幻HTML项目“

【JPCS独立出版】2024年工业机器人与先进制造技术国际学术会议&#xff08;IRAMT 2024&#xff09;_艾思科蓝_学术一站式服务平台 更多学术会议请看 学术会议-学术交流征稿-学术会议在线-艾思科蓝 目录 引言&#xff1a;为何选择IntelliJ IDEA&#xff1f; 第一步&#xff1a…

分布式系统实战经验

分布式系统是现代软件架构的核心部分&#xff0c;它通过多个计算节点协同工作来处理大规模数据和请求&#xff0c;提供高可用性、可扩展性和容错能力。在实际开发和运维中&#xff0c;构建分布式系统需要考虑多方面的挑战。以下是一些在分布式系统中的实战经验&#xff1a; 1.…

Elasticsearch 分片迁移与移除集群节点操作

Elasticsearch 分片迁移与移除集群节点操作 问题背景 在单台服务器上部署了 7 个 Elasticsearch 节点&#xff0c;分别为 es-node1 到 es-node7&#xff0c;端口从 9201 到 9207。每个节点都承载大量数据&#xff0c;但没有设置副本分片。由于多个节点共享同一台服务器的硬件…

vue 中互相不关联的两个组件怎么进行通信(数据传输)

1、Vuex Vuex 是 Vue 官方的状态管理模式与库。通过使用 Vuex&#xff0c;可以将组件间共享的数据存储在一个全局的状态树中&#xff0c;任何组件都可以读取这个状态&#xff0c;通过提交 mutations 或 dispatch actions 来修改状态。 2、Event Bus (事件总线) 创建一个全局的…

Redis面试常见问题

1.Redis的常用类型 Redis常用的类型也就那五个&#xff0c;我想经常看各大八股文的小伙伴&#xff0c;应该都熟练于心了吧&#xff01;它们分别是String、Hash、List、Set、ZSet&#xff1b;接下来跟我一起分析这五大常用类型 String数据类型格式&#xff1a;key valueHash数…