• 物联网工程师开发服务平台

移植 MiCO 至 STM32F407

本文主要讲述如何在 STM32F407 上 移植 MiCO 系统,以此介绍:如何将 MiCO 系统移植到一个新的 MCU 硬件平台,保证 MiCO 应用工程可以正常运行。移植的主要工作:实现驱动接口功能。

阅读本文,开发者应具备一定的硬件知识,了解 MCU 架构,了解 Cortex-M 系列指令,熟悉 IAR 开发环境(部分基础操作不做详细介绍)。

目录

  1. 移植前准备
  2. 明确移植对象
  3. 主体移植思想
  4. MiCO启动流程
  5. 移植相关文件
  6. 移植步骤
  7. 移植Bootloader引导程序
    1. 新建板级支持包
    2. 工程配置相关
    3. 时钟相关
    4. Memory相关
    5. 外设接口相关
    6. 移植结果验证
  8. 移植wifi_uart透传程序
    1. EMW1062模块配置
    2. 模式选择
    3. 外设中断配置
    4. 移植结果验证

移植前准备

1. 明确MiCO支持的MCU内核: 目前 MiCO 已经支持的内核有:Cortex-M3 , Cortex-M4, Cortex-M4F三个,所以基于本文进行 MiCO 移植时,要选 M3 或 M4 内核的 MCU 平台。

2. 明确MiCO所需FLASH和RAM大小: 目前 MiCO 系统移植要求 MCU 必须满足:RAM 不小于 96KB,片内 FLASH 不小于300KB,主频48MHZ以上,支持SDIO或SPI接口。

3.明确MiCO必需的外设接口:

  • 2 个 UART 接口: 1个 UART 接口用于下载调试, 1个 UART 接口用于应用层使用(透传或其他)
  • SPI 接口:
    1. 如果用 SPI 连接 WLAN 模块,则需要两个 SPI 接口,一个专用连接 WLAN 模块,一个连接SPI FLASH 或其他 SPI 外设使用.
    1. 如果用 SDIO 连接 WLAN 模块,就只需要一个 SPI 接口就可以(SPI FLASH 和 SPI 外设)

4.明确 MiCO 支持的单 WLAN 模块型号: MiCO 支持的单 WLAN 模块型号:EMW1062,EMW1088。

5. 获取MCU厂商提供的底层驱动库

6. 下载MiCO SDK开发包:下载中心 ,下载 SDK 开发包,它集成了各种已经移植好的MCU工程,可以做参考。检查移植是否完成,可以使用 MiCO SDK 里的 bootloader 和 Demos(可用\application\wifi_uart)两个工程项目,其他工程项目都只是上层不同而已。

7. 准备移植用的开发板: 确认开发板是否满足MiCO移植要求,如: 是否是MiCO支持的MCU内核类型? WLAN模块正确连接吗(是否是MiCO已经支持的型号)? 片内FLASH,RAM大小满足吗? SPI FLASH 连接正确与否? UART 接口连接正确与否?等等。

8. 准备开发工具: MiCoder IDE v1.0或更高版本,J-Link或ST-link调试工具,串口调试工具,网络调试工具,可参考:第三方开发工具及驱动

明确移植对象

1.选择开发板

根据上节提到的开发板选用要求,同时为了避免开发板电路过于复杂,本次移植选择STM32F407ZET6最小系统开发板。购买开发板,点 这里。开发板详细资料获取,点 这里

  • 开发板硬件资源

开发板主芯片选用 STM32F407ZET6,主频为168MHz,内置512KB Flash、192+4kB SRAM,开发板其他资源如图所示。

  • 1.NRF24L01模块接口: 这是开发板板载的 NRF24L01 模块接口(U6),只要插入模块,我们便可以实现无线通信,从而使得我们板子具备了无线功能,但是这里需要2个模块和2个开发板同时工作才可以。如果只有1个开发板或1个模块,是没法实现无线通信的。

  • 2.W25Q128 128M FLASH: 这是开发板外扩的 SPI FLASH 芯片(U11),容量为128Mbit,也就是16M字节,可用于存储字库和其他用户数据,满足大容量数据存储要求。当然如果觉得 16M 字节还不够用,你可以把数据存放在外部 SD 卡。

  • 3.SD卡接口: 这是开发板板载的一个标准 SD 卡接口(SD_CARD) ,该接口在开发板的背面,采用大 SD卡接口(即相机卡,TF 卡是不能直接插的,TF 卡得加卡套才行) ,SDIO 方式驱动,有了这 个SD 卡接口,就可以满足海量数据存储的需求。

