[APM32F1] 极海国产芯|VScode开发APM32F1过程分享

[复制链接]
 楼主| kai迪皮 发表于 2022-10-30 15:37 | 显示全部楼层 |阅读模式
#申请原创# @21小跑堂 麻烦给个原创标签呦

1 前言
  在单片机开发的过程中,一款好的IDE对于工程师而言是非常重要的。现在主流的第三方IDE有Keil、IAR这两款,也有像Embedded Studio(我们常用的J-Link母公司SEGGER的产品,没错他家也有IDE),这些IDE是需要一定费用的,对于一些“敏感”的用户群体而言不太好。除此之外,还有一个原因由于这些IDE起步较早,一些像UI、代码提示等功能也是比较有“历史”感。
  VS Code是一款免费开源的现代化轻量级代码编辑器,支持几乎所有主流的开发语言的语法高亮、智能代码补全、自定义快捷键、括号匹配和颜色区分、代码片段、代码对比 Diff、GIT命令等特性,支持插件扩展,并针对网页开发和云端应用开发做了优化。本篇文章仅从笔者的角度出发,去分享个人在使用VSCode开发APM32F1的过程,由于笔者能力有限,开发过程中难免有所错误,还请各位多多斧正。欢迎在评论区一起讨论各种解决方法。

2 环境支持
本文开发环境(Windows 10 环境下):
1.VS Code 安装好以下插件,以具有代码补全,工程设置以及调试功能。
  VSCode下载地址:https://code.visualstudio.com/
  C/C++插件(代码补全支持):https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools
  Cortex-Debug(仿真支持):https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug
  Embedded IDE(工程配置支持):https://marketplace.visualstudio.com/items?itemName=CL.eide
  Chinese (Simplified) (中文支持):https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-zh-hans
  关于插件的安装,这里就不在赘述,对于各位小伙伴来说是轻而易举的。
2.GCC工具链支持
  GNU Arm Embedded Toolchain Downloads:https://developer.arm.com/downloads/-/gnu-rm
  我这里选用的是“gcc-arm-none-eabi-10.3-2021.10-win32.exe”软件安装后会提示添加进系统的环境变量,若未提示添加至环境变量或使用的是全量压缩包,请自行添加至系统的环境变量中。检验方法为在任意一处调用CMD,在窗口打入:
  1. arm-none-eabi-gcc -v
  会在命令行窗口显示相应的gcc版本号等信息。
3.仿真支持01,J-Link v9(v7.62a)
  我这里选用了“国产”的J-Link V9作为相应的仿真器。其软件服务可以从其官网下载:
  J-Link Software and Documentation pack:
https://www.segger.com/downloads/jlink
  其最新版本的驱动已经支持了许多Geehy的芯片,若使用的是老版本的驱动需要添加Geehy芯片支持,添加方法请见本人之前的的分享:J-Link 添加Geehy APM32系列MCU
https://bbs.21ic.com/icview-3223010-1-1.html
4.仿真支持02,Geehy-Link(OpenOCD)
  Geehy-Link是一款基于CMSIS-DAP的仿真器,我们对这种类型的仿真器也可以使用OpenOCD来进行使用。若使用该服务需要我们进行一些操作,这部分内容请看后续内容。OpenOCD我们可以在其官网:
https://openocd.org/对其进行了解。其Windows的程序下载地址是:https://github.com/xpack-dev-tools/openocd-xpack/releases/。由于官方提供的为全量包(非安装包),我们解压至相应目录后需要把其添加至环境变量
  检验方法为在任意一处调用CMD,在窗口打入:

  1. openocd -v
  会在命令行窗口显示相应的OpenOCD版本号等信息。
  其支持APM32F1的芯片需我们额外做一些工作,请看后文。
5.APM32 F1 的SDK包
  Geehy提供的APM32F10x标准外设库是进行APM32F1开发的一个利器,我们可以在其官网进行下载。
  APM32F10x_SDK_V1.7:
https://geehy.com/uploads/tool/APM32F10x_SDK_V1.7.zip

  准备好以上环境后,我们将相应的软硬件配合使用,完成工程创建编译,下载与调试等功能。本文介绍的VSCode开发APM32F1主要思想是使用GCC编译相应的工程代码,以完成一个免费的开发环境,这里将涉及到一些编译的基础知识和文件的创建。下面先简单介绍一下从代码到固件中间经历了什么(代码编译链接过程)。

3 编译链接基础
  我们固件(一般来说最终产物是bin文件)的生成,主要经历了程序编写,编译和链接的过程。
