# Zephyr RTOS - Eample: Config STM32 Vendor HAL
[TOC]
## Notes
If you are migrating from STM32Cube ecosystem to Zephyr, temporarily reuse existing codes may be tempting, and here's how you can achieve it in Zephyr.
Note that personally I do **NOT** recommended to use STM32 HAL over Zephyr if you are starting a project fresh. Not only does mixing HAL functions with native Zephyr functions can lead to inconsistent states on both side, but Zephyr offers superior abstractions. It is hardware-agnostic, deterministic at compile-time, and can be configured independently in devicetree without regenerating the entire code base.
You can see the differences even from blinky examples on both side. `blinky` sample in Zephyr can be run immediately on almost every supported board --- witout any modification. On the contrary, code in STM32Cube environment is not guaranteed to be portable even between different product lines, and in generial won't work across project targeted different boards, at least without configuring manually in CubeMX.
## Instructions
The following instructions will take [blinky](https://docs.zephyrproject.org/latest/samples/basic/blinky/README.html) for example to show how to blink LED on Zephyr --- with STM32 HALs!
### Step 1: Add/Edit `Konfig` File
Take `blinky` sample for example, add an `Kconfig` to blinky directory:
```
$ tree blinky
blinky
├── CMakeLists.txt
├── Kconfig
├── README.rst
├── prj.conf
├── sample.yaml
└── src
└── main.c
```
Inside the `Kconfig` file, add the following contents (modified from README in [`zephyrproject-rtos/hal_stm32`](https://github.com/zephyrproject-rtos/hal_stm32)):
```kconfig
source "Kconfig.zephyr"
config APP_WITH_STM32_HAL
default y
bool
select USE_STM32_HAL_GPIO
```
If you already have a `Kconfig` file in the project, just append the contents above in your `Kconfig`. Note that no need to add `source "Kconfig.zephyr"` if you already source it else where in the `Kconfig`.
### Step 2: Choose what HAL to use in `Kconfig`
You may have to select Kconfig options if you want to use more HAL library than GPIO. For example, if you also want to use I2C and UART, you'll have to add their config repectively in `Kconfig`. The `Kconfig` would look like this:
```kconfig
source "Kconfig.zephyr"
config APP_WITH_STM32_HAL
default y
bool
select USE_STM32_HAL_GPIO
select USE_STM32_HAL_I2C
select USE_STM32_HAL_UART
```
You can look up configuration in [`menuconfig`](https://zephyrproject.org/troubleshoot-zephyr-like-a-pro-with-menuconfig/) or `guiconfig` to see what HALs are available. Usually the start with `USE_STM32_HAL_`.
### Step 3: Include STM32 HAL header in `main.c`
In your `main.c`, include header according to board you're using. For example, I'm using STM32F411RE NUCLEO, which is a board equipped with an STM32F4 series SoC. So I'll have to add the following line:
```c
#include <stm32f4xx_hal.h>
```
### Step 4: Start using HALs
Now you are good to use STM32 HALs. The following codes are excert from codes generated by STM32CubeIDE:
```c
#include <zephyr/zephyr.h>
#include <stm32f4xx_hal.h>
/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 1000
#define B1_Pin GPIO_PIN_13
#define B1_GPIO_Port GPIOC
#define USART_TX_Pin GPIO_PIN_2
#define USART_TX_GPIO_Port GPIOA
#define USART_RX_Pin GPIO_PIN_3
#define USART_RX_GPIO_Port GPIOA
#define LD2_Pin GPIO_PIN_5
#define LD2_GPIO_Port GPIOA
#define TMS_Pin GPIO_PIN_13
#define TMS_GPIO_Port GPIOA
#define TCK_Pin GPIO_PIN_14
#define TCK_GPIO_Port GPIOA
#define SWO_Pin GPIO_PIN_3
#define SWO_GPIO_Port GPIOB
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : B1_Pin */
GPIO_InitStruct.Pin = B1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : LD2_Pin */
GPIO_InitStruct.Pin = LD2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);
}
void main(void)
{
MX_GPIO_Init();
while (1) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
k_msleep(SLEEP_TIME_MS);
}
}
```
### Step 5: Build and Flash
Build the project with west:
```
$ west build -p --board nucleo_f411re
```
And then:
```
$ west flash
```
And you can see LED blinking!
## Conclusion
Note that from the moment you include `<stm32f4xx_hal.h>` header, you lose the merits of hardware independent abstraction offered by Zephyr. The code isn't guaranteed to work for hardware other than STM32F4 series.