2.选择射频模块

目前庆科支持的两种单射频无线模块是:EMW1062 和 EMW1088。

  • EMW1062 利用直接序列扩频和OFDM / CCK技术,实现无线调制解调功能,该模块集成2.4GHz IEEE802.11b/g/n(MAC/基带/射频),功率放大器(PA)和电源管理单元(PMU),SDIO2.0或SPI接口,3.3V单电源供电。 该模块的无线局域网符合IEEE802.11b/g/n标准。

  • EMW1088 是一款基于MARVELL88w8801芯片设计的产品。该芯片是一个高度集成的,单波段的(2.4GHz),符合IEEE 802.11n:1x1无线标准的系统级芯片(SoC,System-on-Chip),专门为支持下一代无线局域网产品的高通量数据传输速率而设计。

本次移植单射频模块选择EMW1062,EMW1088同样可以参考本次移植方法。

主体移植思想

首先明确: MiCO分为Bootloader, 应用程序,和 RF 射频驱动三块。其中:

  • Bootloader: 初始化硬件设备、创建存储器空间的映射,通过串口UART烧写其它固件。
  • 应用程序: MiCO应用程序代码。
  • RF射频驱动: 运行在RF射频芯片内,存储在MCU片内flash或者片外SPI flash中,是一个已经build好的bin文件。

移植思路:

  • 首先,移植最核心部分—MCU 内核相关。
  • 然后,让Bootloader可以运行。
  • 然后,让Demo wifi_uart(可以配网,连网,串口透传(本地透传,局域网内))可以工作。

MiCO启动流程

MiCO SDK 中的工程分为两大类:bootloader 引导程序和 Application 应用程序,这两段代码写在不同的flash分区中,分两次写入。那么MiCO系统运行流程也就和普通的STM32程序不同:

  • 1.首先是 Bootloader 引导程序,完成系统硬件环境配置,Bootloader 引导程序的入口函数为 int main(),main()函数在 Bootlaoder 工程中的 BootloaderEntrance.c 文件下,不同平台的bootloader程序基本相同。
  • 2.Bootloader 引导程序完成使命以后就该 Application 应用程序上台表演了,Application 程序的入口函数为int application_start(),application_start()函数在 MICOAppEntrance.c 文件内。上面两 个入口函数非常重要! !

下面我们以hello world工程为例,来分析 MiCO 系统的运行流程,如图所示。

mico_startup

移植相关文件

porting_files

上图红色选中部分为移植时需要更改和实现的文件,主要包括 5 个文件夹:

1.platform_config.h: 当前平台的配置信息

  • a) 硬件信息字符串,OS tick频率,看门狗使能定义,STDIO使能定义,低功耗使能定义,RTC使能定义,按键恢复默认设置超时时间,MCU的时钟频率,NVIC优先级位数;
  • b) WIFI模块相关定义:类型, 引脚类型,存储方式。

2.platform.c文件:

  • a) 可以使用的设备配置:GPIO,SPI, I2C, PWM, ADC, UART, FLASH, WIFI模块引脚配置,WIFI模块使用的SPI配置,flash的分区表(Boot,app,rf,para)。
  • b) 部分中断处理程序入口
  • c) 板级初始化相关函数 和MICO标准按键(BOOT, STATUS)相关处理函数

3.platform.h文件:

  • a) 用户可以使用的设备定义:哪些GPIO可用, 哪些spi,I2C,PWM,ADC, UART, FLASH,可用
  • b) 系统和arduino引脚的对应关系.
  • c) 设备的对应关系

4.memory.ld文件: 定义分配的内存 5.MKF407.mk文件:设计编译规则

移植步骤

1. 移植 Bootloader 引导程序

  1. 新建板级支持包
  2. 工程相关配置
  3. Memory相关
  4. 时钟相关配置
  5. 外设接口
  6. 结果验证