Snipaste_2022-10-30_14-58-20.png
  其中我们比较关注的重要文件有以下几个:
   .c/c++文件:为我们编写好的代码,这里包括APM32F1的标准外设库代码以及我们自己编写的代码。
   .s/S文件:为芯片的启动文件,其内容一般包括芯片的中断向量号以及芯片启动前的一些初始化操作。
   .ld文件:为芯片的链接文件,其内容一般为代码存储的Flash大小,RAM大小以及一些数据段的保存位置。
   .bin/hex文件:为代码经过编译链接后的程序内容,其中hex文件带相应的地址及校验信息。
  我们需要完成GCC编译的支持,基础情况下我们要准备好相应的.c/c++、.s/.S、.ld文件。了解各个文件的基本功能,已经编写规范后,我们可以很简单的写出相应的文件内容(由于APM32F1的最新SDK中GCC编译支持文件尚未提供,这部分内容我们自行准备)。
3.1 启动文件编写
  GCC环境下,芯片的启动文件一般是完成芯片的内核,中断向量号的声明,以及一些数据段的初始化操作,最终在Reset_Handler函数中调用相应的系统时钟初始化函数(“SystemInit”函数)然后执行“main”函数。
  我们新建一个文件“startup_apm32f10x_hd.S”其代码具体为:
  1. .syntax unified
  2. .cpu cortex-m3
  3. .fpu softvfp
  4. .thumb

  5. .global g_pfnVectors
  6. .global Default_Handler

  7. /* start address for the initialization values of the .data section.
  8. defined in linker script */
  9. .word _sidata
  10. /* start address for the .data section. defined in linker script */
  11. .word _sdata
  12. /* end address for the .data section. defined in linker script */
  13. .word _edata
  14. /* start address for the .bss section. defined in linker script */
  15. .word _sbss
  16. /* end address for the .bss section. defined in linker script */
  17. .word _ebss

  18. /**
  19. * [url=home.php?mod=space&uid=247401]@brief[/url] This is the code that gets called when the processor first
  20. *         starts execution following a reset event. Only the absolutely
  21. *         necessary set is performed, after which the application
  22. *         supplied main() routine is called.
  23. * @param None
  24. * @retval : None
  25. */

  26. .section .text.Reset_Handler
  27. .weak Reset_Handler
  28. .type Reset_Handler, %function
  29. Reset_Handler:

  30. /* Copy the data segment initializers from flash to SRAM */
  31. ldr r0, =_sdata
  32. ldr r1, =_edata
  33. ldr r2, =_sidata
  34. movs r3, #0
  35. b LoopCopyDataInit

  36. CopyDataInit:
  37. ldr r4, [r2, r3]
  38. str r4, [r0, r3]
  39. adds r3, r3, #4

  40. LoopCopyDataInit:
  41. adds r4, r0, r3
  42. cmp r4, r1
  43. bcc CopyDataInit

  44. /* Zero fill the bss segment. */
  45. ldr r2, =_sbss
  46. ldr r4, =_ebss
  47. movs r3, #0
  48. b LoopFillZerobss

  49. FillZerobss:
  50. str  r3, [r2]
  51. adds r2, r2, #4

  52. LoopFillZerobss:
  53. cmp r2, r4
  54. bcc FillZerobss

  55. /* Call the clock system intitialization function.*/
  56.    bl  SystemInit
  57. /* Call static constructors */
  58.    bl __libc_init_array
  59. /* Call the application's entry point.*/
  60. bl main
  61. bx lr
  62. .size Reset_Handler, .-Reset_Handler

  63. /**
  64. * [url=home.php?mod=space&uid=247401]@brief[/url] This is the code that gets called when the processor receives an
  65. *         unexpected interrupt. This simply enters an infinite loop, preserving
  66. *         the system state for examination by a debugger.
  67. *
  68. * @param None
  69. * @retval : None
  70. */
  71.   .section .text.Default_Handler,"ax",%progbits
  72. Default_Handler:
  73. Infinite_Loop:
  74. b Infinite_Loop
  75. .size Default_Handler, .-Default_Handler
  76. /*
  77. *
  78. * The minimal vector table for a Cortex M3. Note that the proper constructs
  79. * must be placed on this to ensure that it ends up at physical address
  80. * 0x0000.0000.
  81. *
  82. **/
  83. .section .isr_vector,"a",%progbits
  84. .type g_pfnVectors, %object
  85. .size g_pfnVectors, .-g_pfnVectors


  86. g_pfnVectors:

  87. .word _estack
  88. .word Reset_Handler
  89. .word NMI_Handler
  90. .word HardFault_Handler
  91. .word MemManage_Handler
  92. .word BusFault_Handler
  93. .word UsageFault_Handler
  94. .word 0
  95. .word 0
  96. .word 0
  97. .word 0
  98. .word SVC_Handler
  99. .word DebugMon_Handler
  100. .word 0
  101. .word PendSV_Handler
  102. .word SysTick_Handler
  103. .word WWDT_IRQHandler
  104. .word PVD_IRQHandler
  105. .word TAMPER_IRQHandler
  106. .word RTC_IRQHandler
  107. .word FLASH_IRQHandler
  108. .word RCM_IRQHandler
  109. .word EINT0_IRQHandler
  110. .word EINT1_IRQHandler
  111. .word EINT2_IRQHandler
  112. .word EINT3_IRQHandler
  113. .word EINT4_IRQHandler
  114. .word DMA1_Channel1_IRQHandler
  115. .word DMA1_Channel2_IRQHandler
  116. .word DMA1_Channel3_IRQHandler
  117. .word DMA1_Channel4_IRQHandler
  118. .word DMA1_Channel5_IRQHandler
  119. .word DMA1_Channel6_IRQHandler
  120. .word DMA1_Channel7_IRQHandler
  121. .word ADC1_2_IRQHandler
  122. .word USBD_HP_CAN1_TX_IRQHandler
  123. .word USBD_LP_CAN1_RX0_IRQHandler
  124. .word CAN1_RX1_IRQHandler
  125. .word CAN1_SCE_IRQHandler
  126. .word EINT9_5_IRQHandler
  127. .word TMR1_BRK_IRQHandler
  128. .word TMR1_UP_IRQHandler
  129. .word TMR1_TRG_COM_IRQHandler
  130. .word TMR1_CC_IRQHandler
  131. .word TMR2_IRQHandler
  132. .word TMR3_IRQHandler
  133. .word TMR4_IRQHandler
  134. .word I2C1_EV_IRQHandler
  135. .word I2C1_ER_IRQHandler
  136. .word I2C2_EV_IRQHandler
  137. .word I2C2_ER_IRQHandler
  138. .word SPI1_IRQHandler
  139. .word SPI2_IRQHandler
  140. .word USART1_IRQHandler
  141. .word USART2_IRQHandler
  142. .word USART3_IRQHandler
  143. .word EINT15_10_IRQHandler
  144. .word RTC_Alarm_IRQHandler
  145. .word USBDWakeUp_IRQHandler
  146. .word TMR8_BRK_IRQHandler
  147. .word TMR8_UP_IRQHandler
  148. .word TMR8_TRG_COM_IRQHandler
  149. .word TMR8_CC_IRQHandler
  150. .word ADC3_IRQHandler
  151. .word FSMC_IRQHandler
  152. .word SDIO_IRQHandler
  153. .word TMR5_IRQHandler
  154. .word SPI3_IRQHandler
  155. .word UART4_IRQHandler
  156. .word UART5_IRQHandler
  157. .word TMR6_IRQHandler
  158. .word TMR7_IRQHandler
  159. .word DMA2_Channel1_IRQHandler
  160. .word DMA2_Channel2_IRQHandler
  161. .word DMA2_Channel3_IRQHandler
  162. .word DMA2_Channel4_5_IRQHandler
  163. .word 0                                  // Reserved
  164. .word USBD2_HP_CAN2_TX_IRQHandler        // USBD2 High Priority or CAN2 TX
  165. .word USBD2_LP_CAN2_RX0_IRQHandler       // USBD2 Low Priority or CAN2 RX0
  166. .word CAN2_RX1_IRQHandler                // CAN2 RX1
  167. .word CAN2_SCE_IRQHandler                // CAN2 SCE
  168. .word 0
  169. .word 0
  170. .word 0
  171. .word 0
  172. .word 0
  173. .word 0
  174. .word 0
  175. .word 0
  176. .word 0
  177. .word 0
  178. .word 0
  179. .word 0
  180. .word 0
  181. .word 0
  182. .word 0
  183. .word 0
  184. .word 0
  185. .word 0
  186. .word 0
  187. .word 0
  188. .word 0
  189. .word 0
  190. .word 0
  191. .word 0
  192. .word 0
  193. .word 0
  194. .word 0
  195. .word 0
  196. .word 0
  197. .word 0
  198. .word 0
  199. .word 0
  200. .word 0
  201. .word 0
  202. .word 0
  203. .word 0
  204. .word 0
  205. .word 0
  206. .word 0

  207. /*
  208. *
  209. * Provide weak aliases for each Exception handler to the Default_Handler.
  210. * As they are weak aliases, any function with the same name will override
  211. * this definition.
  212. *
  213. */

  214. .weak NMI_Handler
  215. .thumb_set NMI_Handler,Default_Handler

  216. .weak HardFault_Handler
  217. .thumb_set HardFault_Handler,Default_Handler

  218. .weak MemManage_Handler
  219. .thumb_set MemManage_Handler,Default_Handler

  220. .weak BusFault_Handler
  221. .thumb_set BusFault_Handler,Default_Handler

  222. .weak UsageFault_Handler
  223. .thumb_set UsageFault_Handler,Default_Handler

  224. .weak SVC_Handler
  225. .thumb_set SVC_Handler,Default_Handler

  226. .weak DebugMon_Handler
  227. .thumb_set DebugMon_Handler,Default_Handler

  228. .weak PendSV_Handler
  229. .thumb_set PendSV_Handler,Default_Handler

  230. .weak SysTick_Handler
  231. .thumb_set SysTick_Handler,Default_Handler

  232. .weak WWDT_IRQHandler
  233. .thumb_set WWDT_IRQHandler,Default_Handler

  234. .weak PVD_IRQHandler
  235. .thumb_set PVD_IRQHandler,Default_Handler

  236. .weak TAMPER_IRQHandler
  237. .thumb_set TAMPER_IRQHandler,Default_Handler

  238. .weak RTC_IRQHandler
  239. .thumb_set RTC_IRQHandler,Default_Handler

  240. .weak FLASH_IRQHandler
  241. .thumb_set FLASH_IRQHandler,Default_Handler

  242. .weak RCM_IRQHandler
  243. .thumb_set RCM_IRQHandler,Default_Handler

  244. .weak EINT0_IRQHandler
  245. .thumb_set EINT0_IRQHandler,Default_Handler

  246. .weak EINT1_IRQHandler
  247. .thumb_set EINT1_IRQHandler,Default_Handler

  248. .weak EINT2_IRQHandler
  249. .thumb_set EINT2_IRQHandler,Default_Handler

  250. .weak EINT3_IRQHandler
  251. .thumb_set EINT3_IRQHandler,Default_Handler

  252. .weak EINT4_IRQHandler
  253. .thumb_set EINT4_IRQHandler,Default_Handler

  254. .weak DMA1_Channel1_IRQHandler
  255. .thumb_set DMA1_Channel1_IRQHandler,Default_Handler

  256. .weak DMA1_Channel2_IRQHandler
  257. .thumb_set DMA1_Channel2_IRQHandler,Default_Handler

  258. .weak DMA1_Channel3_IRQHandler
  259. .thumb_set DMA1_Channel3_IRQHandler,Default_Handler

  260. .weak DMA1_Channel4_IRQHandler
  261. .thumb_set DMA1_Channel4_IRQHandler,Default_Handler

  262. .weak DMA1_Channel5_IRQHandler
  263. .thumb_set DMA1_Channel5_IRQHandler,Default_Handler

  264. .weak DMA1_Channel6_IRQHandler
  265. .thumb_set DMA1_Channel6_IRQHandler,Default_Handler

  266. .weak DMA1_Channel7_IRQHandler
  267. .thumb_set DMA1_Channel7_IRQHandler,Default_Handler

  268. .weak ADC1_2_IRQHandler
  269. .thumb_set ADC1_2_IRQHandler,Default_Handler

  270. .weak USBD_HP_CAN1_TX_IRQHandler
  271. .thumb_set USBD_HP_CAN1_TX_IRQHandler,Default_Handler

  272. .weak USBD_LP_CAN1_RX0_IRQHandler
  273. .thumb_set USBD_LP_CAN1_RX0_IRQHandler,Default_Handler

  274. .weak CAN1_RX1_IRQHandler
  275. .thumb_set CAN1_RX1_IRQHandler,Default_Handler

  276. .weak CAN1_SCE_IRQHandler
  277. .thumb_set CAN1_SCE_IRQHandler,Default_Handler

  278. .weak EINT9_5_IRQHandler
  279. .thumb_set EINT9_5_IRQHandler,Default_Handler

  280. .weak TMR1_BRK_IRQHandler
  281. .thumb_set TMR1_BRK_IRQHandler,Default_Handler

  282. .weak TMR1_UP_IRQHandler
  283. .thumb_set TMR1_UP_IRQHandler,Default_Handler

  284. .weak TMR1_TRG_COM_IRQHandler
  285. .thumb_set TMR1_TRG_COM_IRQHandler,Default_Handler

  286. .weak TMR1_CC_IRQHandler
  287. .thumb_set TMR1_CC_IRQHandler,Default_Handler

  288. .weak TMR2_IRQHandler
  289. .thumb_set TMR2_IRQHandler,Default_Handler

  290. .weak TMR3_IRQHandler
  291. .thumb_set TMR3_IRQHandler,Default_Handler

  292. .weak TMR4_IRQHandler
  293. .thumb_set TMR4_IRQHandler,Default_Handler

  294. .weak I2C1_EV_IRQHandler
  295. .thumb_set I2C1_EV_IRQHandler,Default_Handler

  296. .weak I2C1_ER_IRQHandler
  297. .thumb_set I2C1_ER_IRQHandler,Default_Handler

  298. .weak I2C2_EV_IRQHandler
  299. .thumb_set I2C2_EV_IRQHandler,Default_Handler

  300. .weak I2C2_ER_IRQHandler
  301. .thumb_set I2C2_ER_IRQHandler,Default_Handler

  302. .weak SPI1_IRQHandler
  303. .thumb_set SPI1_IRQHandler,Default_Handler

  304. .weak SPI2_IRQHandler
  305. .thumb_set SPI2_IRQHandler,Default_Handler

  306. .weak USART1_IRQHandler
  307. .thumb_set USART1_IRQHandler,Default_Handler

  308. .weak USART2_IRQHandler
  309. .thumb_set USART2_IRQHandler,Default_Handler

  310. .weak USART3_IRQHandler
  311. .thumb_set USART3_IRQHandler,Default_Handler

  312. .weak EINT15_10_IRQHandler
  313. .thumb_set EINT15_10_IRQHandler,Default_Handler

  314. .weak RTC_Alarm_IRQHandler
  315. .thumb_set RTC_Alarm_IRQHandler,Default_Handler

  316. .weak USBDWakeUp_IRQHandler
  317. .thumb_set USBDWakeUp_IRQHandler,Default_Handler

  318. .weak TMR8_BRK_IRQHandler
  319. .thumb_set TMR8_BRK_IRQHandler,Default_Handler

  320. .weak TMR8_UP_IRQHandler
  321. .thumb_set TMR8_UP_IRQHandler,Default_Handler

  322. .weak TMR8_TRG_COM_IRQHandler
  323. .thumb_set TMR8_TRG_COM_IRQHandler,Default_Handler

  324. .weak TMR8_CC_IRQHandler
  325. .thumb_set TMR8_CC_IRQHandler,Default_Handler

  326. .weak ADC3_IRQHandler
  327. .thumb_set ADC3_IRQHandler,Default_Handler

  328. .weak FSMC_IRQHandler
  329. .thumb_set FSMC_IRQHandler,Default_Handler

  330. .weak SDIO_IRQHandler
  331. .thumb_set SDIO_IRQHandler,Default_Handler

  332. .weak TMR5_IRQHandler
  333. .thumb_set TMR5_IRQHandler,Default_Handler

  334. .weak SPI3_IRQHandler
  335. .thumb_set SPI3_IRQHandler,Default_Handler

  336. .weak UART4_IRQHandler
  337. .thumb_set UART4_IRQHandler,Default_Handler

  338. .weak UART5_IRQHandler
  339. .thumb_set UART5_IRQHandler,Default_Handler

  340. .weak TMR6_IRQHandler
  341. .thumb_set TMR6_IRQHandler,Default_Handler

  342. .weak TMR7_IRQHandler
  343. .thumb_set TMR7_IRQHandler,Default_Handler

  344. .weak DMA2_Channel1_IRQHandler
  345. .thumb_set DMA2_Channel1_IRQHandler,Default_Handler

  346. .weak DMA2_Channel2_IRQHandler
  347. .thumb_set DMA2_Channel2_IRQHandler,Default_Handler

  348. .weak DMA2_Channel3_IRQHandler
  349. .thumb_set DMA2_Channel3_IRQHandler,Default_Handler

  350. .weak DMA2_Channel4_5_IRQHandler
  351. .thumb_set DMA2_Channel4_5_IRQHandler,Default_Handler

  352. .weak USBD2_HP_CAN2_TX_IRQHandler
  353. .thumb_set USBD2_HP_CAN2_TX_IRQHandler,Default_Handler

  354. .weak USBD2_LP_CAN2_RX0_IRQHandler
  355. .thumb_set USBD2_LP_CAN2_RX0_IRQHandler,Default_Handler

  356. .weak CAN2_RX1_IRQHandler
  357. .thumb_set CAN2_RX1_IRQHandler,Default_Handler

  358. .weak CAN2_SCE_IRQHandler
  359. .thumb_set CAN2_SCE_IRQHandler,Default_Handler

