TA的每日心情 | 奋斗 前天 09:33 |
---|
签到天数: 208 天 连续签到: 2 天 [LV.7]常住居民III
|
本帖最后由 andeyqi 于 2024-1-12 09:52 编辑
RT-thread 系统已经适配完成,我们的设计中涉及的CAN/软件模拟的I2C都依赖PIN驱动,我们按照RT-thread 的规范适配PIN 驱动。在RT-Thread中,PIN(引脚)驱动层主要负责对硬件引脚进行控制和管理。该层的设计旨在提供一种通用的、可移植的方式,使应用程序能够方便地与硬件引脚进行交互,而不需要关心底层硬件的具体细节。PIN 驱动提供了硬件抽象层,使得相同的应用程序代码可以在不同的硬件上运行。开发者在移植 RT-Thread 到新的硬件时,只需要实现相应的 PIN 驱动,而无需修改应用层的代码。右侧链接为官方文档对PIN驱动架构的详细描述(RT-thread PIN驱动介绍)。根据官方文档的介绍可以知道,RT-thread PIN 驱动框架通过如下几个接口和BSP芯片的GPIO对接,我们按照要求适配好这几个接口就完成了PIN 驱动框架和硬件的对接,接口如下:
函数 | 描述 | rt_pin_get() | 获取引脚编号 | rt_pin_mode() | 设置引脚模式 | rt_pin_write() | 设置引脚电平 | rt_pin_read() | 读取引脚电平 | rt_pin_attach_irq() | 绑定引脚中断回调函数 | rt_pin_irq_enable() | 使能引脚中断 | rt_pin_detach_irq() | 脱离引脚中断回调函数 |
该接口通过传入pin 的name 获取pin 脚号,然后用户通过 pin number 完成GPIO 的输入、输出及中断控制。具体实现代码如下: - static rt_base_t s32kxxx_pin_get(const char * name)
- {
- int pin = 0;
- int hw_port_num, hw_pin_num = 0;
- int i, name_len;
- name_len = strlen(name);
- if ((name_len < 4) || (name_len >= 6))
- {
- return -1;
- }
- if ((name[0] != 'P') || (name[2] != '.'))
- {
- return -1;
- }
- if ((name[1] >= 'A') && (name[1] <= 'E'))
- {
- hw_port_num = (int)(name[1] - 'A');
- }
- else
- {
- return -1;
- }
- for (i = 3; i < name_len; i++)
- {
- hw_pin_num *= 10;
- hw_pin_num += name[i] - '0';
- }
- pin = PIN_NUM(hw_port_num, hw_pin_num);
- return pin;
- }
复制代码 使用的S32K146 芯片引脚是按照PTAx,我们对应成PA.x的形式,例如要获取PTA2 的pin number ,按照如下方式调用即可:
- pin_number = rt_pin_get("PA.2");
复制代码 该接口使用rt_pin_get()接口返回的pin number 配置GPIO 的输入输出属性,及上下拉配置,在S32K146上适配代码如下:- /**
- * @brief set pin mode
- * @param pin, mode
- * @retval None
- */
- static void s32kxxx_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
- {
- const struct pin_index *index = NULL;
- index = get_pin(pin);
- if (index == NULL)
- {
- return;
- }
- PINS_DRV_SetMuxModeSel(index->port,index->pin,PORT_MUX_AS_GPIO);
- switch(mode)
- {
- case PIN_MODE_OUTPUT:
- case PIN_MODE_OUTPUT_OD:
- PINS_DRV_SetPinDirection(index->gpio,index->pin,GPIO_OUTPUT_DIRECTION);
- break;
- case PIN_MODE_INPUT:
- PINS_DRV_SetPullSel(index->port,index->pin,PORT_INTERNAL_PULL_NOT_ENABLED);
- PINS_DRV_SetPinDirection(index->gpio,index->pin,GPIO_INPUT_DIRECTION);
- break;
- case PIN_MODE_INPUT_PULLUP:
- PINS_DRV_SetPullSel(index->port,index->pin,PORT_INTERNAL_PULL_UP_ENABLED);
- PINS_DRV_SetPinDirection(index->gpio,index->pin,GPIO_INPUT_DIRECTION);
- break;
- case PIN_MODE_INPUT_PULLDOWN:
- PINS_DRV_SetPullSel(index->port,index->pin,PORT_INTERNAL_PULL_DOWN_ENABLED);
- PINS_DRV_SetPinDirection(index->gpio,index->pin,GPIO_INPUT_DIRECTION);
- break;
- default:
- break;
- }
- }
复制代码 该接口使用rt_pin_get()接口返回的pin number 配置GPIO 的输出高低电平设置适配代码如下:
- /**
- * @brief pin write
- * @param pin, valuie
- * @retval None
- */
- static void s32kxxx_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
- {
- const struct pin_index *index = NULL;
- index = get_pin(pin);
- if (index == NULL)
- {
- return;
- }
- PINS_DRV_WritePin(index->gpio,index->pin,value);
- }
复制代码 该接口使用rt_pin_get()接口返回的pin number 读取 GPIO 的输入引脚状态,设置适配代码如下:该接口绑定rt_pin_get()接口返回的pin number 对应的中断回调函数,设置适配代码如下:
- /**
- * @brief pin irq attach
- * @param device, pin, mode
- * @retval None
- */
- static rt_err_t s32kxxx_pin_attach_irq(struct rt_device *device, rt_base_t pin,
- rt_uint8_t mode, void (*hdr)(void *args), void *args)
- {
- rt_base_t level;
- rt_int32_t hdr_index = -1;
- hdr_index = pin/32;
- if (hdr_index < 0 || hdr_index >= 5)
- {
- return -RT_EINVAL;
- }
- level = rt_hw_interrupt_disable();
- if (pin_irq_hdr_tab[hdr_index].pin == pin &&
- pin_irq_hdr_tab[hdr_index].hdr == hdr &&
- pin_irq_hdr_tab[hdr_index].mode == mode &&
- pin_irq_hdr_tab[hdr_index].args == args)
- {
- rt_hw_interrupt_enable(level);
- return RT_EOK;
- }
- if (pin_irq_hdr_tab[hdr_index].pin != -1)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EFULL;
- }
- pin_irq_hdr_tab[hdr_index].pin = pin;
- pin_irq_hdr_tab[hdr_index].hdr = hdr;
- pin_irq_hdr_tab[hdr_index].mode = mode;
- pin_irq_hdr_tab[hdr_index].args = args;
- rt_hw_interrupt_enable(level);
- return RT_EOK;
- }
复制代码 该接口解除绑定rt_pin_get()接口返回的pin number 对应的中断回调函数,设置适配代码如下:
- /**
- * @brief pin irq detach
- * @param device, pin
- * @retval None
- */
- static rt_err_t s32kxxx_pin_detach_irq(struct rt_device *device, rt_base_t pin)
- {
- rt_base_t level;
- rt_int32_t hdr_index = -1;
- hdr_index = pin/32;
- if (hdr_index < 0 || hdr_index >= 5)
- {
- return -RT_EINVAL;
- }
- level = rt_hw_interrupt_disable();
- if (pin_irq_hdr_tab[hdr_index].pin == -1)
- {
- rt_hw_interrupt_enable(level);
- return RT_EOK;
- }
- pin_irq_hdr_tab[hdr_index].pin = -1;
- pin_irq_hdr_tab[hdr_index].hdr = RT_NULL;
- pin_irq_hdr_tab[hdr_index].mode = 0;
- pin_irq_hdr_tab[hdr_index].args = RT_NULL;
- rt_hw_interrupt_enable(level);
- return RT_EOK;
- }
复制代码 该接口开启、关闭rt_pin_get()接口返回的pin number 对应的中断,设置适配代码如下:
- /**
- * @brief pin irq enable
- * @param device, pin, enabled
- * @retval None
- */
- static rt_err_t s32kxxx_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
- {
- const struct pin_index *index;
- rt_base_t level;
- rt_int32_t hdr_index = -1;
- port_interrupt_config_t trigger_mode;
- index = get_pin(pin);
- if (index == RT_NULL)
- {
- return -RT_EINVAL;
- }
- if (enabled == PIN_IRQ_ENABLE)
- {
- hdr_index = pin/32;
- if (hdr_index < 0 || hdr_index >= 5)
- {
- return -RT_EINVAL;
- }
- level = rt_hw_interrupt_disable();
- if (pin_irq_hdr_tab[hdr_index].pin == -1)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EINVAL;
- }
- switch (pin_irq_hdr_tab[hdr_index].mode)
- {
- case PIN_IRQ_MODE_RISING:
- trigger_mode = PORT_INT_RISING_EDGE;
- break;
- case PIN_IRQ_MODE_FALLING:
- trigger_mode = PORT_INT_FALLING_EDGE;
- break;
- case PIN_IRQ_MODE_RISING_FALLING:
- trigger_mode = PORT_INT_EITHER_EDGE;
- break;
- case PIN_IRQ_MODE_HIGH_LEVEL:
- trigger_mode = PORT_INT_LOGIC_ONE;
- break;
- case PIN_IRQ_MODE_LOW_LEVEL:
- trigger_mode = PORT_INT_LOGIC_ZERO;
- break;
- default:
- rt_hw_interrupt_enable(level);
- return -RT_EINVAL;
- }
- PINS_DRV_SetPinIntSel(index->port,index->pin,trigger_mode);
- INT_SYS_SetPriority(index->irq, 0);
- INT_SYS_EnableIRQ(index->irq);
- rt_hw_interrupt_enable(level);
- }
- else if (enabled == PIN_IRQ_DISABLE)
- {
- PINS_DRV_SetPinIntSel(index->port,index->pin,PORT_DMA_INT_DISABLED);
- INT_SYS_DisableIRQ(index->irq);
- }
- else
- {
- return -RT_EINVAL;
- }
- return RT_EOK;
- }
- const static struct rt_pin_ops s32kxxx_pin_ops =
- {
- .pin_mode = s32kxxx_pin_mode,
- .pin_write = s32kxxx_pin_write,
- .pin_read = s32kxxx_pin_read,
- .pin_get = s32kxxx_pin_get,
- .pin_attach_irq = s32kxxx_pin_attach_irq,
- .pin_detach_irq= s32kxxx_pin_detach_irq,
- .pin_irq_enable = s32kxxx_pin_irq_enable,
- };
- int rt_hw_pin_init(void)
- {
- int result;
- result = rt_device_pin_register("pin", &s32kxxx_pin_ops, RT_NULL);
- return result;
- }
- INIT_BOARD_EXPORT(rt_hw_pin_init);
复制代码至此已经适配好了PIN驱动。我们可以在此基础行控制GPIO完成CAN 收发器GPIO 模拟的I2C 接口的控制。
|
|