2. 移植 Demos\application\wifi_uart示例程序

  1. 无线模块配置
  2. 模式选择
  3. 外设中断配置
  4. 结果验证

移植Bootloader引导程序

1.新建板级支持包

  • 为了快速构建支持包,我们从 board 目录下的 NUCLEO_F411RE 复制出一个新的文件,修改名字为MK407。

2.工程配置相关

(1)修改mk配置文件

  • 1)修改 MK 配置文件名:将 NUCLEO_F411RE.mk 文件名称修改为 MK407.mk 文件。
  • 2)打开 MK407.mk 文件,修改 NAME 值:NAME := Board_NUCLEO_F411RE 修改为NAME := Board_MK407
  • 3)WLAN_CHIP 相关参数:
WLAN_CHIP               := 43362
WLAN_CHIP_REVISION      := A2
WLAN_CHIP_FAMILY        := 43362
WLAN_CHIP_FIRMWARE_VER  := 5.90.230.12

注意: 本次移值开发板和 NUCLEO_F411RE 均使用EMW1062,不需修改,当使用EMW1088模块时候需要修改,修改参数可以参考 MK3288 板级支持包。

  • 4)将MODULE :=3165修改为MODULE :=407;
  • 5)修改如下参数以便系统可以正常调用ST公司底层库函数:
HOST_MCU_FAMILY         := STM32F4xx #对应platform/MCU、STM32F4xx文件
HOST_MCU_VARIANT        := STM32F411
HOST_MCU_PART_NUMBER    := STM32F411CEY6

由于开发板选用STM32F407ZET6,仍使用ST公司的库函数,所以将以上参数修改为:

HOST_MCU_FAMILY         := STM32F4xx 
HOST_MCU_VARIANT        := STM32F407
HOST_MCU_PART_NUMBER    := STM32F407ZET6
  • 6)选择wifi模块驱动方式:BUS := SDIO 或者 BUS := SPI

  • 7)声明外部HSE:GLOBAL_DEFINES += HSE_VALUE=8000000 #系统使用8MHz外部震荡晶振

  • 8)搜索路径声明:GLOBAL_LDFLAGS += -L ./board/NUCLEO_F411RE 修改为:GLOBAL_LDFLAGS += -L ./board/MK407

  • 9)SPI驱动共享配置:SHARED_WIFI_SPI_BUS := YES 如果使用共享模式,保留上述配置方法,一般不开启共享功能,建议使用单独SPI驱动wifi模块。

(2) 程序启动时进入bootloader

打开platform.c文件,下拉至最后,修改 MicoShouldEnterBootloader 函数.

注意:由于本开发板上没有 BOOT 和 STATUS 模式切换拨码开关,因此应用程序直接进入bootloader模式。

bool MicoShouldEnterBootloader(void)
{
//  if(MicoGpioInputGet((mico_gpio_t)BOOT_SEL)==false && \MicoGpioInputGet((mico_gpio_t)MFG_SEL)==true)
//    return true;
//  else
  //    return false;
    return true;
}

(3) 修改platform_config.h文件中参数:

  • 1)修改版本号:
#define HARDWARE_REVISION   "1.0"
#define DEFAULT_NAME        "NUCLEO"
#define MODEL               "NUCLEO-F411RE"

将以参数修改为如下所示:

#define HARDWARE_REVISION   "1.0"
#define DEFAULT_NAME        "STM32"
#define MODEL               "STM32-F407ZE"
  • 2)关闭SPI共享功能:注释掉 #define MICO_WIFI_SHARE_SPI_BUS

3.时钟相关

(1)MK407.mk中相关参数

声明开发板的外部晶振频率; 在 7.2.1 中 7) 已经配置了此参数: GLOBAL_DEFINES += HSE_VALUE=8000000

(2)Platform_config.h中参数

a.修改主频: #define MCU_CLOCK_HZ (100000000), 修改为 #define MCU_CLOCK_HZ (168000000)

b.修改PLL锁相环相关参数:

#define PLL_M_CONSTANT          16            /* PLLM = 16   */
#define PLL_N_CONSTANT          400          /* PLLN = 400  */
#define PLL_P_CONSTANT          4            /* PLLP = 4    */
#define PPL_Q_CONSTANT          7            /* PLLQ = 7    */  

修改为

#define PLL_M_CONSTANT          8            /* PLLM = 16   */
#define PLL_N_CONSTANT          336          /* PLLN = 400  */
#define PLL_P_CONSTANT          2            /* PLLP = 4    */
#define PPL_Q_CONSTANT          7            /* PLLQ = 7    */  

计算公式:

示例:8MHz*336/(8*2)=168MHz     //系统主时钟  
示例:8MHz*336/(8*7)=48MHz      //USB时钟

4.Memory相关

  • (1)在platform.c文件中修改flash的划分,分为:BOOT区(32KB),固件区,RF驱动区,参数区,OTA升级暂存区
  • (2)STM3F407ZET6内置512Kflash,外部连接一个W25Q16,因此可修改NUCLEO_F411RE中的flash划分,将bootloader程序和Application程序放在STM32F407的内部flash中,wifi固件、OTA升级区、参数1区和参数2区都放在外部的W25Q16中,具体划分如下所示:
const mico_logic_partition_t mico_partitions[] =
{
  [MICO_PARTITION_BOOTLOADER] =
  {
    .partition_owner           = MICO_FLASH_EMBEDDED,
    .partition_description     = "Bootloader",
    .partition_start_addr      = 0x08000000,
    .partition_length          =     0x8000,    //32k bytes
    .partition_options         = PAR_OPT_READ_EN | PAR_OPT_WRITE_DIS,
  },
  [MICO_PARTITION_APPLICATION] =
  {
    .partition_owner           = MICO_FLASH_EMBEDDED,
    .partition_description     = "Application",
    .partition_start_addr      = 0x0800C000,
    .partition_length          =    0x64000,   //400k bytes
    .partition_options         = PAR_OPT_READ_EN | PAR_OPT_WRITE_DIS,
  },
  [MICO_PARTITION_RF_FIRMWARE] =
  {
    .partition_owner           = MICO_FLASH_SPI,
    .partition_description     = "RF Firmware",
    .partition_start_addr      = 0x2000,
    .partition_length          = 0x3E000,  //248k bytes
    .partition_options         = PAR_OPT_READ_EN | PAR_OPT_WRITE_DIS,
  },
  [MICO_PARTITION_OTA_TEMP] =
  {
    .partition_owner           = MICO_FLASH_SPI,
    .partition_description     = "OTA Storage",
    .partition_start_addr      = 0x40000,
    .partition_length          = 0x70000, //448k bytes
    .partition_options         = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
  },
  [MICO_PARTITION_PARAMETER_1] =
  {
    .partition_owner           = MICO_FLASH_SPI,
    .partition_description     = "PARAMETER1",
    .partition_start_addr      = 0x0,
    .partition_length          = 0x1000, // 4k bytes
    .partition_options         = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
  },
  [MICO_PARTITION_PARAMETER_2] =
  {
    .partition_owner           = MICO_FLASH_SPI,
    .partition_description     = "PARAMETER2",
    .partition_start_addr      = 0x1000,
    .partition_length          = 0x1000, //4k bytes
    .partition_options         = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
  }
};

5.外设接口相关

platform_peripheral.h文件定义HAL层使用时,外设相关的类型定义,以及移植需要实现的接口函数。platform_mcu_peripheral.h文件定义外设使用的结构体,分为:

  1. MCU指向外设端口的port定义:platform_xxx_port_t (操作驱动库使用)
  2. MCU外设硬件结构体定义:platform_xxx_t (port,引脚,中断号,等)
  3. MCU外设使用时结构体定义:platform_xxx_driver_t(外设,信号量,配置,buffer等等) 外设接口定义在platform.h, platform.c文件。

(1)修改platform.h

  • 1) GPIO定义: 修改开发板对外GPIO定义,修改后结果如下所示:
typedef enum
{ 
    MICO_SYS_LED, 
    MICO_RF_LED, 
    BOOT_SEL, 
    MFG_SEL, 
    EasyLink_BUTTON, 
    STDIO_UART_RX,  
    STDIO_UART_TX,  
    FLASH_PIN_SPI_CS,
    FLASH_PIN_SPI_CLK,
    FLASH_PIN_SPI_MOSI,
    FLASH_PIN_SPI_MISO,

    MICO_GPIO_2,
    MICO_GPIO_8,
    MICO_GPIO_9,
    MICO_GPIO_12,
    MICO_GPIO_14,
    MICO_GPIO_16,
    MICO_GPIO_17,
    MICO_GPIO_18,
    MICO_GPIO_19,
    MICO_GPIO_27,  
    MICO_GPIO_29,
    MICO_GPIO_30,
    MICO_GPIO_31,
    MICO_GPIO_33,
    MICO_GPIO_34,
    MICO_GPIO_35,
    MICO_GPIO_36,
    MICO_GPIO_37,
    MICO_GPIO_38,
    MICO_GPIO_MAX, /* Denotes the total number of GPIO port aliases. Not a valid GPIO alias */
    MICO_GPIO_NONE,
} mico_gpio_t;

可以按照自己的命名风格命名,删除如下定义:

#define MFG_SEL               (MICO_GPIO_NONE)
#define MICO_RF_LED           (MICO_GPIO_NONE)
#define BOOT_SEL              (MICO_GPIO_NONE)

以便支持硬件方式选择程序进入的模式,bootloader模式或者application模式。

  • 2)外设资源定义: 本次移植定义了一路SPI接口、一路I2C接口、3路ADC接口和两路串口,如果需要扩展,可以参考本次移植以及其他micokit中相关资源自行移植。
typedef enum
{
  MICO_SPI_1,
  MICO_SPI_MAX, /* Denotes the total number of SPI port aliases. Not a valid SPI alias */
  MICO_SPI_NONE,
} mico_spi_t;
typedef enum
{
    MICO_I2C_1,
    MICO_I2C_MAX, /* Denotes the total number of I2C port aliases. Not a valid I2C alias */
    MICO_I2C_NONE,
} mico_i2c_t;
typedef enum
{
    MICO_PWM_MAX, /* Denotes the total number of PWM port aliases. Not a valid PWM alias */
    MICO_PWM_NONE,
} mico_pwm_t;
typedef enum
{
    MICO_ADC_1,
    MICO_ADC_2,
    MICO_ADC_3,
    MICO_ADC_MAX, /* Denotes the total number of ADC port aliases. Not a valid ADC alias */
    MICO_ADC_NONE,
} mico_adc_t;
typedef enum
{
    MICO_UART_1,
    MICO_UART_2,
    MICO_UART_MAX, /* Denotes the total number of UART port aliases. Not a valid UART alias */
    MICO_UART_NONE,
} mico_uart_t;
  • 3)串口配置: 将bootloader模式使用的debug串口和CLI串口定义为MICO_UART_2。
#ifdef BOOTLOADER
#define STDIO_UART       (MICO_UART_2)
#define STDIO_UART_BAUDRATE (115200) 
#else
#define STDIO_UART       (MICO_UART_2)
#define STDIO_UART_BAUDRATE (115200) 
#endif

#define UART_FOR_APP     (MICO_UART_2)
#define MFG_TEST         (MICO_UART_2)
#define CLI_UART         (MICO_UART_2)

(2) 修改platform.c

  • 1)GPIO配置: 根据开发板各个资源引脚分布情况,合理配置GPIO引脚,配置如下:
const platform_gpio_t platform_gpio_pins[] =
{
  /* Common GPIOs for internal use */
  [MICO_SYS_LED]                      = { GPIOF,  9 },
  [MICO_RF_LED]                       = { GPIOF,  10},
  [BOOT_SEL]                          = { GPIOF,  1 },
  [MFG_SEL]                           = { GPIOF,  0 },
  [EasyLink_BUTTON]                   = { GPIOE,  4 },   //key0
  [STDIO_UART_RX]                     = { GPIOA,  3 },  
  [STDIO_UART_TX]                     = { GPIOA,  2 },  
  [FLASH_PIN_SPI_CS  ]                = { GPIOB, 14 },
  [FLASH_PIN_SPI_CLK ]                = { GPIOB,  3 },
  [FLASH_PIN_SPI_MOSI]                = { GPIOB,  5 },
  [FLASH_PIN_SPI_MISO]                = { GPIOB,  4 },

  /* GPIOs for external use */
  [MICO_GPIO_2]                       = { GPIOG,  7 },
  [MICO_GPIO_8]                       = { GPIOA , 2 },
  [MICO_GPIO_9]                       = { GPIOA,  1 },
  [MICO_GPIO_12]                      = { GPIOA,  3 },
  [MICO_GPIO_14]                      = { GPIOA,  0 },
  [MICO_GPIO_16]                      = { GPIOC, 13 },
  [MICO_GPIO_17]                      = { GPIOB, 10 },
  [MICO_GPIO_18]                      = { GPIOB,  9 },
  [MICO_GPIO_19]                      = { GPIOB, 12 },
  [MICO_GPIO_27]                      = { GPIOA, 12 },  
  [MICO_GPIO_29]                      = { GPIOA, 10 },
  [MICO_GPIO_30]                      = { GPIOA,  9 },
  [MICO_GPIO_31]                      = { GPIOB,  8 },
  [MICO_GPIO_33]                      = { GPIOB, 13 },
  [MICO_GPIO_34]                      = { GPIOA,  5 },
  [MICO_GPIO_35]                      = { GPIOA, 11 },
  [MICO_GPIO_36]                      = { GPIOB,  1 },
  [MICO_GPIO_37]                      = { GPIOB,  0 },
  [MICO_GPIO_38]                      = { GPIOA,  4 },
};
  • 2)配置外设资源:
const platform_i2c_t platform_i2c_peripherals[] =
{
  [MICO_I2C_1] =
  {
    .port                         = I2C1,
    .pin_scl                      = &platform_gpio_pins[MICO_GPIO_18],
    .pin_sda                      = &platform_gpio_pins[MICO_GPIO_17],
    .peripheral_clock_reg         = RCC_APB1Periph_I2C1,
    .tx_dma                       = DMA1,
    .tx_dma_peripheral_clock      = RCC_AHB1Periph_DMA1,
    .tx_dma_stream                = DMA1_Stream7,
    .rx_dma_stream                = DMA1_Stream5,
    .tx_dma_stream_id             = 7,
    .rx_dma_stream_id             = 5,
    .tx_dma_channel               = DMA_Channel_1,
    .rx_dma_channel               = DMA_Channel_1,
    .gpio_af_scl                  = GPIO_AF_I2C1,
    .gpio_af_sda                  = GPIO_AF_I2C1
  },
};
platform_i2c_driver_t platform_i2c_drivers[MICO_I2C_MAX];