3.2 链接文件编写
  链接脚本文件一般为芯片的主要存储空间信息以及一些程序段保存位置信息,在了解其编写规范后编写也比较简单的将其写出。我们这里新建一个文件“apm32_flash.ld”,其内容为:
  1. /* Entry Point */
  2. ENTRY(Reset_Handler)

  3. /* Highest address of the user mode stack */
  4. _estack = 0x20020000;    /* end of 64K RAM */

  5. /* Generate a link error if heap and stack don't fit into RAM */
  6. _Min_Heap_Size = 0;      /* required amount of heap */
  7. _Min_Stack_Size = 0x200; /* required amount of stack */

  8. /* Specify the memory areas */
  9. MEMORY
  10. {
  11. FLASH (rx)     : ORIGIN = 0x08000000, LENGTH = 512K
  12. RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
  13. }

  14. /* Define output sections */
  15. SECTIONS
  16. {
  17. /* The startup code goes first into FLASH */
  18. .isr_vector :
  19. {
  20.   . = ALIGN(4);
  21.    KEEP(*(.isr_vector)) /* Startup code */
  22.   . = ALIGN(4);
  23. } >FLASH

  24. /* The program code and other data goes into FLASH */
  25. .text :
  26. {
  27.   . = ALIGN(4);
  28.    *(.text)           /* .text sections (code) */
  29.    *(.text*)          /* .text* sections (code) */
  30.    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
  31.    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
  32.    *(.glue_7)         /* glue arm to thumb code */
  33.    *(.glue_7t)        /* glue thumb to arm code */

  34.    KEEP (*(.init))
  35.    KEEP (*(.fini))

  36.   . = ALIGN(4);
  37.    _etext = .;        /* define a global symbols at end of code */
  38. } >FLASH


  39.   .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
  40.   .ARM : {
  41.    __exidx_start = .;
  42.      *(.ARM.exidx*)
  43.      __exidx_end = .;
  44.   } >FLASH

  45. .ARM.attributes : { *(.ARM.attributes) } > FLASH

  46. .preinit_array     :
  47. {
  48.    PROVIDE_HIDDEN (__preinit_array_start = .);
  49.    KEEP (*(.preinit_array*))
  50.    PROVIDE_HIDDEN (__preinit_array_end = .);
  51. } >FLASH
  52. .init_array :
  53. {
  54.    PROVIDE_HIDDEN (__init_array_start = .);
  55.    KEEP (*(SORT(.init_array.*)))
  56.    KEEP (*(.init_array*))
  57.    PROVIDE_HIDDEN (__init_array_end = .);
  58. } >FLASH
  59. .fini_array :
  60. {
  61.    PROVIDE_HIDDEN (__fini_array_start = .);
  62.    KEEP (*(.fini_array*))
  63.    KEEP (*(SORT(.fini_array.*)))
  64.    PROVIDE_HIDDEN (__fini_array_end = .);
  65. } >FLASH

  66. /* used by the startup to initialize data */
  67. _sidata = .;

  68. /* Initialized data sections goes into RAM, load LMA copy after code */
  69. .data : AT ( _sidata )
  70. {
  71.   . = ALIGN(4);
  72.    _sdata = .;        /* create a global symbol at data start */
  73.    *(.data)           /* .data sections */
  74.    *(.data*)          /* .data* sections */

  75.   . = ALIGN(4);
  76.    _edata = .;        /* define a global symbol at data end */
  77. } >RAM

  78. /* Uninitialized data section */
  79. . = ALIGN(4);
  80. .bss :
  81. {
  82.    /* This is used by the startup in order to initialize the .bss secion */
  83.    _sbss = .;         /* define a global symbol at bss start */
  84.    __bss_start__ = _sbss;
  85.    *(.bss)
  86.    *(.bss*)
  87.    *(COMMON)

  88.   . = ALIGN(4);
  89.    _ebss = .;         /* define a global symbol at bss end */
  90.    __bss_end__ = _ebss;
  91. } >RAM

  92. PROVIDE ( end = _ebss );
  93. PROVIDE ( _end = _ebss );

  94. /* User_heap_stack section, used to check that there is enough RAM left */
  95. ._user_heap_stack :
  96. {
  97.   . = ALIGN(4);
  98.   . = . + _Min_Heap_Size;
  99.   . = . + _Min_Stack_Size;
  100.   . = ALIGN(4);
  101. } >RAM

  102. /* Remove information from the standard libraries */
  103. /DISCARD/ :
  104. {
  105.    libc.a ( * )
  106.    libm.a ( * )
  107.    libgcc.a ( * )
  108. }
  109. }
  这里需要注意的是我的链接文件是基于APM32F103ZET6写的,若使用的是其他的芯片,需要把FLASH和RAM大小设置为相应芯片的大小,否则程序下载进芯片后将会无法运行

