背景介绍
最近在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开发的问题可以一起讨论,诸君共勉!!!