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