4 VSCode环境配置
  编写完成GCC环境下的启动文件和链接文件后,我们接下来将VSCode环境的配置,以使得我们可以在VSCode上流畅的进行开发。
4.1 Cortex-Debug 插件配置  
  打开扩展程序,找到Cortex-Debug 插件,右键选择“扩展设置”,配置相应工具链的路径。注意:路径复制后将文件目录分隔符“\”改为“\\”。
    1.配置Arm Toolchain路径。
    2.配置JLinkGDBServer路径。

    3.配置openocd路径。

image-20221030124843178.png
4.2 Embedded IDE插件配置
  打开扩展程序,找到Embedded IDE插件,右键选择“扩展设置”,配置相应工具链的路径。
    1.配置Arm Toolchain路径。
    2.配置JLink软件安装路径。
    3.配置openocd路径。

image-20221030124821770.png
5 OpenOCD支持
  若使用Geehy-Link调试,我们需要完成OpenOCD对APM32F1的支持,我们新建“apm32f1x.cfg”,完成对其的内容内容编辑后后将其保存至OpenOCD的安装路径下的“\share\openocd\scripts\target”中。
  apm32f1x.cfg的内容为:
  1. # script for apm32f1x family

  2. #
  3. # apm32 devices support both JTAG and SWD transports.
  4. #
  5. source [find target/swj-dp.tcl]
  6. source [find mem_helper.tcl]

  7. if { [info exists CHIPNAME] } {
  8.    set _CHIPNAME $CHIPNAME
  9. } else {
  10.    set _CHIPNAME apm32f1x
  11. }

  12. set _ENDIAN little

  13. # Work-area is a space in RAM used for flash programming
  14. # By default use 4kB.
  15. if { [info exists WORKAREASIZE] } {
  16.    set _WORKAREASIZE $WORKAREASIZE
  17. } else {
  18.    set _WORKAREASIZE 0x1000
  19. }

  20. # Allow overriding the Flash bank size
  21. if { [info exists FLASH_SIZE] } {
  22.     set _FLASH_SIZE $FLASH_SIZE
  23. } else {
  24.     # autodetect size
  25.     set _FLASH_SIZE 0
  26. }

  27. #jtag scan chain
  28. if { [info exists CPUTAPID] } {
  29.    set _CPUTAPID $CPUTAPID
  30. } else {
  31.       # this is the SW-DP tap id not the jtag tap id
  32.       set _CPUTAPID 0x2ba01477
  33. }

  34. swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
  35. dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu

  36. if {[using_jtag]} {
  37.    jtag newtap $_CHIPNAME bs -irlen 5
  38. }

  39. set _TARGETNAME $_CHIPNAME.cpu
  40. target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap

  41. $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0

  42. # flash size will be probed
  43. set _FLASHNAME $_CHIPNAME.flash
  44. flash bank $_FLASHNAME stm32f1x 0x08000000 $_FLASH_SIZE 0 0 $_TARGETNAME

  45. # JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz
  46. adapter speed 1000

  47. adapter srst delay 100
  48. if {[using_jtag]} {
  49. jtag_ntrst_delay 100
  50. }

  51. reset_config srst_nogate

  52. if {![using_hla]} {
  53.     # if srst is not fitted use SYSRESETREQ to
  54.     # perform a soft reset
  55.     cortex_m reset_config sysresetreq
  56. }

  57. $_TARGETNAME configure -event examine-end {
  58.         # DBGMCU_CR |= DBG_WWDT_STOP | DBG_IWDT_STOP |
  59.         #              DBG_STANDBY | DBG_STOP | DBG_SLEEP
  60.         mmw 0xE0042004 0x00000307 0
  61. }

  62. $_TARGETNAME configure -event trace-config {
  63.         # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync
  64.         # change this value accordingly to configure trace pins
  65.         # assignment
  66.         mmw 0xE0042004 0x00000020 0
  67. }