const platform_uart_t platform_uart_peripherals[] =
{
  [MICO_UART_1] =
  {
    .port                         = USART2,
    .pin_tx                       = &platform_gpio_pins[STDIO_UART_TX],
    .pin_rx                       = &platform_gpio_pins[STDIO_UART_RX],
    .pin_cts                      = NULL,
    .pin_rts                      = NULL,
    .tx_dma_config =
    {
      .controller                 = DMA1,
      .stream                     = DMA1_Stream6,
      .channel                    = DMA_Channel_4,
      .irq_vector                 = DMA1_Stream6_IRQn,
      .complete_flags             = DMA_HISR_TCIF6,
      .error_flags                = ( DMA_HISR_TEIF6 | DMA_HISR_FEIF6 ),
    },
    .rx_dma_config =
    {
      .controller                 = DMA1,
      .stream                     = DMA1_Stream5,
      .channel                    = DMA_Channel_4,
      .irq_vector                 = DMA1_Stream5_IRQn,
      .complete_flags             = DMA_HISR_TCIF5,
      .error_flags                = ( DMA_HISR_TEIF5 | DMA_HISR_FEIF5 | DMA_HISR_DMEIF5 ),
    },
  },
  [MICO_UART_2] =
  {
    .port                         = USART1,
    .pin_tx                       = &platform_gpio_pins[MICO_GPIO_30],
    .pin_rx                       = &platform_gpio_pins[MICO_GPIO_29],
    .pin_cts                      = NULL,
    .pin_rts                      = NULL,
    .tx_dma_config =
    {
      .controller                 = DMA2,
      .stream                     = DMA2_Stream7,
      .channel                    = DMA_Channel_4,
      .irq_vector                 = DMA2_Stream7_IRQn,
      .complete_flags             = DMA_HISR_TCIF7,
      .error_flags                = ( DMA_HISR_TEIF7 | DMA_HISR_FEIF7 ),
    },
    .rx_dma_config =
    {
      .controller                 = DMA2,
      .stream                     = DMA2_Stream2,
      .channel                    = DMA_Channel_4,
      .irq_vector                 = DMA2_Stream2_IRQn,
      .complete_flags             = DMA_LISR_TCIF2,
      .error_flags                = ( DMA_LISR_TEIF2 | DMA_LISR_FEIF2 | DMA_LISR_DMEIF2 ),
    },
  },
};
const platform_adc_t platform_adc_peripherals[] =
{
  [MICO_ADC_1] = { ADC1, ADC_Channel_0, RCC_APB2Periph_ADC1, 1, (platform_gpio_t*)&platform_gpio_pins[MICO_GPIO_24] },
  [MICO_ADC_2] = { ADC1, ADC_Channel_1, RCC_APB2Periph_ADC1, 1, (platform_gpio_t*)&platform_gpio_pins[MICO_GPIO_23] },
  [MICO_ADC_3] = { ADC1, ADC_Channel_4, RCC_APB2Periph_ADC1, 1, (platform_gpio_t*)&platform_gpio_pins[MICO_GPIO_22] },
};

至此,bootloader工程已移植完毕。

6.移植结果验证

按照以上步骤移植完 Bootloader 工程,将程序编译下载进入开发板,然后打开串口调试工具,可以看到如下 log 信息,通过串口调试工具向开发板发送命令: 7,可以看到系统重启,有log信息输出,此时,bootloader移植成功,我们可以进入下一环节进行应用程序的移植。

boot_log

移植wifi_uart透传程序

1.EMW1062模块配置

(1)功能配置

在platform_config.h文件中声明相关引脚功能,如下:

/******************************************************
 *  EMW1062 Options
******************************************************/
/*  Wi-Fi chip module */
#define EMW1062
/*  GPIO pins are used to bootstrap Wi-Fi to SDIO or gSPI mode */
//#define MICO_WIFI_USE_GPIO_FOR_BOOTSTRAP_0
//#define MICO_WIFI_USE_GPIO_FOR_BOOTSTRAP_1
/*  Wi-Fi GPIO0 pin is used for out-of-band interrupt */
#define MICO_WIFI_OOB_IRQ_GPIO_PIN  ( 0 )
/*  Wi-Fi power pin is present */
//#define MICO_USE_WIFI_POWER_PIN
/*  Wi-Fi reset pin is present */
#define MICO_USE_WIFI_RESET_PIN
/*  Wi-Fi 32K pin is present */
//#define MICO_USE_WIFI_32K_PIN
/*  USE SDIO 1bit mode */
//#define SDIO_1_BIT
/* Wi-Fi power pin is active high */
//#define MICO_USE_WIFI_POWER_PIN_ACTIVE_HIGH
/*  WLAN Powersave Clock Source
 *  The WLAN sleep clock can be driven from one of two sources:
 *  1. MCO (MCU Clock Output) - default
 *  2. WLAN 32K internal oscillator (30% inaccuracy)
 */
//#define MICO_USE_WIFI_32K_CLOCK_MCO
//#define MICO_USE_BUILTIN_RF_DRIVER

(2)引脚配置

打开platform.c文件,修改wifi_control_pins[]数组和wifi_spi_pins[]数组中相关引脚如下所示:

const platform_gpio_t wifi_control_pins[] =
{
  [WIFI_PIN_RESET   ]        = { GPIOG,  2 },
};
const platform_gpio_t wifi_spi_pins[] =
{
  [WIFI_PIN_SPI_IRQ ] = { GPIOG,  1 },
  [WIFI_PIN_SPI_CS  ] = { GPIOG,  3 },
  [WIFI_PIN_SPI_CLK ] = { GPIOC,  10 },
  [WIFI_PIN_SPI_MOSI] = { GPIOC,  12 },
  [WIFI_PIN_SPI_MISO] = { GPIOC,  11 },
};

