Co to jest HAL? W ogólności biblioteka funkcji do obsługi zasobów mikrokontrolera. Zebrała się grupa mądrych, doświadczonych ludzi, pomyślała i napisała. Podoba mi się to rozwiązanie. Czyste, łatwe i przejrzyste. Jednak jak każde narzędzie musi być używane z głową. Ot pozorna funkcja do ustawiania stanu wyprowadzenia HAL_GPIO_WritePin()
. Robi rzecz niby trywialną, ale jak jest złożona. To jest jej rozkład na poszczególne instrukcje (procesora, po kompilacji):
420:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) 421:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** { 842 .loc 1 421 0 843 .cfi_startproc 844 @ args = 0, pretend = 0, frame = 8 845 @ frame_needed = 1, uses_anonymous_args = 0 846 @ link register save eliminated. 847 0000 80B4 push {r7} 848 .cfi_def_cfa_offset 4 849 .cfi_offset 7, -4 850 0002 83B0 sub sp, sp, #12 851 .cfi_def_cfa_offset 16 852 0004 00AF add r7, sp, #0 853 .cfi_def_cfa_register 7 854 0006 7860 str r0, [r7, #4] 855 0008 0B46 mov r3, r1 856 000a 7B80 strh r3, [r7, #2] @ movhi 857 000c 1346 mov r3, r2 858 000e 7B70 strb r3, [r7, #1] 422:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** /* Check the parameters */ 423:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** assert_param(IS_GPIO_PIN(GPIO_Pin)); 424:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** assert_param(IS_GPIO_PIN_ACTION(PinState)); 425:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** 426:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** if(PinState != GPIO_PIN_RESET) 859 .loc 1 426 0 860 0010 7B78 ldrb r3, [r7, #1] @ zero_extendqisi2 861 0012 002B cmp r3, #0 862 0014 03D0 beq .L55 427:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** { 428:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** GPIOx->BSRR = (uint32_t)GPIO_Pin; 863 .loc 1 428 0 864 0016 7A88 ldrh r2, [r7, #2] 865 0018 7B68 ldr r3, [r7, #4] 866 001a 9A61 str r2, [r3, #24] 429:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** } 430:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** else 431:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** { 432:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** GPIOx->BRR = (uint32_t)GPIO_Pin; 433:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** } 434:../Drivers/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_gpio.c **** } 867 .loc 1 434 0 868 001c 02E0 b .L57
To na oko kilkanaście instrukcji, z czego min 10 z nich jest wykonywane zawsze. Dlatego warto jest poznać procesor bliżej, instukcje assembera i warto przeglądać to, co generuje kompilator. Wiem, używając biblioteki możemy szybko osiągnąć efekt. Jednak HAL, jak każde narzędzie nie użyte z głową, wcale nie musi poprowadzić nas właściwą drogą. Załóżmy, że mamy przerwanie timera, które zgłaszane jest co 1ms. W przerwaniu naszym zadaniem jest ustawić 3 różne wyprowadzenia procesora w określone stany. Sprawa prosta. W procedurze przerwania umieszczamy trzy wywołania 3x funkcję HAL_GPIO_WritePin()
i sprawa jest załatwiona. Dokładamy kodu, do naszej aplikacji, dokładamy o okazuje się, że że coś się nie wyrabia. Mikrokontroler 72MHz… No skoro się nie wyrabia, bierzemy szybszy i sprawa załatwiona. A jednak moża było podejść inaczej i zastanowić się co tak naprawdę dzieje się w przerwaniu. 3 wywołania funkcji kosztują nasz 30 instrukcji procesora, w ciągu sekundy 30 tyś instrukcji procesora idących w przysłowiowy gwizdek. Gdyby zagłębić się w działanie procesora, to stosunkowo łatwo się dowiedzieć, że żeby zmienić stan wyprowadzenia trzeba wpisać jedynkę na odpowiednie miejsce w rejestrze BSRR lub BRR odpowiedniego bloku GPIO. Zatem zamiast wołania funkcji HAL można napisać GPIOC->BSRR=GPIO_PIN_5
lub GPIOC->BRR=GPIO_PIN_5
. Kompilator kompiluje ten kod do trzech instrukcji a nie kilkunastu. Dzięki temu procesor nie musi skakać do funkcji i nie wykonuje dodatkowych 30 tyś instrukcji w ciągu 1s. 30 tyś instrukcji przy zegarze 72MHz, to nie jest to jakiś dramatyczny zysk na przestrzeni 1s, ale wszystko zależy od aplikacji. Tak więc warto poza znajomością bibliotek znać procesor i kompilator na jego najniższym poziomie i korzystać z narzędzi w sposób rozsądny.