6 工程创建
  完成了比较核心的VSCode的插件配置,以及仿真器配置,我们接下来需要开始动手编写代码创建工程了,现在我们整体进度完成了百分之七八十咯。
6.1 准备源码目录
  我们在一个文件夹准备好我们的工程文件,我这里是基于“APM32F10x_SDK_V1.7.zip”中的“SysTick_TimeBase”例程直接去创建的,直接在其“Project”文件夹下新建一个“VSCode”文件夹,保存我们的工程文件及编译的中间过程文件。
image-20221030124917148.png
  然后我们把上文制作好的“apm32_flash.ld”和“startup_apm32f10x_hd.S”文件复制至“VSCode”文件夹内。
image-20221030125014373.png
6.2 新建工程
  完成源码的准备后我们开始使用“Embedded IDE”插件来完成我们的项目创建。
image-20221030130010763.png
  然后我们选择刚刚新建的项目路径保存我们的项目。
image-20221030130049089.png
  这个时候我们最终得到以下目录结构。
image-20221030130223132.png
  然后我们接着一步步完成我们的源码添加、宏定义声明、头文件包含、链接文件添加等操作。
    1.源码添加,右键点击“项目资源”,选择“虚拟文件夹”,添加“CMSIS”、“StdPeriphDriver”、“Application”和“Board”文件夹目录。然后添加相应的源文件。
    2.芯片支持配置,右键点击“芯片支持”,选择安装然后选择“From Disk”,选择Geehy提供的官方最新支持包。安装成功后芯片选型为“APM32F103ZE”。
