华大 MCU 之一 HC32F460 替换 STM32F411 移植记录
更新
- 2020年 10 月 21 日,将驱动库更新到了最新版 1.1.1
- 2020年 10 月 20 日,MCU 由原来的 HC32F460KCTA 更换为 HC32F460KETA
简介
目前,部分产品需要国产化,首当其冲的就是更换国产 MCU。在经过几番研究之后,最终决定使用华大的 MCU 来代替(STM32F411 -> HC32F460)。工作的重点就是如何将现有项目代码一点点移植到 HC32F460 上。以下就是一些在移植过程中的记录。
首先从官网 https://www.hdsc.com.cn/ 下载各种资料、开发包
开发环境
当前所以开发环境中,默认都没有华大的 MCU。因此,需要我们自己从华大的官网下载各 IDE 的配套工具包进行安装,具体有以下几个方面:
MCU 选择
默认 Keil 和 IAR 中并没有华大的 MCU,必须从其官网下载开发工具包,然后进行安装!实际使用中发现,安装之后的虽然可以选择华大 MCU,但是,里面竟然没有我对应的 MCU 类型。
貌似,目前其开发包中仅提供了几个类型的 MCU。包括下载算法,都没有我使用的 MCU 的!不过好在我们可以选择一个资源多一些的 MCU 下载算法代替!
下载算法
安装了早期的开发包(1.0.2)后,貌似并没有对应的 FLASH 下载算法,至少 Keil 里面不会显示下载算法。解决方法是:将华大提供的下载算法 Flash_HC32F46x.FLM
(位于其开发包中对应的开发环境目录下)放到 Keil 的安装目录下的 D:\Keil_v5\ARM\Flash
中。不过,最新我从官网下载了最新 1.0.5 版本并安装,Keil 就可以显示 FLASH 下载算法了!
注意:如果想更新对应的驱动库,可要谨慎!我看了一下,新的驱动库与旧的并不兼容!
Jlink/J-Flash 的配置
如果开发中使用 Jlink 进行仿真调试,那么经常会用到 J-Flash 来读写 MCU。默认情况下 Jlink 中也是没有华大 MCU 的。解决方法是,手动编辑 Jlink 的安装目录下的配置文件 JLinkDevices.xml
,增加如下内容:
<!-- --><!-- HDSC (HC32) --><!-- --><Device><ChipInfo Vendor="HDSC" Name="HC32L176" WorkRAMAddr="0x20000000" WorkRAMSize="0x2000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_128K" BaseAddr="0x0" MaxSize="0x20000" Loader="Devices/HDSC/FlashHC32L17X_128K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32L136" WorkRAMAddr="0x20000000" WorkRAMSize="0x2000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_64K" BaseAddr="0x0" MaxSize="0x10000" Loader="Devices/HDSC/FlashHC32L13X_64K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32L130" WorkRAMAddr="0x20000000" WorkRAMSize="0x2000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_64K" BaseAddr="0x0" MaxSize="0x10000" Loader="Devices/HDSC/FlashHC32L13X_64K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32F030" WorkRAMAddr="0x20000000" WorkRAMSize="0x2000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_64K" BaseAddr="0x0" MaxSize="0x10000" Loader="Devices/HDSC/FlashHC32F030_64K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device> <Device><ChipInfo Vendor="HDSC" Name="HC32L110x4" WorkRAMAddr="0x20000000" WorkRAMSize="0x800" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_16K" BaseAddr="0x0" MaxSize="0x4000" Loader="Devices/HDSC/FlashHC32L110_16K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device> <Device><ChipInfo Vendor="HDSC" Name="HC32L110x6" WorkRAMAddr="0x20000000" WorkRAMSize="0x1000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_32K" BaseAddr="0x0" MaxSize="0x8000" Loader="Devices/HDSC/FlashHC32L110_32K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32F003" WorkRAMAddr="0x20000000" WorkRAMSize="0x800" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_16K" BaseAddr="0x0" MaxSize="0x4000" Loader="Devices/HDSC/FlashHC32F003_16K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device> <Device><ChipInfo Vendor="HDSC" Name="HC32F005" WorkRAMAddr="0x20000000" WorkRAMSize="0x1000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_32K" BaseAddr="0x0" MaxSize="0x8000" Loader="Devices/HDSC/FlashHC32F005_32K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device> <Device><ChipInfo Vendor="HDSC" Name="HC32L15" WorkRAMAddr="0x20000000" WorkRAMSize="0x1800" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_128K" BaseAddr="0x0" MaxSize="0x20000" Loader="Devices/HDSC/HC32L15.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32F_M14" WorkRAMAddr="0x20000000" WorkRAMSize="0x2000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_128K" BaseAddr="0x0" MaxSize="0x20000" Loader="Devices/HDSC/HC32F_M14.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device> <Device><ChipInfo Vendor="HDSC" Name="HC32F46x" WorkRAMAddr="0x20000000" WorkRAMSize="0x10000" Core="JLINK_CORE_CORTEX_M4"/><FlashBankInfo Name="Flash_512K" BaseAddr="0x0" MaxSize="0x80000" Loader="Devices/HDSC/HC32F46x.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32L19x" WorkRAMAddr="0x20000000" WorkRAMSize="0x8000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_256K" BaseAddr="0x0" MaxSize="0x40000" Loader="Devices/HDSC/FlashHC32L19X_256K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32F19x" WorkRAMAddr="0x20000000" WorkRAMSize="0x8000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_256K" BaseAddr="0x0" MaxSize="0x40000" Loader="Devices/HDSC/FlashHC32F19X_256K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32F17x" WorkRAMAddr="0x20000000" WorkRAMSize="0x4000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_128K" BaseAddr="0x0" MaxSize="0x20000" Loader="Devices/HDSC/FlashHC32F17X_128K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32L17x" WorkRAMAddr="0x20000000" WorkRAMSize="0x4000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_128K" BaseAddr="0x0" MaxSize="0x20000" Loader="Devices/HDSC/FlashHC32L17X_128K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32F072" WorkRAMAddr="0x20000000" WorkRAMSize="0x4000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_128K" BaseAddr="0x0" MaxSize="0x20000" Loader="Devices/HDSC/FlashHC32F072_128K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device><Device><ChipInfo Vendor="HDSC" Name="HC32L07X" WorkRAMAddr="0x20000000" WorkRAMSize="0x4000" Core="JLINK_CORE_CORTEX_M0"/><FlashBankInfo Name="Flash_128K" BaseAddr="0x0" MaxSize="0x20000" Loader="Devices/HDSC/FlashHC32L07X_128K.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1"/></Device>
注意,如果升级了 Jlink 驱动,需要重新更改以上内容!
驱动库移植
这个不是很麻烦,根据下面的图,对应到原 ST 的目录结构中即可
启动引脚
HC32F460 的 BOOT 引脚(PB11)接高电平为从 Flash 启动,低电平为从 BOOT 启动。与 ST 正好相反。下面是 ST 和 华大 文档中的说明:
驱动库中断处理
HC32F460 的驱动库提供了一个 hc32f46x_interrupts.c/h
的文件,该文件将所有的中断进行了统一的处理,然后以弱函数的形式开发对外接口(hc32f46x_it.c
中定义的函数均为 hc32f46x_interrupts.c/h
中声明的弱函数接口)。但是,其弱函数的使用貌似并不是很规范。在我的项目中,弱函数并没有起作用,导致了中断接口不能用。具体解决方法:
- 修改驱动库,具体可以参考 ST 的 HAL 库中对于弱函数的使用
- 增加一个连接器参数,如下图所示:
这么搞,弱函数的使用上不就复杂了?多此一举了?
在实际使用中,大部分中断(中断号 32 ~ 127)必须先定义一个回调函数,然后将使用的中断注册到 hc32f46x_interrupts.c/h
中定义的方法表中。例如:
/* Select External Int Ch.3 */stcIrqRegiConf.enIntSrc = INT_PORT_EIRQ3;/* Register External Int to Vect.No.007 */stcIrqRegiConf.enIRQn = Int007_IRQn;/* Callback function */stcIrqRegiConf.pfnCallback = &ExtInt03_Callback; /* 这里定义一个回调函数 *//* Registration IRQ */enIrqRegistration(&stcIrqRegiConf);
对于不需要注册的中断,则直接定义弱函数接口。例如:
/*********************************************************************************** \brief SysTick interrupt callback function.**** \param None**** \retval None********************************************************************************/
void SysTick_IrqHandler(void)
{SysTick_IncTick();
}
个人感觉这个文件真的是脱裤子放屁,多此一举!在启动的 .s 文件中,各中断处理函数接口都已经声明并以死循环来处理了。这里把中断再以另一个名字放出去,完全就是为了增加代码量,在使用上没有任何便捷之处。这个文件编译后就近 10K 的代码量,然后还得占一堆 RAM!有没有考虑过 MCU 100 多个中断实际才用几个,一股脑全给搞一块去了!
关于弱函数的使用,请参考博文 ARM 之十一__weak 和 attribute((weak)) 关键字的使用
由于 FLASH 空间不足,目前正在更换 HC32F460KETA
看门狗
目前,看门狗(SWDT)的配置可以必须在库文件 hc32f46x_icg.h
中进行配置(WDT 可以使用 hc32f46x_wdt.c/h
中进行配置),然后将 hc32f46x_icg.c
包含到自己的项目中,否则配置依旧无效!在更改了驱动库源码之后,在更新驱动库时需要注意!
此外,上面这种配置方法会间接导致一个问题:由于我们的程序分为 IAP 和 APP 两部分。看门狗的配置必须放到 IAP 中,且 APP 中不能再包含该文件,否则在调试烧写时会报错!具体见下文的 [程序下载异常] 章节
DMA
在使用串口 DMA 接收的时候,发现驱动库提供的接口并不能满足实际需要。具体表现为,串口的 DMA 是工作在循环模式下的,这就要求在必要的时候可以获取 DMA 接收的数据长度,不过驱动库貌似没有对应的接口!
DMA 驱动中只有设置接口,没有读取接口! 。无奈自己增加了几个接口!
GPIO
华大应该称为 PORT
时钟
貌似,华大 MCU 并不能像 ST MCU 似得,开启或者关闭某个 GPIO 的时钟。所以在配置 IO 时,无需要处理时钟的问题。
特殊配置
某些 IO 在上电时默认是用作其他功能的。例如:
- PA13,PA14,PA15,PB3,PB4 端口复位后初始状态为 JTAG/SWD 功能有效。
- PC14,PC15 端口复位后初始状态为数字功能禁止状态
- PA11,PA12 与 USBFS_DM,USBFS_DP 引脚复用,内藏约 400KΩ 的下拉电阻,且一直有效。
- 端口 PB11 与 MD 复用,为输入专用端口,无输出功能
这一点貌似和 STM32F1x 的使用情况是一致的。因此,如果需要将上面的 IO 作为普通 IO 使用,则必须进行特殊配置,然后才能进行正常的 IO 配置!
- PA13,PA14,PA15,PB3,PB4 在配置 FSEL[5:0] 选择功能时需要先将寄存器 PSPCR 相应位写 0 无效JTAG/SWD 功能。对应的库函数接口
en_result_t PORT_DebugPortSetting(uint8_t u8DebugPort, en_functional_state_t enFunc);
- PC14,PC15 在选择数字功能时需要先将相应寄存器 PCRxy 的 DDIS 位写 0 有效数字功能。这个在进行 IO 配置时,在
en_result_t PORT_Init(en_port_t enPort, uint16_t u16Pin, const stc_port_init_t *pstcPortInit);
中就有对应的处理。 - 当系统运行在高速时钟下,由于 I/O 输入存在延迟,单周期可能无法正确读取输入状态值。此时需要设置寄存器 PCCR.RDWT[1:0],插入若干等待周期。
外设引脚映射
具体见用户手册的 2.2 引脚功能表。在我的项目中,出现了 SPI_CLK 引脚无法映射的问题。
程序下载异常
在使用中发现,在下载程序之后并不能正常启动。我的项目结构是 IAP(在线升级) + APP,每次下载 APP 之后,IAP 就会被清除。一开始没有具体分析错误的原因的情况下,想当然的通过如下解决方法来处理。
但是,如上图修改之后,在实际下载的时候,Keil 会提示如下的警告,不过貌似没啥影响
虽然调试没啥影响,但是在生成 .bin 文件时却会出现错误!
但实际该方法并没有解决根本。通过详细分析,最后发现该问题是由于看门狗的配置导致的。具体:由于 APP 中包含了 看门狗的配置,看门狗的配置其实是 FLASH 中的固定一块空间。我们的 APP 偏移之后,自然没有看门狗部分的操作算法!
最终解决方法: 我们不需要上面的更改,只需要将看门狗的配置放到 IAP 中即可! IAP 肯定是从起始地址开始,自然不会有问题!
外设反初始化
我的项目结构是 IAP(在线升级) + APP,外设在 IAP 中工作正常,但是在 APP 中工作不正常。这主要是由于:外设在 IAP 中已经初始化,然而在调整到 APP 之后,这部分外设由于已经被初始化,导致不会再次被初始化。这一点其实对于 ST 的 MCU 同样适用。因此,需要我们来特殊处理!
例如 hc32f46x_interrupts.c/h
中配置的中断,如果在 IAP 中已经被设置,跳转到 APP 后,就无法再正常配置了(全局变量中会检查是否被配置过)
en_result_t enIrqRegistration(const stc_irq_regi_conf_t *pstcIrqRegiConf)
{// todo, assert ...stc_intc_sel_field_t *stcIntSel;en_result_t enRet = Ok;//DDL_ASSERT(NULL != pstcIrqRegiConf->pfnCallback);DDL_ASSERT(IS_NULL_POINT(pstcIrqRegiConf->pfnCallback));/* IRQ032~127 whether out of range */if (((((pstcIrqRegiConf->enIntSrc/32)*6 + 32) > pstcIrqRegiConf->enIRQn) || \(((pstcIrqRegiConf->enIntSrc/32)*6 + 37) < pstcIrqRegiConf->enIRQn)) && \(pstcIrqRegiConf->enIRQn >= 32)){enRet = ErrorInvalidParameter;}else{stcIntSel = (stc_intc_sel_field_t *)((uint32_t)(&M4_INTC->SEL0) + \(4u * pstcIrqRegiConf->enIRQn));if (0x1FFu == stcIntSel->INTSEL) /* 如果已经初始化过,这里将不能再初始化 */{stcIntSel->INTSEL = pstcIrqRegiConf->enIntSrc;IrqHandler[pstcIrqRegiConf->enIRQn] = pstcIrqRegiConf->pfnCallback;}else{enRet = ErrorUninitialized;}}return enRet;
}
具体方法就是使用 enIrqResign
函数进行重新标记!
华大 MCU 之一 HC32F460 替换 STM32F411 移植记录相关推荐
- 华大 MCU 之三 时钟控制器(CMU)配置记录
今天在新项目(MCU 为华大 HC32F460)中不再使用外部晶振,转而要使用 HC32F460 内部的 HRC,之前在使用外部晶振时,对华大 MCU 的时钟配置有过一些了解,但是,由于使用内部晶 ...
- 华大 MCU 之五 SPI 从机 DMA 模式 配置(不能正常接收问题处理)
最近有个需求是需要使用 华大 MCU(HC32F460) 的 SPI 作为从机来接收数据,无奈搞了两天死活不可用.配置完 SPI 的从机模式后,只要启动主机端的发送就出现如下图所示的错误: 下面是 ...
- 华大 MCU 之四 使用问题记录
在最近使用华大 MCU 时,遇到了不少坑,这里记录一下,以方便在以后升级驱动库!其中,有些问题仅仅是在由 ST 切换到 华大之后不太适于的问题,有些是驱动库的更改问题! 如果您发现我说的问题是 ...
- 华大 MCU 之七 DMA 导致 SPI 异常停止的原因分析、DMA 配置的那些坑
缘起 在最近的项目测试中发现,SPI 通信总是莫名其妙的失败,查看寄存器发现 SPI 已经被停止了.根据手册,SPI 在异常情况下会被强制停止(SPI 的使能为被清零),而根据波形显示通信过程没有 ...
- android touch screen keyboard input移植记录
android touch screen keyboard input移植记录 仅仅是作为记录: Andorid 的 touchscreen 事件必须要有 BTN_TOUCH 才可以. 所以初始化 ...
- 华大 MCU 之六 SEGGER Embedded Studio 及 Ozone 使用 Jlink 调试
首先说一下,我之前的开发流程是:VSCode 编辑代码 + Keil 编译及调试.Keil 的调试功能虽然很强大,但是多数功能需要配合 ARM 自家的 ULINKpro 才可以用,例如 Perfo ...
- 安卓平台下的GPS架构介绍及驱动移植记录
一.前言 我的工作是关于汽车车机BSP部分. 汽车车机,其实基本和人们日常所用的手机一样,也是安卓平台的.所谓安卓,就是一层安卓服务包裹着Linux内核所形成的操作系统. BSP组,主要工作内容就是负 ...
- mjpg-streamer移植记录
一.基于ubuntu18.04系统的mjpg-streamer移植记录 1.移植之前使用ubuntu的软件测试USB摄像头是否正常工作 (1).插上摄像头之后,ubuntu右下角有摄像头图标 (2). ...
- 基于Android8.1的博通bcm89342蓝牙驱动的驱动移植记录
基于Android8.1的博通蓝牙BCM89342的驱动移植记录 说明 一 .软硬件平台 二.蓝牙移植流程 2.1 kernel 对蓝牙的驱动支持配置 2.2 kernel层编写蓝牙电源管理(bt r ...
最新文章
- Linux基金会宣布将为GraphQL成立基金会
- 记一次被DDoS敲诈的历程
- mysql分区有好处吗_mysql 分区有实用价值吗?
- Python学习-基础篇4 模块与包与常用模块
- OpenCV gapi模块基本API的实例(附完整代码)
- SAP CRM IBASE read header debug
- 如何获取微信API的Access Token
- 运行Vue在ASP.NET Core应用程序并部署在IIS上
- echarts tooltip在图表范围内显示
- 最通俗易懂的 Java 10 新特性讲解 | 原力计划
- AI 口罩督查官诞生,识别率高达 85%!
- thinking in java(第七章)
- 用mysql创建图书信息表_数据库创建图书管理系统
- 深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:命令传递) .
- CMMI-V2.0真题模拟(1)
- win10专业版占多少空间_Win10系统
- 木兰当事人回应!承认部分基于 Python 二次开发
- 公有云 私有云 混合云
- 5G聚合路由器助力无人机监控盲区打好疫情阻击战
- charles抓包https证书下载
热门文章
- Ansible-playbook简单应用的几个实例
- hadoop中datanode无法启动,报Caused by: java.net.NoRouteToHostException: No route to host
- Dynamic Web TWAIN扫描识别工具改变缓冲区图像大小
- [转]CDN(内容分发网络)技术原理
- Hadoop集群搭建(27)
- 404 – File or directory not found.
- 关于两个用于创建和销毁二维动态数组的宏
- 真香!你的 2019 年终总结已经出 - 请查收
- 【Python】PAT-1026 程序运行时间(AC)
- Hadoop Yarn公平调度器的特点、缺额、DRF策略