1、zephyr中调用hal库函数

背景介绍

最近在stm32上面跑zephyr,要使用i2c来获取pcf853的时钟,但是我们知道stm32f1系列的硬件i2c有点小问题,本人也没时间深究,就打算采用软件模拟的方式,硬件上使用了PA15-SCL PB3-SDA(画板子的时候,没留意,随便找了两根线,造孽呀!!!)

问题描述

我们知道,STM3210X系列的芯片在复位后,会将PA13/14/15 PB3/4默认配置为JTAG功能,在hal库开发的时候,将上述gpio做普通输入输出的时候,只需要调用如下宏即可

__HAL_AFIO_REMAP_SWJ_NOJTAG();

注:zephyr中使用的是hal库,不是标准库,标准库禁用JATG功能的代码可自行百度

解决方案

如果zephyr中可以直接调用hal的函数,那岂不是爽喂喂(我可真是个小机灵鬼,哈哈)。
开始尝试的时候,直接在cmake中将hal的头文件直接包进来,然后调用,发现依赖太多,直接编不过,然后一直踩坑。。。。。。。。话不多说,上代码!

其他说明

1、采用的单片机型号为:stm32f103c8t6,最便宜,哈哈!
2、本文只针对zephyr支持的soc(注意不是board哟),对于不支持的,可以自己倒腾

配置步骤

1、在下面路径中找到board的配置文件Kconfig.defconfig,对于自定义的板子,也找到该文件即可

zephyr/boards/arm/stm32_min_dev/Kconfig.defconfig

然后在该文件中添加一个配置项,如下:

config STM32F103_HAL_GPIO
	bool "stm32 hal gpio"
	select USE_STM32_HAL_GPIO_EX
	select USE_STM32_HAL_GPIO

下面深究一下原理

其中STM32F103_HAL_GPIO是自定义的配置项,USE_STM32_HAL_GPIO_EX是zephyr内置的,全局搜zephyr源码,可以找到在如下文件中:

zephyr/modules/Kconfig.stm32
config USE_STM32_HAL_GPIO
	bool
	help
	  Enable STM32Cube General-purpose I/Os (GPIO) HAL module driver

可以看到help里面也描述了,打开这个配置项之后,会使能hal module中gpio的driver
翻到这个文件的最上面,有一项需要注意:

config HAS_STM32CUBE
	bool
	select HAS_CMSIS_CORE
	depends on SOC_FAMILY_STM32

if HAS_STM32CUBE

config USE_STM32_HAL_ADC
	bool
	help
	  Enable STM32Cube Analog-to-Digital Converter (ADC) HAL module driver
.....

这里表示,只有定义了HAS_STM32CUBE之后,才能去使能下面的所有config选项
再全局搜一下HAS_STM32CUBE,能找到在soc中配置如下:

zephyr/soc/arm/st_stm32/stm32f1/Kconfig.series

config SOC_SERIES_STM32F1X
	bool "STM32F1x Series MCU"
	select ARM
	select CPU_CORTEX_M3
	select CPU_CORTEX_M_HAS_DWT
	select SOC_FAMILY_STM32
	select HAS_STM32CUBE
	select HAS_SWO
	help
	  Enable support for STM32F1 MCU series

原来我们在定义soc的时候,会打开HAS_STM32CUBE
这样就全部串起来了,终于满足了好奇宝宝


2、直接在项目下的prj.conf中使能上面步骤自定义的配置项即可

CONFIG_STM32F103_HAL_GPIO=y

就这么简单

3、测试的main文件如下:

#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/device.h>
#include <zephyr/fs/fs.h>
#include <zephyr/fs/littlefs.h>
#include <zephyr/logging/log.h>
#include <zephyr/storage/flash_map.h>

#include "stm32_ll_gpio.h" //该头文件下面详解

static const struct device *dev_gpioa = DEVICE_DT_GET(DT_NODELABEL(gpioa));
static const struct device *dev_gpiob = DEVICE_DT_GET(DT_NODELABEL(gpiob));

int main()
{
	gpio_pin_configure(dev_gpioa, 15, GPIO_OUTPUT);
	gpio_pin_configure(dev_gpiob, 3, GPIO_OUTPUT);
	__HAL_AFIO_REMAP_SWJ_NOJTAG();

	while(1)
	{
		gpio_pin_toggle(dev_gpiob, 6);	//翻转gpio
		gpio_pin_toggle(dev_gpioa, 15);
		k_msleep(100);
	}
	return 0;
}

然后波形就出来了,nice!!
在这里插入图片描述再啰嗦一下上面stm32_ll_gpio.h头文件,

xxx@xx-pc:~/myzephyr/temperature-control/modules/hal/stm32/stm32cube$ ls
CMakeLists.txt  stm32c0xx  stm32f1xx  stm32f3xx  stm32f7xx  stm32g4xx  stm32h7xx  stm32l1xx  stm32l5xx   stm32u5xx   stm32wbxx
common_ll       stm32f0xx  stm32f2xx  stm32f4xx  stm32g0xx  stm32h5xx  stm32l0xx  stm32l4xx  stm32mp1xx  stm32wbaxx  stm32wlxx

可以在如下路径中看到,在stm32cube目录中,除了hal库,还多了一个目录,common_ll,这个目录是zephyr为了组织hal的头文件,包装的一层,所以使用hal库的时候,直接调用这个目录中的头文件即可!

看来zephyr早就想到了这个问题,也为我们开发者提供了接口,只需要适配即可,先生大才!

有zephyr开发的问题可以一起讨论,诸君共勉!!!