image-20221030131344067.png
    3.“构建配置”选择“GCC”,CPU类型选择“Cortex-M3”,链接脚本路径选择我们的保存路径“../apm32_flash.ld”(这里选用相对路径)。
image-20221030133223385.png
    4.“构建器选项”中C/C++编译的C标准选择“c99”。
image-20221030133347599.png
    5.“烧录配置”这里选择“JLink”。芯片名称选择“APM32F103ZE”。接口类型可选“SWD”或“JTAG”,这里选择“SWD”。下载速度选择“8000kHz”。
image-20221030132723415.png
      若是选择使用Geehy-Link,则配置如下:
image-20221030135944465.png
    6.“项目属性”将我们源码的头文件路径以及宏定义添加进去。
image-20221030133557813.png


  至此我们的工程新建完毕。
7 编译与下载
  完成工程创建后我们就可以进行工程的编译与下载了。点击我们的工程,我们会发现出现四个图标,各个功能从左到右依次为:
image-20221030134122379.png
    构建,即编译工程。
    清理,即清除编译的中间过程文件。
    下载,即下载程序至芯片(需保证硬件连接正常)。
    重新构建,即重新编译工程,一般为修改了部分源码所使用。
  先进行“构建”,在终端窗口查看编译信息。
image-20221030134544040.png
  然后进行“下载”,此时会调用J-Link的相关下载程序以完成对芯片程序的下载。
