tft每日頭條

 > 生活

 > stm32 如何降低功耗

stm32 如何降低功耗

生活 更新时间:2024-11-14 13:14:30

在上一篇文章《假美猴王之三極管與MOS管,誰是悟空,誰又是六耳猕猴》中我們講到了真假美猴王之三極管與MOS管的區别。今天來探讨一下武功秘籍的修煉,據說秘籍第一頁就寫道:欲練此功,必先自宮。意思就是說明一個道理,任何人要想成仙成佛,練就一身超神的本領,那麼是要付出的代價并做好準備工作的。

而今天我們的要探讨的主角STM32處理器也不例外,别看它運行起來玉樹臨風,似乎無所不能,啟動初期也要先苦練一番本領才行。那麼這一部分都做了哪些工作呢?

STM32這款處理器使用的是的arm的Cortex-M3内核,Cortex-M3内核有個特點就是在地址0x00000000存放的是全局的棧地址。緊接着從地址0x00000004執行(因為STM32是32位的處理器,一條指令正好對應4個字節),也就是從這個地址取出中斷向量表的地址,跳轉執行中斷處理函數。

stm32 如何降低功耗(欲練此功必先自宮之STM32彙編啟動)1

M3内核複位後程序執行過程

在前面文章《敢問路在何方,STM32邁出的第一步,卻注定了它非凡的一生》中我們有介紹通過BOOT0和BOOT1引腳高低電平的不同組合,對應者三種不同的啟動方式,同樣也就對應着三種地址的映射: Flash system memory就是将0x00000000映射到了0x08000000;System memory就是将0x00000000映射到了0x1FFF0000;SRAM就是将0x00000000映射到了0x20000000。選擇了哪種啟動方式就會把0地址映射到對應物理地址。同樣該區的物理地址最前面存放的就是棧地址和中斷向量表。

DATA __vector_table DCD sfe(CSTACK) DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler ; External Interrupts DCD WWDG_IRQHandler ; Window Watchdog DCD PVD_IRQHandler ; PVD through EXTI Line detect DCD RTC_IRQHandler ; RTC through EXTI Line DCD FLASH_IRQHandler ; FLASH DCD RCC_CRS_IRQHandler ; RCC_CRS DCD EXTI0_1_IRQHandler ; EXTI Line 0 and 1 DCD EXTI2_3_IRQHandler ; EXTI Line 2 and 3 DCD EXTI4_15_IRQHandler ; EXTI Line 4 to 15 DCD TSC_IRQHandler ; TSC DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 DCD DMA1_Channel2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 DCD DMA1_Channel4_5_6_7_IRQHandler ; DMA1 Channel 4, Channel 5, Channel 6 and Channel 7 DCD ADC1_COMP_IRQHandler ; ADC1, COMP1 and COMP2 DCD LPTIM1_IRQHandler ; LPTIM1 DCD 0 ; Reserved DCD TIM2_IRQHandler ; TIM2 DCD 0 ; Reserved DCD TIM6_DAC_IRQHandler ; TIM6 and DAC DCD 0 ; Reserved DCD 0 ; Reserved DCD TIM21_IRQHandler ; TIM21 DCD 0 ; Reserved DCD TIM22_IRQHandler ; TIM22 DCD I2C1_IRQHandler ; I2C1 DCD I2C2_IRQHandler ; I2C2 DCD SPI1_IRQHandler ; SPI1 DCD SPI2_IRQHandler ; SPI2 DCD USART1_IRQHandler ; USART1 DCD USART2_IRQHandler ; USART2 DCD RNG_LPUART1_IRQHandler ; RNG and LPUART1 DCD LCD_IRQHandler ; LCD DCD USB_IRQHandler ; USB

而中斷處理函數的第一個就是複位中斷處理函數Reset_Handler:

THUMB PUBWEAK Reset_Handler SECTION .text:CODE:NOROOT:REORDER(2) Reset_Handler LDR R0, =SystemInit BLX R0 LDR R0, =__iar_program_start BX R0 PUBWEAK NMI_Handler SECTION .text:CODE:NOROOT:REORDER(1)

我們看下默認的複位中斷處理函數裡邊都做了什麼事情,首先将SystemInit函數的首地址存放到R0寄存器裡邊,然後跳轉到R0寄存器的地址,即去執行IAR本身庫文件中的SystemInit函數進行相關初始化。然後将__iar_program_start函數的首地址存放到R0寄存器裡邊,然後跳轉到R0寄存器的地址,即去執行__iar_program_start函數。

那麼__iar_program_start這個函數在哪裡呢?沒錯,你在整個彙編文件中都沒有找到!這個文件在IAR的安裝目錄裡邊,具體的路徑是C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.2\arm\src\lib\thumb,我是将IAR裝在C:\Program Files (x86)目錄下的,大家根據自己情況查找。在thumb目錄下有個cstartup_M.s文件,文件代碼如下:

MODULE ?cstartup PUBLIC __iar_program_start EXTERN __cmain EXTERN __vector_table EXTWEAK __iar_init_core EXTWEAK __iar_init_vfp SECTION .text:CODE:REORDER(1) THUMB __iar_program_start: FUNCALL __iar_program_start, __iar_init_core BL __iar_init_core FUNCALL __iar_program_start, __iar_init_vfp BL __iar_init_vfp FUNCALL __iar_program_start, __cmain BL __cmain REQUIRE __vector_table END

__iar_program_start中分别調用了__iar_init_core,__iar_init_vfp和__cmain三個函數。前面兩個函數式弱函數,在工程中沒有定義,大家可以根據實際情況重寫這兩個函數。最後一個函數__cmain也在同目錄下的cmain.s中定義:

THUMB __cmain: ?main: ; Initialize segments. ; __segment_init and __low_level_init are assumed to use the same ; instruction set and to be reachable by BL from the ICODE segment ; (it is safest to link them in segment ICODE). FUNCALL __cmain, __low_level_init bl __low_level_init cmp r0,#0 beq ?l1 FUNCALL __cmain, __iar_data_init3 bl __iar_data_init3 ?l1: REQUIRE ?l3 SECTION .text:CODE:NOROOT(2) PUBLIC _main PUBLIC _call_main THUMB __iar_init$$done: ; Copy initialization is done ?l3: _call_main: MOVS r0,#0 ; No parameters FUNCALL __cmain, __iar_argc_argv BL __iar_argc_argv ; Maybe setup command line FUNCALL __cmain, main BL main _main: FUNCALL __cmain, exit BL exit END

其實最後就是進行了一個底層的初始化,然後就永久的跳轉到main.c文件中的main函數了。至此,彙編部分代碼結束,開始執行大家在main中編寫的代碼。

喜歡就在文末點個“關注”或者 “轉發”,這樣可以讓更多的人學習哦!!!

有問題評論一起交流學習進步! 感謝!

更多優質文章請點擊我的頭像,選擇“文章”标簽!

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved