OpenHarmony开发者论坛

标题: 【5】AT32F437 OpenHarmony轻量系统移植教程(2) [打印本页]

作者: 润开鸿_贾佳豪    时间: 昨天 10:16
标题: 【5】AT32F437 OpenHarmony轻量系统移植教程(2)
[md]开源地址: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](https://gitee.com/arterytek/AT32F435_437_Firmware_Library)获取

2.找到[at32f435_437_board.c](https://gitee.com/AT32437_OpenHa ... t32f435_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](https://gitee.com/AT32437_OpenHa ... 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](https://gitee.com/AT32437_OpenHa ... eos_m/src/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](https://gitee.com/AT32437_OpenHa ... liteos_m/src/main.c)的main.c里面初始化串口打印函数uart_print_init

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

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

2.找到[at32f435_437_board.c](https://gitee.com/AT32437_OpenHa ... t32f435_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](https://gitee.com/AT32437_OpenHa ... 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](https://gitee.com/AT32437_OpenHa ... eos_m/src/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](https://gitee.com/AT32437_OpenHa ... liteos_m/src/main.c)的main.c里面初始化串口打印函数uart_print_init

![alt text](./media/image-5.png)

### 4.添加at32f437驱动库

> 前面提到首先获取AT32F437的底层驱动源代码(Firmware Library),我们需要从官方托管的gitee仓库[AT32F435_437_Firmware_Library](https://gitee.com/arterytek/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](https://gitee.com/AT32437_OpenHa ... at32f435_437_conf.h)中添加
![alt text](./media/image-6.png)

```
#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](./media/image-7.png)

### 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](https://gitee.com/arterytek/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](https://gitee.com/AT32437_OpenHa ... at32f435_437_conf.h)中添加

![image.png](https://dl-harmonyos.51cto.com/i ... rocess=image/resize,w_820,h_630)

```
#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](https://dl-harmonyos.51cto.com/i ... rocess=image/resize,w_366,h_962)

### 5.内核子系统适配

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

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




欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5