image-20221030134720349.png
8 程序仿真
  完成了程序编译以及下载功能,MCU的仿真功能也是必不可少的。
  点击左侧的“仿真”按钮,进入仿真界面再点击绿色的仿真运行按钮,进入程序仿真界面。
image-20221030135249173.png
  在默认的仿真界面中主要分别为三个板块。
  最上面是程序运行控制按钮,有“单步运行”、“全速运行”和“退出仿真”等按钮。
  左侧是芯片的主要内部信息,有内核寄存器,变量查看,外设寄存器查看等窗口。
  居中的是源码,通过单击行号左侧,可以设置断点。
image-20221030135416324.png
9 总结
  以上便是本人在使用VSCode开发APM32F1的过程记录了,里面使用到了一些网络资源,仅供学习使用,如有侵权请联系本人删除。工程文件如下: APM32F10x_SDK_V1.7_VSCode_SysTick_TimeBase.zip (8.11 MB, 下载次数: 39)
  Geehy的芯片功能非常不错,玩起来还非常简单。各位在玩他们芯片都遇到了什么好玩的事情呢?欢迎在评论区一起讨论。






21小跑堂 发表于 2022-10-31 09:57 | 显示全部楼层
hi,感谢分享内容,原创不与其他活动共同进行噢~等极海那边结束后可以给您加原创标

