最近中文字幕2019高清,亚洲人成高清在线播放,男生淦哭男生图片动漫有字,国产亚洲精品九九久在线观看,无码av专区丝袜专区

體驗用VS Code 里 EIDE 進(jìn)行芯片開(kāi)發(fā)的快樂(lè )~ 開(kāi)源、免費、更簡(jiǎn)便、支

優(yōu)采云 發(fā)布時(shí)間: 2022-05-01 16:09

  體驗用VS Code 里 EIDE 進(jìn)行芯片開(kāi)發(fā)的快樂(lè )~ 開(kāi)源、免費、更簡(jiǎn)便、支

  

  出品 21ic論壇yang377156216

  網(wǎng)站:

  整體概覽

  作為 ARM Cotex M 系列內核的 32 位單片機開(kāi)發(fā)者,在平時(shí)工作中經(jīng)常會(huì )因為芯片平臺的不同而去切換各種開(kāi)發(fā)環(huán)境,幸好市面上有著(zhù)各式各樣的工具能夠滿(mǎn)足開(kāi)發(fā)攻城獅們的需求,大體上這些開(kāi)發(fā)環(huán)境可以分為幾大類(lèi):較為通用的集成環(huán)境(編輯、編譯、鏈接、下載和調試等功能合為一體),比較有代表性的有 Keil MDK、IAR EWARM、SEGGER Embedded Studio 、Mbed Studio 等等;廠(chǎng)家自制的專(zhuān)用 IDE ,主流的代表作有 STM32CubeIDE 、MCUXpresso IDE 、RT-Thread Studio 、MPLAB IDE 等等;還有一種 ”混搭版“ 的風(fēng)格,開(kāi)發(fā)者可以在 Eclipse 、VS Code 、Visual Studio 等工具中搭配 ARM GCC 編譯工具鏈進(jìn)行項目軟件開(kāi)發(fā)。在眼花繚亂的工具中,根據是否免費、編輯功能體驗度是否高、上手與熟悉難度是否適宜等因素綜合考慮,今天選擇了一種開(kāi)源、免費且更加簡(jiǎn)便的 VS Code +EIDE + GCC + J-Link 方式進(jìn)行 MM32F0144C6P 芯片的軟件開(kāi)發(fā)。接下來(lái)的內容整體可分為以下幾點(diǎn):

  一、單片機軟件開(kāi)發(fā)流程和其中一些知識點(diǎn)

  一個(gè) ARM Cortex M 系列內核的 MCU 軟件開(kāi)發(fā)者需要清楚完成一個(gè)軟件項目的大致流程是需經(jīng)過(guò)以下幾步的:

  編寫(xiě)代碼。通常是 C/C++ 語(yǔ)言,但是在考究執行效率的時(shí)候就得用到 ASM 匯編,講究面向對象的結構化編程時(shí)甚至用上 Python、Lua 等其它高級語(yǔ)言。

  將各種語(yǔ)言進(jìn)行編譯和鏈接最終生成機器二進(jìn)制文件。相信絕大部分人都親身體驗過(guò)這一步,在很多集成環(huán)境中就是一鍵 Build ,然后默認生成 hex 格式燒錄文件。

  燒錄和調試。一般燒錄方式分為 ISP 、ICP 和 IAP ,根據 MCU 的不同選擇的燒錄工具也不盡相同。有些廠(chǎng)商,例如國產(chǎn)的 STC,只支持串口方式的 ISP ,且配套的在線(xiàn)仿真調試器也是基于串口形式的;而 ARM 內核的大部分 MCU 都支持 JTAG/SWD 接口形式的 ICP 方式,配套的調試工具可以是 J-Link、U-Link、CMSIS DAP-Link 和 ST-Link 等等,也幾乎都有配套的上位機給予支持。

  運行程序?;窘?jīng)過(guò)一番調試后,最終能夠得到滿(mǎn)足功能需求的代碼了,此時(shí)終于可以結案交付了,當然,后面可能還會(huì )面對大大小小的 Bug ,還得繼續 “升級打怪”。

  

  以上內容簡(jiǎn)述了整個(gè)軟件開(kāi)發(fā)的流程,其中涉及到的編譯和鏈接這個(gè)知識點(diǎn)比較重要。為了對這些名詞有更深的理解,特意查了資料。通俗講,編譯器會(huì )將 C 程序轉換成一種機器能理解的符號形式的匯編語(yǔ)言程序,包括了各種偽指令和符號表,然后匯編器將這些代碼轉換成目標文件,包括了機器語(yǔ)言指令、數據和指令正確放入內存所需要的信息,最后由系統程序(鏈接編譯器) 將各個(gè)獨立匯編的機器語(yǔ)言程序組合起來(lái)并且解釋所有未定義的標記,直到生成可執行文件。這其中也會(huì )涉及到很多文件,比如后綴名為 .c / .s / .o / .a / .lib / .elf / .axf / .bin / .hex 等等文件,有些是中間文件,另外一些是結果可執行文件。以下這幅圖用于幫助理解這個(gè)過(guò)程:

  

  既然編譯鏈接這個(gè)過(guò)程有著(zhù)舉足輕重的地位,那市面上的又有哪些主流工具可供選擇呢?據了解,目前針對于 ARM平臺的主流編譯器主要有以下一些:

  

  用到比較多的 KEIL AC5/AC6 是閉源和收費的,編譯速度在大型項目上 AC6 非常有優(yōu)勢,它們都具備多種優(yōu)化等級可調,編出來(lái)的代碼大小較小且運行更為安全,另外也都可以在 ARM 官網(wǎng)單獨下載,比較適合用于產(chǎn)品開(kāi)發(fā)中;IAR 的 ICC 編譯器也更加高性能而被廣泛使用,在很多 benchmark 跑分測試中同顆芯片的運行結果效率都更高些,且編出來(lái)的代碼大小也適中;Keil MDK、IAR 等工具都是收費的,在使用中很可能牽扯到一定的版權問(wèn)題,而 GCC(GNU Compiler Collection)作為GNU計劃的一部分,**是完全免費的,這就是最大的優(yōu)勢**,盡管使用 GCC 是需要付出一定代價(jià)的——對編譯后造成的不良后果負全責(比如編譯出來(lái)的代碼量非常大,程序跑飛從而致使板級器件燒毀,系統死機崩潰導致丟失關(guān)鍵數據之類(lèi)的情況)。

  這里特別感謝硬漢大哥和傻孩子大哥針對各家編譯器做出的實(shí)測比較和探討,可參見(jiàn):

  二、VS Code 優(yōu)勢和 EIDE 插件介紹

  這里選擇 ARM GCC 交叉編譯工具鏈作為最重要的一環(huán),除了看重它開(kāi)源、免費、資料多等優(yōu)勢以外,更重要的是可以跨平臺。除了“內核”,那再來(lái)聊聊為什么選擇 VS Code 作為外殼吧。

  考慮 Windows 環(huán)境下能夠使用 Eclipse IDE for C/C++ Developers 來(lái)搭建 ARM 開(kāi)發(fā)環(huán)境,但是整個(gè) JAVA 環(huán)境占用了太大的 PC 資源,完整地安裝下來(lái)會(huì )非常臃腫,性?xún)r(jià)比不高,所以轉而會(huì )考慮一個(gè)跨平臺且非常流行的編輯器 VS Code ,其特點(diǎn)有:

  等等……

  好的開(kāi)發(fā)環(huán)境就像一把好刀,能讓我們開(kāi)發(fā)速度達到事半功倍,主流的就是對的,下圖顯示了 VS Code 的受歡迎程度:

  

  VS Code 里面的 EIDE 插件是個(gè)什么東西?很多人可能沒(méi)有接觸過(guò),不知道它能讓 KEIL 工程導入到 VS Code 中有多方便。下面來(lái)簡(jiǎn)單介紹。

  EIDE是 keil-assistant 插件的升級版,它們同屬一個(gè)開(kāi)發(fā)團隊,這是一款適用于 8051/STM8/Cortex-M/RISC-V 的單片機開(kāi)發(fā)環(huán)境。能夠在 VS Code 上提供 8051, STM8, Cortex-M, RISC-V 項目的開(kāi)發(fā), 編譯, 燒錄功能。通俗點(diǎn)說(shuō),它就是那個(gè)披上 VS Code 外衣然后可以將 GCC 工具、各種調試工具集大成的 “后來(lái)者”,有多種實(shí)用功能,能讓開(kāi)發(fā)工作變得更加簡(jiǎn)單高效。更多相關(guān)資源可以查看官方提供的文檔:#/ 。

  三、準備資源

  硬件資源如下:

  

  軟件資源如下:

  提示:本文中的展示基于 WIN10 64 位 PC 系統,用戶(hù)需要根據自己的電腦系統下載對應版本的資源。既可通過(guò)上述超鏈接獲取,也可直接使用壓縮包內的,為更好對照文中步驟實(shí)現環(huán)境搭建,建議盡量使用附件提供的資源包。工具軟件的安裝可以根據自己的習慣自定義路徑,也可以一直 next 選擇默認模式,記得將 gcc-arm-none-eabi 工具安裝路徑加入系統環(huán)境變量中,保險起見(jiàn)其它幾個(gè)也可以一并添加。

  

  由于官方不提供 MM32F0144C6P GCC 啟動(dòng)文件對應的鏈接文件,那自己動(dòng)手制作,思路是找到 STM32F030x 相關(guān)的文件來(lái)做修改,因為它們兩者外設資源上極為相似。要注意的是,需要根據 MM32F0144C6P 實(shí)際的中斷向量表去做修改。以下為修改好的 startup_mm32f0140_gcc.s 文件:

  /**<br />??******************************************************************************<br />??* @file? ?? ?startup_mm32f0140_gcc.s<br />??* @author? ? <br />??* @brief? ???MM32F014x devices vector table for GCC toolchain.<br />??*? ?? ?? ?? ?This module performs:<br />??*? ?? ?? ?? ?? ? - Set the initial SP<br />??*? ?? ?? ?? ?? ? - Set the initial PC == Reset_Handler,<br />??*? ?? ?? ?? ?? ? - Set the vector table entries with the exceptions ISR address<br />??*? ?? ?? ?? ?? ? - Branches to main in the C library (which eventually<br />??*? ?? ?? ?? ?? ?? ?calls main()).<br />??*? ?? ?? ?? ?After Reset the Cortex-M0 processor is in Thread mode,<br />??*? ?? ?? ?? ?priority is Privileged, and the Stack is set to Main.<br />??*<br />??******************************************************************************<br />??*/<br /><br /><br />??.syntax unified<br />??.cpu cortex-m0<br />??.fpu softvfp<br />??.thumb<br /><br /><br />.global g_pfnVectors<br />.global Default_Handler<br /><br /><br />/* start address for the initialization values of the .data section.<br />defined in linker script */<br />.word _sidata<br />/* start address for the .data section. defined in linker script */<br />.word _sdata<br />/* end address for the .data section. defined in linker script */<br />.word _edata<br />/* start address for the .bss section. defined in linker script */<br />.word _sbss<br />/* end address for the .bss section. defined in linker script */<br />.word _ebss<br /><br /><br />/**<br /> * @brief??This is the code that gets called when the processor first<br /> *? ?? ?? ? starts execution following a reset event. Only the absolutely<br /> *? ?? ?? ? necessary set is performed, after which the application<br /> *? ?? ?? ? supplied main() routine is called.<br /> * @param??None<br /> * @retval : None<br />*/<br /><br /><br />??.section .text.Reset_Handler<br />??.weak Reset_Handler<br />??.type Reset_Handler, %function<br />Reset_Handler:<br />??ldr? ?r0, =_estack<br />??mov? ?sp, r0? ?? ?? ? /* set stack pointer */<br /><br /><br />/* Copy the data segment initializers from flash to SRAM */<br />??ldr r0, =_sdata<br />??ldr r1, =_edata<br />??ldr r2, =_sidata<br />??movs r3, #0<br />??b LoopCopyDataInit<br /><br /><br />CopyDataInit:<br />??ldr r4, [r2, r3]<br />??str r4, [r0, r3]<br />??adds r3, r3, #4<br /><br /><br />LoopCopyDataInit:<br />??adds r4, r0, r3<br />??cmp r4, r1<br />??bcc CopyDataInit<br />??<br />/* Zero fill the bss segment. */<br />??ldr r2, =_sbss<br />??ldr r4, =_ebss<br />??movs r3, #0<br />??b LoopFillZerobss<br /><br /><br />FillZerobss:<br />??str??r3, [r2]<br />??adds r2, r2, #4<br /><br /><br />LoopFillZerobss:<br />??cmp r2, r4<br />??bcc FillZerobss<br /><br /><br />/* Call the clock system intitialization function.*/<br />??bl??SystemInit<br />/* Call static constructors */<br />??bl __libc_init_array<br />/* Call the application's entry point.*/<br />??bl main<br /><br /><br />LoopForever:<br />? ? b LoopForever<br /><br /><br /><br /><br />.size Reset_Handler, .-Reset_Handler<br /><br /><br />/**<br /> * @brief??This is the code that gets called when the processor receives an<br /> *? ?? ?? ?unexpected interrupt.??This simply enters an infinite loop, preserving<br /> *? ?? ?? ?the system state for examination by a debugger.<br /> *<br /> * @param??None<br /> * @retval : None<br />*/<br />? ? .section .text.Default_Handler,"ax",%progbits<br />Default_Handler:<br />Infinite_Loop:<br />??b Infinite_Loop<br />??.size Default_Handler, .-Default_Handler<br />/******************************************************************************<br />** The minimal vector table for a Cortex M0.??Note that the proper constructs<br />* must be placed on this to ensure that it ends up at physical address<br />* 0x0000.0000.<br />*******************************************************************************/<br />? ?.section .isr_vector,"a",%progbits<br />??.type g_pfnVectors, %object<br />??.size g_pfnVectors, .-g_pfnVectors<br /><br /><br /><br /><br />g_pfnVectors:<br />??.word??_estack<br />??.word??Reset_Handler<br />??.word??NMI_Handler<br />??.word??HardFault_Handler<br />??.word??0<br />??.word??0<br />??.word??0<br />??.word??0<br />??.word??0<br />??.word??0<br />??.word??0<br />??.word??SVC_Handler<br />??.word??0<br />??.word??0<br />??.word??PendSV_Handler<br />??.word??SysTick_Handler<br />??.word??WWDG_IRQHandler? ?? ?? ?? ?? ?? ? /* Window WatchDog? ?? ?? ?? ???*/<br />??.word??PVD_IRQHandler? ?? ?? ?? ?? ?? ???/* PVD through EXTI Line detect */<br />??.word??MIPI_IRQHandler? ?? ?? ?? ?? ?? ? /* MIPI? ?? ?? ?? ?? ?? ?? ?? ? */<br />??.word??FLASH_IRQHandler? ?? ?? ?? ?? ?? ?/* FLASH? ?? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??RCC_IRQHandler? ?? ?? ?? ?? ?? ???/* RCC? ?? ?? ?? ?? ?? ?? ?? ???*/<br />??.word??EXTI0_1_IRQHandler? ?? ?? ?? ?? ? /* EXTI Line 0 and 1? ?? ?? ?? ?*/<br />??.word??EXTI2_3_IRQHandler? ?? ?? ?? ?? ? /* EXTI Line 2 and 3? ?? ?? ?? ?*/<br />??.word??EXTI4_15_IRQHandler? ?? ?? ?? ?? ?/* EXTI Line 4 to 15? ?? ?? ?? ?*/<br />??.word??HWDIV_IRQHandler? ?? ?? ?? ?? ?? ?/* HWDIV? ?? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??DMA1_Channel1_IRQHandler? ?? ?? ? /* DMA1 Channel 1? ?? ?? ?? ?? ?*/<br />??.word??DMA1_Channel2_3_IRQHandler? ?? ???/* DMA1 Channel 2 and Channel 3 */<br />??.word??DMA1_Channel4_5_IRQHandler? ?? ???/* DMA1 Channel 4 and Channel 5 */<br />??.word??ADC1_COMP_IRQHandler? ?? ?? ?? ???/* ADC1 & COMP? ?? ?? ?? ?? ?? ?*/<br />??.word??TIM1_BRK_UP_TRG_COM_IRQHandler? ? /* TIM1 Break, Update, Trigger and Commutation */<br />??.word??TIM1_CC_IRQHandler? ?? ?? ?? ?? ? /* TIM1 Capture Compare? ?? ?? ?*/<br />??.word??TIM2_IRQHandler? ?? ?? ?? ?? ?? ? /* TIM2? ?? ?? ?? ?? ?? ?? ?? ? */<br />??.word??TIM3_IRQHandler? ?? ?? ?? ?? ?? ? /* TIM3? ?? ?? ?? ?? ?? ?? ?? ? */<br />??.word??0? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?/* Reserved? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??0? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?/* Reserved? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??TIM14_IRQHandler? ?? ?? ?? ?? ?? ?/* TIM14? ?? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??0? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?/* Reserved? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??TIM16_IRQHandler? ?? ?? ?? ?? ?? ?/* TIM16? ?? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??TIM17_IRQHandler? ?? ?? ?? ?? ?? ?/* TIM17? ?? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??I2C1_IRQHandler? ?? ?? ?? ?? ?? ? /* I2C1? ?? ?? ?? ?? ?? ?? ?? ? */<br />??.word??0? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?/* Reserved? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??SPI1_IRQHandler? ?? ?? ?? ?? ?? ? /* SPI1? ?? ?? ?? ?? ?? ?? ?? ? */<br />??.word??SPI2_IRQHandler? ?? ?? ?? ?? ?? ? /* SPI2? ?? ?? ?? ?? ?? ?? ?? ? */<br />??.word??UART1_IRQHandler? ?? ?? ?? ?? ?? ?/* UART1? ?? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??UART2_IRQHandler? ?? ?? ?? ?? ?? ?/* UART2? ?? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??UART3_IRQHandler? ?? ?? ?? ?? ?? ?/* UART3? ?? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??FLEX_CAN_IRQHandler? ?? ?? ?? ?? ?/* FLEX_CAN? ?? ?? ?? ?? ?? ?? ?*/<br />??.word??0? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?/* Reserved? ?? ?? ?? ?? ?? ?? ?*/<br /><br /><br /><br /><br />/*******************************************************************************<br />** Provide weak aliases for each Exception handler to the Default_Handler.<br />* As they are weak aliases, any function with the same name will override<br />* this definition.<br />********************************************************************************/<br /><br /><br />??.weak? ?? ?NMI_Handler<br />??.thumb_set NMI_Handler,Default_Handler<br /><br /><br />??.weak? ?? ?HardFault_Handler<br />??.thumb_set HardFault_Handler,Default_Handler<br /><br /><br />??.weak? ?? ?SVC_Handler<br />??.thumb_set SVC_Handler,Default_Handler<br /><br /><br />??.weak? ?? ?PendSV_Handler<br />??.thumb_set PendSV_Handler,Default_Handler<br /><br /><br />??.weak? ?? ?SysTick_Handler<br />??.thumb_set SysTick_Handler,Default_Handler<br /><br /><br />??.weak? ?? ?WWDG_IRQHandler<br />??.thumb_set WWDG_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?PVD_IRQHandler<br />??.thumb_set PVD_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?MIPI_IRQHandler<br />??.thumb_set MIPI_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?FLASH_IRQHandler<br />??.thumb_set FLASH_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?RCC_IRQHandler<br />??.thumb_set RCC_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?EXTI0_1_IRQHandler<br />??.thumb_set EXTI0_1_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?EXTI2_3_IRQHandler<br />??.thumb_set EXTI2_3_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?EXTI4_15_IRQHandler<br />??.thumb_set EXTI4_15_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?HWDIV_IRQHandler<br />??.thumb_set HWDIV_IRQHandler,Default_Handler<br />??<br />??.weak? ?? ?DMA1_Channel1_IRQHandler<br />??.thumb_set DMA1_Channel1_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?DMA1_Channel2_3_IRQHandler<br />??.thumb_set DMA1_Channel2_3_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?DMA1_Channel4_5_IRQHandler<br />??.thumb_set DMA1_Channel4_5_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?ADC1_COMP_IRQHandler<br />??.thumb_set ADC1_COMP_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?TIM1_BRK_UP_TRG_COM_IRQHandler<br />??.thumb_set TIM1_BRK_UP_TRG_COM_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?TIM1_CC_IRQHandler<br />??.thumb_set TIM1_CC_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?TIM2_IRQHandler<br />??.thumb_set TIM2_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?TIM3_IRQHandler<br />??.thumb_set TIM3_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?TIM14_IRQHandler<br />??.thumb_set TIM14_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?TIM16_IRQHandler<br />??.thumb_set TIM16_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?TIM17_IRQHandler<br />??.thumb_set TIM17_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?I2C1_IRQHandler<br />??.thumb_set I2C1_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?SPI1_IRQHandler<br />??.thumb_set SPI1_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?SPI2_IRQHandler<br />??.thumb_set SPI2_IRQHandler,Default_Handler<br />??<br />??.weak? ?? ?UART1_IRQHandler<br />??.thumb_set UART1_IRQHandler,Default_Handler<br />??<br />??.weak? ?? ?UART2_IRQHandler<br />??.thumb_set UART2_IRQHandler,Default_Handler<br /><br /><br />??.weak? ?? ?UART3_IRQHandler<br />??.thumb_set UART3_IRQHandler,Default_Handler<br />??<br />??.weak? ?? ?FLEX_CAN_IRQHandler<br />??.thumb_set FLEX_CAN_IRQHandler,Default_Handler<br />

  以下為修改好的 MM32F0144C6P_FLASH 文件:

  /*<br />*****************************************************************************<br />**<br />**??File? ?? ???: mm32_flash.ld<br />**<br />**??Abstract? ? : Linker script for MM32F0144C6P Device with<br />**? ?? ?? ?? ?? ? 64KByte FLASH, 16KByte RAM<br />**<br />**? ?? ?? ?? ?? ? Set heap size, stack size and stack location according<br />**? ?? ?? ?? ?? ? to application requirements.<br />**<br />**? ?? ?? ?? ?? ? Set memory bank area and size if external memory is used.<br />**<br />**??Target? ?? ?: MM32<br />**<br />**??Environment : VScode<br />**<br />**??Distribution: The file is distributed “as is,” without any warranty<br />**? ?? ?? ?? ?? ? of any kind.<br />*****************************************************************************<br />*/<br /><br /><br />/* Entry Point */<br />ENTRY(Reset_Handler)<br /><br /><br />/* Highest address of the user mode stack */<br />_estack = 0x20002000;? ? /* end of 16K RAM */<br /><br /><br />/* Generate a link error if heap and stack don't fit into RAM */<br />_Min_Heap_Size = 0x200;? ?? ?/* required amount of heap??*/<br />_Min_Stack_Size = 0x400; /* required amount of stack */<br /><br /><br />/* Specify the memory areas */<br />MEMORY<br />{<br />??FLASH (rx)? ?? ?: ORIGIN = 0x08000000, LENGTH = 64K<br />??RAM (xrw)? ?? ? : ORIGIN = 0x20000000, LENGTH = 8K<br />}<br /><br /><br />/* Define output sections */<br />SECTIONS<br />{<br />??/* The startup code goes first into FLASH */<br />??.isr_vector :<br />??{<br />? ? . = ALIGN(4);<br />? ? KEEP(*(.isr_vector)) /* Startup code */<br />? ? . = ALIGN(4);<br />??} >FLASH<br /><br /><br />??/* The program code and other data goes into FLASH */<br />??.text :<br />??{<br />? ? . = ALIGN(4);<br />? ? *(.text)? ?? ?? ???/* .text sections (code) */<br />? ? *(.text*)? ?? ?? ? /* .text* sections (code) */<br />? ? *(.glue_7)? ?? ?? ?/* glue arm to thumb code */<br />? ? *(.glue_7t)? ?? ???/* glue thumb to arm code */<br />? ? *(.eh_frame)<br /><br /><br />? ? KEEP (*(.init))<br />? ? KEEP (*(.fini))<br /><br /><br />? ? . = ALIGN(4);<br />? ? _etext = .;? ?? ???/* define a global symbols at end of code */<br />??} >FLASH<br /><br /><br />??/* Constant data goes into FLASH */<br />??.rodata :<br />??{<br />? ? . = ALIGN(4);<br />? ? *(.rodata)? ?? ?? ?/* .rodata sections (constants, strings, etc.) */<br />? ? *(.rodata*)? ?? ???/* .rodata* sections (constants, strings, etc.) */<br />? ? . = ALIGN(4);<br />??} >FLASH<br /><br /><br />??.ARM.extab? ?: { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH<br />??.ARM : {<br />? ? __exidx_start = .;<br />? ? *(.ARM.exidx*)<br />? ? __exidx_end = .;<br />??} >FLASH<br /><br /><br />??.preinit_array? ???:<br />??{<br />? ? PROVIDE_HIDDEN (__preinit_array_start = .);<br />? ? KEEP (*(.preinit_array*))<br />? ? PROVIDE_HIDDEN (__preinit_array_end = .);<br />??} >FLASH<br />??.init_array :<br />??{<br />? ? PROVIDE_HIDDEN (__init_array_start = .);<br />? ? KEEP (*(SORT(.init_array.*)))<br />? ? KEEP (*(.init_array*))<br />? ? PROVIDE_HIDDEN (__init_array_end = .);<br />??} >FLASH<br />??.fini_array :<br />??{<br />? ? PROVIDE_HIDDEN (__fini_array_start = .);<br />? ? KEEP (*(SORT(.fini_array.*)))<br />? ? KEEP (*(.fini_array*))<br />? ? PROVIDE_HIDDEN (__fini_array_end = .);<br />??} >FLASH<br /><br /><br />??/* used by the startup to initialize data */<br />??_sidata = LOADADDR(.data);<br /><br /><br />??/* Initialized data sections goes into RAM, load LMA copy after code */<br />??.data : <br />??{<br />? ? . = ALIGN(4);<br />? ? _sdata = .;? ?? ???/* create a global symbol at data start */<br />? ? *(.data)? ?? ?? ???/* .data sections */<br />? ? *(.data*)? ?? ?? ? /* .data* sections */<br /><br /><br />? ? . = ALIGN(4);<br />? ? _edata = .;? ?? ???/* define a global symbol at data end */<br />??} >RAM AT> FLASH<br /><br /><br />??/* Uninitialized data section */<br />??. = ALIGN(4);<br />??.bss :<br />??{<br />? ? /* This is used by the startup in order to initialize the .bss secion */<br />? ? _sbss = .;? ?? ?? ?/* define a global symbol at bss start */<br />? ? __bss_start__ = _sbss;<br />? ? *(.bss)<br />? ? *(.bss*)<br />? ? *(COMMON)<br /><br /><br />? ? . = ALIGN(4);<br />? ? _ebss = .;? ?? ?? ?/* define a global symbol at bss end */<br />? ? __bss_end__ = _ebss;<br />??} >RAM<br /><br /><br />??/* User_heap_stack section, used to check that there is enough RAM left */<br />??._user_heap_stack :<br />??{<br />? ? . = ALIGN(4);<br />? ? PROVIDE ( end = . );<br />? ? PROVIDE ( _end = . );<br />? ? . = . + _Min_Heap_Size;<br />? ? . = . + _Min_Stack_Size;<br />? ? . = ALIGN(4);<br />??} >RAM<br /><br /><br />??/* Remove information from the standard libraries */<br />??/DISCARD/ :<br />??{<br />? ? libc.a ( * )<br />? ? libm.a ( * )<br />? ? libgcc.a ( * )<br />??}<br /><br /><br />??.ARM.attributes 0 : { *(.ARM.attributes) }<br />}

  四、著(zhù)手搭建環(huán)境

  有了前面的準備就可以開(kāi)始配置整合開(kāi)發(fā)環(huán)境了。限于篇幅,這里略過(guò)在 VS Code 中下載安裝 EIDE 和 Cortex-Debug(可以讓 VS Code + EIDE 環(huán)境具備調試功能,非必須,可以使用 O-Zone 調試) 插件,可點(diǎn)擊參考超鏈接文章說(shuō)明,這里重點(diǎn)說(shuō)明一下關(guān)鍵配置。

  Cortex-Debug 插件的配置頁(yè)需要配置兩個(gè):Arm Toolchain Path 和 Jlink GDBserver Path。如果 GNU for Arm和 Jlink GDBserver Path 已經(jīng)加入到系統環(huán)境變量中,就可以不用配置了,另外如果在 EIDE 中已經(jīng)配置了 GCC 工具鏈和 J-Link 驅動(dòng)安裝路徑的話(huà),那在這也可以不再配置。而重點(diǎn)的 EIDE 插件配置信息需要根據自己安裝情況來(lái)填寫(xiě),主要包括以下幾個(gè)內容:

  以下為我的配置情況:

  

  

  

  1. 按照上述配置好后基本就可以使用 EIDE 和 Cortex-Debug 插件了

  2. 首先將準備好的 KEIL 工程導入到 EIDE 中,建立好一個(gè)位于 VS Code 中的 EIDE KEIL 工程,名為 KEILPRJ.code-workspace,該文件后面可以直接在 EIDE 中打開(kāi) 類(lèi)似 KEIL 的 .uvprojx 工程描述文件

  3. 然后在項目資源包中將原先 KEIL 的啟動(dòng)文件替換為 GCC 平臺的

  4. 添加 MM32F0140_DFP 芯片支持包并且選擇對應芯片 MM32F0144C6P

  5. Build 配置選擇 GCC ,鏈接腳本選擇準備好的 MM32F0144C6P_FLASH.ld 所在路徑

  6. 燒錄器選項選擇 Jlink,對應好芯片名稱(chēng)

  7. 項目屬性中的包含目錄將之前 KEIL 平臺相關(guān)的替換為 GCC 平臺的即可,不動(dòng)也沒(méi)關(guān)系因為就差了個(gè) .s 文件

  8. 其它按照默認配置即可,最后類(lèi)似在 KEIL 中操作一樣,一鍵編譯和燒錄

  9. 進(jìn)而轉到 Cortex-Debug 中進(jìn)行調試

  

  

  實(shí)際調試過(guò)程中,遇到 2 個(gè)問(wèn)題:

  第一個(gè)是由于意識里認為 MM32F0144C6P 芯片的 RAM 大小為 16KB ,在 .ld 鏈接文件中填寫(xiě)的也自然是 16KB,編譯燒錄后發(fā)現 LED 并未閃爍且串口無(wú)打印輸出,再使用 Cortex-Debug 調試,發(fā)現只要一運行 bl SystemInit 就會(huì )跳到 HardFault 里面去,心里面慌了,會(huì )是 .s 沒(méi)做好?再調試也未定位到問(wèn)題點(diǎn),于是轉而使用更加出色的 O-Zone 工具去調試,結合豐富的資源顯示 ,好不容易定位到一 PUSH 就會(huì )觸發(fā)錯誤,想來(lái)應該是棧大小和地址的問(wèn)題,最后查到原來(lái)使用的芯片應該是 8KB 的 RAM 才對。.s 文件并無(wú)問(wèn)題,改過(guò) .ld 文件后,解決。

  

  

  第二個(gè)是由于官方 lib samples 里面的串口重定向并未考慮到 GCC 平臺的使用,未適配好導致 printf 打印功能失效,于是使用了自定義 printf 方法改造了程序,解決。

  

  void vprint(const char *fmt, va_list argp){<br />? ? char string[200];<br />? ? if(0 < vsprintf(string,fmt,argp)) // build string<br />? ? {<br />? ?? ???for (int i = 0; i < strlen(string); i++) {<br />? ?? ?? ?? ?while ((UART1->CSR & UART_IT_TXIEN) == 0)<br />? ?? ?? ?? ?? ? ; // The loop is sent until it is finished<br />? ?? ?? ?? ?UART1->TDR = (u8)string[i];<br />? ?? ???}<br />? ? }<br />}<br /><br /><br />void my_printf(const char *fmt, ...) // custom printf() function{<br />? ? va_list argp;<br />? ? va_start(argp, fmt);<br />? ? vprint(fmt, argp);<br />? ? va_end(argp);<br />}

  操作到這里已經(jīng)可以盡情享受 VS Code 開(kāi)發(fā) MM32 MCU 的快樂(lè )了,既不用寫(xiě) makefile ,還能保持原來(lái)在 KEIL IDE 中的一些打包工程的操作習慣。另外,依托于工具強大的插件庫,我們還可以在 VS Code 中安裝配置 Astyle 格式化工具,使得代碼結構整潔美觀(guān)并且規范;還可以在 VS Code 部署好本地 Git 倉,利用 Github 進(jìn)行工程迭代管理,使得項目開(kāi)發(fā)變得井然有序;還可以使用 Settings Sync 插件進(jìn)行多臺 PC 機上的 VS Code 配置同步,再也不用擔心更換電腦后重新又得重新安裝配置之前一直使用的那么多插件了??偠灾?,VS Code 真香!

  五、編譯、燒錄及調試演示視頻

  實(shí)驗中導入的示例工程為自己移植的 nr micro shell 組件測試代碼,可以作為 Template 使用。編譯燒錄好程序后,開(kāi)發(fā)板的串口會(huì )輸出調試信息, LED 燈快速閃爍一會(huì )兒然后停止,此時(shí)可以使用 EIDE 中的串口工具終端與開(kāi)發(fā)板進(jìn)行指令交互,根據 LED 的亮滅狀態(tài)來(lái)看終端給開(kāi)發(fā)板發(fā)出的命令是否有被正確執行。

  

0 個(gè)評論

要回復文章請先登錄注冊


官方客服QQ群

微信人工客服

QQ人工客服


線(xiàn)

最近中文字幕2019高清,亚洲人成高清在线播放,男生淦哭男生图片动漫有字,国产亚洲精品九九久在线观看,无码av专区丝袜专区