(3)驱动方式配置

  • 1)MK407.mk 文件中,配置BUS :=SPI,确定驱动方式为 SPI 驱动。
  • 2)platform.c文件中,配置 wifi_spi_pins[]数组内容,这个数组将被platform/MCU/STM32F2xx/EMW1062_driver/wlan)spi.c中函数调用。配置 SPI DMA 接收中断的中断优先级:
   //NVIC_SetPriority( DMA2_Stream3_IRQn,  3 ); /*WLAN SDIO DMA*/
     NVIC_SetPriority( DMA1_Stream2_IRQn,  3 ); /* WLAN SPI DMA  */ 

2.模式选择

在platform.c文件中,配置 MicoShouldEnterMFGMode() 函数 和 MicoShouldEnterBootloader() 函数。

bool MicoShouldEnterMFGMode(void)
{
//  if(MicoGpioInputGet((mico_gpio_t)BOOT_SEL)==false && MicoGpioInputGet((mico_gpio_t)MFG_SEL)==false)
//    return true;
//  else
    return false;
}
bool MicoShouldEnterBootloader(void)
{
//  if(MicoGpioInputGet((mico_gpio_t)BOOT_SEL)==false && MicoGpioInputGet((mico_gpio_t)MFG_SEL)==true)
//    return true;
//  else
      return false;
}

以上配置方式是使用软件控制程序进入application应用程序中也可以打开以上两函数注释的内容通过外部引脚来控制模式,MFG_SEL引脚拉低,系统进入产测模式,BOOT_SEL引脚拉低,系统进入bootloader模式,当引脚均拉高,进入应用程序。

3.外设中断配置

主要配置为串口中断的配置,本系统中,发送流通道USART1选为DMA2_Stream7,USART2选择DMA1_Stream6;接收流通道,USART1选择DMA2_Stream2,USART2船则DMA1_Stream5。具体配置如下所示。

MICO_RTOS_DEFINE_ISR( USART1_IRQHandler )
{
  platform_uart_irq( &platform_uart_drivers[MICO_UART_2] );
}
MICO_RTOS_DEFINE_ISR( USART2_IRQHandler )
{
  platform_uart_irq( &platform_uart_drivers[MICO_UART_1] );
}
MICO_RTOS_DEFINE_ISR( DMA1_Stream6_IRQHandler )
{
  platform_uart_tx_dma_irq( &platform_uart_drivers[MICO_UART_1] );
}
MICO_RTOS_DEFINE_ISR( DMA2_Stream7_IRQHandler )
{
  platform_uart_tx_dma_irq( &platform_uart_drivers[MICO_UART_2] );
}
MICO_RTOS_DEFINE_ISR( DMA1_Stream5_IRQHandler )
{
  platform_uart_rx_dma_irq( &platform_uart_drivers[MICO_UART_1] );
}
MICO_RTOS_DEFINE_ISR( DMA2_Stream2_IRQHandler )
{
  platform_uart_rx_dma_irq( &platform_uart_drivers[MICO_UART_2] );
}

4.移植结果验证

(1)编译与下载

至此,我们已经完成了手把手的移值工作,只需将修改的板级支持包放到board目录下,通过mico-cube工具或MiCoder IDE对工程进行编译。

如在 git 命令行中,通过 mico-cube 工具命令: mico make application.wifi_uart@MK407 total download, 完成编译和下载,log内容如下:

demo_compile

(2)结果验证

  • 1)本demo需配合手机APP-Easylink使用,首先为设备配网。
  • 2)配网后,在在线调试 uart 口通过 ifconfig 命令,查看该开发板设备 ip 地址。
  • 3)然后在PC上用tcp客户端工具连接到该 ip地址: 8080端口,进行数据传输测试,可以测试数据传输速率,长时间传输稳定性。

说明:Easylink是上海庆科开发的一款智能设备配网APP,请参考: Easylink SDK 下载安装使用。

文本导读目录