评论

好的,Thanks♪(・ω・)ノ  发表于 2022-10-31 10:18
susutata 发表于 2022-10-31 13:59 来自手机 | 显示全部楼层
感谢分享,学习学习

评论

感谢支持  发表于 2022-11-2 09:57
感谢支持  发表于 2022-11-1 10:27
两只袜子 发表于 2022-11-2 15:24 来自手机 | 显示全部楼层
讲的真专业了

评论

谢谢支持,其实还不够,启动文件里面涉及的东西还是一知半解,现在只处于会用的状态。。。  发表于 2022-11-2 19:03
土司Apple 发表于 2022-11-4 17:04 | 显示全部楼层
这个还是挺好的。

评论

感谢支持,极海家的芯片还是可以的  发表于 2022-11-5 23:10
chenjun89 发表于 2022-11-4 20:52 来自手机 | 显示全部楼层
这个写的太详细了,可以申请原创了。

评论

感谢支持  发表于 2022-11-5 23:09
Gfan 发表于 2022-12-5 10:53 | 显示全部楼层
感谢参与

评论

感谢认可  发表于 2022-12-5 23:37
luobeihai 发表于 2022-12-7 23:26 | 显示全部楼层
写得很详细,感谢分享
110xia 发表于 2023-1-13 09:56 | 显示全部楼层
写得很详细

评论

感谢支持  发表于 2023-1-29 15:08
bartonalfred 发表于 2023-3-2 11:46 | 显示全部楼层
VScode开发的教程有吗?              
beacherblack 发表于 2023-3-4 21:58 | 显示全部楼层
这个如何在VScode搭建开发环境
deliahouse887 发表于 2023-3-5 11:01 | 显示全部楼层
VScode需要gcc开发的吗?
juliestephen 发表于 2023-3-10 15:35 | 显示全部楼层
这个如何在VScode搭建开发环境
您需要登录后才可以回帖 登录 | 注册

本版积分规则

43

主题

292

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部

43

主题

292

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部