# 记录下调试过程 脑袋不好使,过一周就记不清楚了。趁着还有印象,做下调试记录吧。 ## 缘起 原来一直用stm8s003这款芯片,最多时候3颗003配合分工完成功能。 主控mcu各种IO口模拟多串口接收,数据流交叉流动,再配合自己搞的小调度内核,写起程序来太爽了。 直到疫情来了,各种芯片价格暴涨,原来1块的的直接暴涨到10块,而且缺货~ 好日子到头了,只能考虑切换到国产MCU。 华大的这款看起来名字不错,比ww产的有更好的发展预期,就定它了。虽然现在国产MCU也缺货~ ## HC32F003C4PA 性能看起来不错,很契合手头产品的使用场景。 * 32Mhz Corex-M0 * 16K Flash * 2K RAM * 低功耗 * 10Byte Chip ID * 12bit 1Msps SARADC ## 为什么是python python有多好自不用说,主要是主力开发工具是丐版MacBook Air,一入苹果,终身windows黑了。 话说之前主力系统是debian,足够清淡了~ 国产这些MCU们,还没意思到社区的力量。更多diy玩家的参与,足够的热度,流量来了销量也水到渠成。 类似乐鑫/合宙(*唉,都是最早参与的一批人,就是没有跟随其喝汤,属实可惜*),日子过得真香。 希望华大成为下一个,虽然看起来完全没有搞社区的意识、能力。 ## 番外思考 借助于自己搞的那套小调度内核,mcu甚至只有基本IO、串口、定时器功能就能完成大部分工作。 哪天能否自己封测个小mcu? 8/20脚TSSOP封装,2个串口,2-4个定时器,剩下全是基本IO。售价?5毛不能再多了, 那是不是能发财啦 :] ## 小目标 * **编译/下载**脱离windows环境依赖,支持mac及linux系统 * python脚本,串口烧录bin文件 * 离线烧录器,按键自动串口下载固件 (稍后一丢丢) * 工程模版,gcc编译 ## 调试方法 首先hc系列支持串口下载,高级点的mcu有mode引脚,可以直接进入uart下载模式。 hc32f003呢,启动时候uart应该是10ms内接收到0x18字节可以直接进入uart下载模式。 话说这种有很大风险,如果相连的外设启动后,不小心发了个0x18过来,是不是就炸了~ 关键也没有文档说很清楚,如何退出uart下载模式。先mark下@ arm-none-eabi-gcc是支持M0内核编译的,加之华大提供了IAR/MDK的工程模版、启动文件, 移植到mac/linux系统应该是没问题的。 先说下烧录固件这部分功能吧,windows下有官方提供的HDSC ISP V2.07在线烧录工具, 连接好串口及RST引脚后,使用逻辑分析仪抓串口数据包就ok了。 后来发现了文档[HC32F003系列的FLASH串行编程.pdf](https://github.com/kicer/hc32flash/tree/master/docs/HC32F003系列的FLASH串行编程.pdf), 显然是过期的,协议格式不一致,但是有很大参考价值。 后面发现ISP烧录工具是Mono .NET的,借助ILSpy反汇编出来。 可以得到你想得到的一切~ 当然理论上也是可以直接把反汇编后的代码再重新生成linux/mac上用的。 但.NET不是本人的菜,自己写个python用起来会更爽~ 下载脚本借鉴了stm8flash、luatool工具的很多代码, 芯片配置数据及ramcode都是从官方ISP软件中复制过来的,没有精力验证。 遇到坑就填吧,反正有原始反汇编代码可以参考。 所以,就这么简单 ## 调试过程 ### bootloader启动 1. 复位RESET引脚约18ms 2. pc循环发送0x18 0xFF共10组 3. mcu应答0x11共9组 4. 检查mcu状态 > 01 FC 0B 00 00 02 00 00 00 0A < 01 02 EE FF ED (加密) < 01 02 FF FF FE (未加密) 5. 加密则执行解密动作(擦除FLASH上内容) > B5 34 84 52 BF < 01 6. 准备下载ramcode > 00 00 00 00 20 A4 07 00 00 CB < 01 7. 开始下载ramcode > B8 0A ... 9F < 01 8. 启动ramcode > C0 00 00 00 00 00 00 00 00 C0 < happybaby 00 00 ### ramcode启动 启动后mcu端发送字符串 *happybaby* > 68 61 70 70 79 62 61 62 79 00 00 0. 修改通信用波特率 - 修改成9600bps (00 00 80 25) > 49 01 00 00 00 00 04 00 80 25 00 00 F3 - 修改成115200bps (00 01 C2 00) > 49 01 00 00 00 00 04 00 00 C2 01 00 11 - 应答 < 49 00 00 00 00 00 00 00 49 1. 请求0x20字节数据 (指定波特率) > 49 05 00 00 00 00 20 00 6E < 49 00 00 00 00 00 20 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF EF 38 2. 校验错误 > 49 05 00 00 00 00 20 00 5E < 49 01 00 00 00 00 00 00 4A 3. 请求0x10字节数据 > 49 05 00 00 00 00 10 00 5E < 49 00 00 00 00 00 10 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FE 48 4. 请求0x0200字节数据 > 49 05 00 00 00 00 00 02 50 > 49 05 00 02 00 00 00 02 52 > ... > 49 05 00 3C 00 00 00 02 8C > 49 05 00 3E 00 00 00 02 8E 5. 空白检测 > 49 07 00 00 00 00 04 00 00 40 00 00 94 < 49 00 00 00 00 00 01 00 01 4B > 49 07 00 00 00 00 04 00 00 02 00 00 56 < 49 00 0F 00 00 00 01 00 00 59 6. 整片擦除 > 49 02 00 00 00 00 00 00 4B 7. 页擦除(1sector=512Bytes) > 49 03 00 00 00 00 00 00 4C < 49 00 00 00 00 00 00 00 49 > 49 03 00 02 00 00 00 00 4E < 49 00 00 02 00 00 00 00 4B > ... > 49 03 00 3E 00 00 00 00 8A > 49 00 00 3E 00 00 00 00 87 8. 编程 > 49 04 00 00 00 00 20 00 CHK < 49 00 00 00 00 00 00 00 49 9. 校验,所有数据的累加和取最后两个字节 > 49 06 00 00 00 00 04 00 20 00 00 00 73 < 49 00 00 00 00 00 02 00 CF 1F 39 > 49 06 00 00 00 00 04 00 00 40 00 00 93 < 49 00 00 00 00 00 02 00 00 C0 0B #### 读取FLASH数据 > 49 05 A0 A1 A2 A3 L0 L1 CHK < 49 00 A0 A1 A2 A3 L0 L1 CHK * 49 05: 协议头 * A3..0: 起始地址 * L1..0: 字节长度 * data: FLASH数据 #### 按页擦除FLASH数据 > 49 03 A0 A1 A2 A3 00 00 CHK < 49 00 A0 A1 A2 A3 00 00 CHK * 49 03: 协议头 * A3..0: 起始地址 #### 整片擦除FLASH数据,耗时约40ms > 49 02 00 00 00 00 00 00 4B < 49 00 00 00 00 00 00 00 49 * 49 02: 协议头 #### 空白检测 > 49 07 00 00 00 00 04 00 A0 A1 A2 A3 CHK < 49 C1 C0 00 00 00 01 00 00 CHK * 49 07: 协议头 * C1..0: 检测值 * A3..0: 字节长度 #### 校验 > 49 06 00 00 00 00 04 00 L0 L1 L2 L3 CHK < 49 00 00 00 00 00 02 00 S1 S0 CHK * 49 06: 协议头 * S1..0: 校验和 * L3..0: 字节长度 #### 编程 > 49 04 A0 A1 A2 A3 L0 L1 CHK < 49 00 A0 A1 A2 A3 00 00 CHK * 49 04: 协议头 * A3..0: 起始地址 * L1..0: 字节长度,最大支持0x40字节 #### 加密 > 49 09 00 00 00 00 00 00 52 < 49 00 00 00 00 00 00 00 49