搞完LED,搞Button,【\samples\basic\button】目录下有关于button的按钮,发现printk()函数在串口打印显示不正常。于是乎读有关UART的DataSheet想找到问题所在,读DataSheet太痛苦了,头晕眼花啊!体力活。最后发现显示不正常是波特率没设置对,cc3200在zephyr中默认设置为115200。虽然DataSheet白读了,但也了解不少东西,这就是学习。准备改写button例子,发现有必要先把GPIO搞清楚,于是先针对GPIO写一篇日志吧。
第二部分:GPIO驱动
要了解zephyr的GPIO首先要了解【\include\gpio.h】头文件,它是统一调用接口。代码比较多,但不必惊慌,只要抓住重点,这些代码就不难懂了。代码主要分为2个部分,下面一一讲解。
第一部分:引脚功能标志位宏定义
在之后的函数中,经常会看到一个整型flag参数,此参数代表了对应PIN所设置的功能状态。flag中的每个位都对应一种功能或状态,下面用一张图表示出来:
每个位的具体使用方法及功能请参考源码注释,已经足够详细。
第二部分主要关注核心代码gpio_driver_api结构体的声明:
struct gpio_driver_api {
gpio_config_t config; gpio_write_t write; gpio_read_t read; gpio_manage_callback_t manage_callback; gpio_enable_callback_t enable_callback; gpio_disable_callback_t disable_callback; gpio_api_get_pending_int get_pending_int; }; |
7个成员全为函数指针,这7个函数的第一个参数无一例外都是
struct device *port
|
device代表一个设备或端口,在【\include\device.h】中device定义如下:
/** * @brief 运行时每个设备实例在内存中的结构体 * @param device_config 创建时的配置信息 * @param driver_api 结构体指针,包含设备类型的API函数。 * 这些指针在初始化时由驱动填充。 * @param driver_data 驱动实例数据. 仅为驱动使用 */ struct device { struct device_config *config; const void *driver_api; void *driver_data; }; |
每个device的第二个成员*driver_api实际上就是gpio_driver_api结构体,
通过它就可以调用各个函数原型。
gpio_driver_api结构体中的每个函数指针都对应2个函数原型,一个是指针访问方式,一个是端口访问方式,这里只configure函数来讲解:
static
inline
int gpio_pin_configure(
struct device *port, uint8_t pin,
int flags) { const struct gpio_driver_api *api = port->driver_api; return api->config(port, GPIO_ACCESS_BY_PIN, pin, flags); } |
static
inline
int gpio_port_configure(
struct device *port,
int flags)
{ const struct gpio_driver_api *api = port->driver_api; return api->config(port, GPIO_ACCESS_BY_PORT, 0, flags); } |
可以看到,最终调用的还是各个设备自己定义的API函数。可以把gpio_driver_api理解为调用接口或代理。
具体到CC3200的API实现,可参考【
\drivers\gpio\
gpio_cc32xx.c】文件。代码就不具体讲解了,这里只需注意,回调函数被加到一个单向链表串了起来。可通过gpio_add_callback函数和gpio_remove_callback函数进行添加和删除。