ผมลองเปลี่ยนชื่อฟังชั่นใหม่เป็นอย่างนี้ void HAL_ADC_MspInit1(ADC_HandleTypeDef* hadc); แล้วมันไม่ทำงานนะ จอขาวเลย ผมเอา 1 ออก ก็ทำงานได้ปกติ แสดงว่าของเขาทำมาถูกแล้ว ผมก็ยังมือใหม่ยังต้องงม HAL ไปอีกนาน คุณ dec พอจะทราบการทำงานของมันมั๊ย ท่านใดพอจะทราบ ช่วยอธิบายหน่อยครับ
ถ้าลองไปดูฟังชั่น HAL_ADC_Init ในไฟล์ stm32fxxx_hal_adc.c ลองไล่ดูจะเห็นว่ามันมีการเรียก HAL_ADC_MspInit
ิอยู่ครับ เวลาเรียก HAL_ADC_Init มันจะไปเรียก HAL_ADC_MspInit ให้ด้วยเลย
แล้วทีนี้ถ้าเปลี่ยนชื่อเป็น HAL_ADC_MspInit1 มันยัง compile ได้ปกติ ไม่ได้ฟ้อง error อะไร ลองไล่ code ไปอีกหน่อย
จะเจอ
__weak void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hadc);
/* NOTE : This function should not be modified. When the callback is needed,
function HAL_ADC_MspInit must be implemented in the user file.
*/
}
มันคือ HAL_ADC_MspInit นั่นแหละครับ แต่มี attribute __weak นำหน้า (สำหรับ GNU C Compiler และ IAR ตัวใหม่ๆ จะใช้ __attribute__((weak)) )
มันหมายถึงถ้าทั้ง project ไม่มี HAL_ADC_MspInit อยู่เลย linker จะใช้ฟังชั่นนี้ แต่ถ้ามีการนิยาม HAL_ADC_MspInit ไว้ที่อื่นอีก
อันที่มี attribute __weak จะถูกตัดออก
การเขียน code ลักษณะนี้ยังใช้ในไฟล์ startup ที่มี vector table อีกด้วยครับ
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
....
ปกติเวลาเราจะประกาศฟังชั่น interrupt เราก็แค่ประกาศชื่อให้ตรงกับชื่อที่อยู่ใน vector table แต่ฟังชั่นไหน
ไม่ได้ประกาศมันก็ไม่ได้ error อะไรเพราะมันมี weak ฟังชั่นอยู่เหมือนกัน แต่จะแตกต่างจากภาษาซีนิดหน่อยตรง
assembly มันไม่ได้ประกาศฟังชั่นมาทั้งอัน มันประกาศ alias ของฟังชั่นได้
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
...
.weak CRS_IRQHandler
.thumb_set CRS_IRQHandler,Default_Handler
.weak I2C4_EV_IRQHandler
.thumb_set I2C4_EV_IRQHandler,Default_Handler
.weak I2C4_ER_IRQHandler
.thumb_set I2C4_ER_IRQHandler,Default_Handler
หรือพูดง่ายๆ ก็คือมันสามารถประกาศ Default_Handler ให้มีหลายๆ ชื่อได้นั่นเอง แล้วชื่่ออื่นๆ ก็มี attribute weak กำกับไว้
เวลาเราไปประกาศฟังชั่น interrupt ในไฟล์ stm32xxxx_it.c ซ้ำกับชื่อฟังชั่น interrupt ในไฟล์ startup มันก็จะตัดชื่อในไฟล์ startup ออก
แล้วไปใช้ฟังชั่น interrupt ในไฟล์ stm32xxxx_it.c แทน