本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。
- 本博文目录:
1、 认识alios-things架构
如下图,AliOS Things是一个分层 + 组件架构,可以较简单的移植到各类MCU及Connectivity SoC平台上。
CPU支持
这部分工作一般由AliOS Things内核团队完成,主要是各类CPU架构如ARM Cortex-M系列,C-Sky 80x系列的支持。 同时也欢迎社区爱好者及各类合作伙伴根据Rhino Porting Guide支持新的CPU,并贡献到github。BSP/HAL
这部分工作主要是芯片的驱动开发,以及和AliOS Things HAL的对接。 请参考HAL Porting Guide了解进一步细节。- CLI
CLI是AliOS Things的交互命令行组件,辅助开发者调试开发,强烈建议作为移植的第一个里程碑。CLI依赖于UART HAL,当移植完成后,开发者可以通过命令行和AliOS Things交互,查看系统状态。
- CLI
总结
- 对于我们这些开发者,就是在熟悉芯片厂家提供 SDK 之后,在 bsp/hal 层做适配工作。
2、开始移植
在编写底层文件时候,要对该芯片的SDK编程特别熟悉,当前是 esp8266 , 大家也可以去网上看看一些 gpio 口的 rtos sdk 使用代码。
第一步:熟悉 hal 层的头文件 gpio.h 。
该文件在主目录下面的
include
–>hal
–>gpio.h
这里,打开之后,我们发现有十几个方法定义,而且方法注释非常清楚,注意,这里面的头文件方法都是要我们根据芯片自行去实现的,所以一来要熟悉芯片SDK
编程,还要熟悉alios
的架构体系。
第二步:编写源文件 gpio.c 。
该上面提到要我们自己编写 gpio.c 源文件,所以我们要写一个!那么放在哪呢?又应该怎么写呢? 其实,我们按照 rots sdk来写驱动就行了。首先在目录下面的
platform
–>mcu
–>esp8266
–>hal
这个子文件夹,新建一个gpio.c
文件即可。
应该怎么写呢?下面我就列出部分我写的函数代码:
int32_t hal_gpio_init(aos_gpio_dev_t *gpio)
{
if (gpio == NULL)
{
return EIO;
}
if (gpio ->port > 16)
{
return EIO;
}
if (gpio->port == 16)
{
gpio16_output_conf();
return 0;
}
gpio_config_t io_conf;
/* disable interrupt */
io_conf.GPIO_IntrType = GPIO_PIN_INTR_DISABLE;
/* set mode */
if (gpio->config == OUTPUT_PUSH_PULL)
{
io_conf.GPIO_Mode = GPIO_Mode_Output;
}
else if ((gpio->config == OUTPUT_OPEN_DRAIN_NO_PULL) ||
(gpio->config == OUTPUT_OPEN_DRAIN_PULL_UP))
{
io_conf.GPIO_Mode = GPIO_Mode_Out_OD;
}
else if ((gpio->config == INPUT_PULL_UP) ||
(gpio->config == INPUT_PULL_DOWN) ||
(gpio->config == INPUT_HIGH_IMPEDANCE))
{
io_conf.GPIO_Mode = GPIO_Mode_Input;
}
/* bit mask of the pins */
io_conf.GPIO_Pin = BIT(gpio->port);
/* set pull-up mode */
io_conf.GPIO_Pullup = ((gpio->config == INPUT_PULL_UP) ||
(gpio->config == IRQ_MODE) ||
(gpio->config == OUTPUT_OPEN_DRAIN_PULL_UP))
? 1
: 0;
/* configure GPIO with the given settings */
gpio_config(&io_conf);
return 0;
}
- 配置 gpio 高电平输出:
int32_t hal_gpio_output_high(aos_gpio_dev_t *gpio)
{
if (gpio == NULL)
{
return EIO;
}
if (gpio->port == 16)
{
gpio16_output_set(enable);
uint32_t ret = gpio16_input_get();
if (ret != enable)
{
return EIO;
}
return 0;
}
GPIO_OUTPUT_SET(gpio->port, enable);
uint32_t ret = GPIO_INPUT_GET(gpio->port);
if (ret != enable)
{
return EIO;
}
return 0;
}
- 配置 gpio 低电平输出:
int32_t hal_gpio_output_low(aos_gpio_dev_t *gpio)
{
if (gpio == NULL)
{
return EIO;
}
if (gpio->port == 16)
{
gpio16_output_set(disable);
int ret = gpio16_input_get();
if (ret != disable)
{
return EIO;
}
return 0;
}
GPIO_OUTPUT_SET(gpio->port, disable);
int ret = GPIO_INPUT_GET(gpio->port);
if (ret != disable)
{
return EIO;
}
return 0;
}
- 中断初始化,这个我费了好大功夫终于成功了!
int32_t hal_gpio_enable_irq(aos_gpio_dev_t *gpio, gpio_irq_trigger_t trigger,
gpio_irq_handler_t handler, void *arg)
{
int32_t ret = EIO;
if (gpio == NULL || arg == NULL)
{
return EIO;
}
GPIO_ConfigTypeDef gpio_in_cfg; //Define GPIO Init Structure
gpio_in_cfg.GPIO_IntrType = (GPIO_INT_TYPE)trigger; //set the type
gpio_in_cfg.GPIO_Mode = GPIO_Mode_Input; //Input mode
gpio_in_cfg.GPIO_Pullup = GPIO_PullUp_EN;
gpio_in_cfg.GPIO_Pin = BIT(gpio->port); // Enable GPIO
gpio_config(&gpio_in_cfg); //Initialization function
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(gpio->port));//Forbidden ouput register
gpio_intr_handler_register(handler, arg);
_xt_isr_unmask(1 << ETS_GPIO_INUM); //enable
return 0;
}
第三步:添加依赖
- 以上步骤弄好了之后,还不是完善的,我们还需要把一些依赖关系弥补下,在目录下面的 platform –> mcu –> esp8266 下面的 esp8266.mk文件添加如下;
第四步:还有一些头文件需要包含进来。
以上步骤弄好了之后,基本是可以编译了。但是小徐发现,竟然在 SDK 报错找不到一些头文件,那么手动包含进来了;如果不报错,你就不用包含了。
在 gpio_register.h 包含 “esp8266/eagle_soc.h” ;
第五步:怎么使用。
代码比较简单,这里就贴出来。
int application_start(int argc, char *argv[])
{
/* gpio port config */
led.port = GPIO_LED_IO;
/* set as output mode */
led.config = OUTPUT_PUSH_PULL;
/* configure GPIO with the given settings */
hal_gpio_init(&led);
/* gpio port config */
trigger.port = GPIO_TRIGGER_IO;
/* set as output mode */
trigger.config = OUTPUT_PUSH_PULL;
/* configure GPIO with the given settings */
hal_gpio_init(&trigger);
/* input pin config */
input.port = GPIO_INPUT_IO;
/* set as interrupt mode */
input.config = IRQ_MODE;
/* configure GPIO with the given settings */
hal_gpio_init(&input);
/* gpio interrupt config */
hal_gpio_enable_irq(&input, IRQ_TRIGGER_FALLING_EDGE, gpio_isr_handler, (void *)GPIO_INPUT_IO);
aos_post_delayed_action(1000, app_trigger_low_action, NULL);
aos_loop_run();
return 0;
}
- 需要特别强调的是, esp8266发生串口中断之后,要清除中断,再使能中断。否则一直回调触发中断回调函数哦!
static void gpio_enable_irq()
{
hal_gpio_clear_irq(&input);
}
static void gpio_isr_handler(void *arg)
{
//for esp8266 ,need to disable interrupt 需要手动去停止中断
hal_gpio_disable_irq(&input);
//delay 2s ,then enable interrupt 延迟2秒后,再次使能中断
aos_post_delayed_action(2000, gpio_enable_irq, NULL);
}
3、分享环节
- 好了,全部工作已经做完了。下面分享下
gpio.c
和blink.c
文件吧。因为这个blink.c
只是针对esp8266
的,我就不push
到官方的仓库了,而gpio.c
我会会贡献到官方仓库的 。我就放在下面仓库子文件夹吧,需要的自取哈!
https://github.com/xuhongv/StudyInEsp8266/tree/master/25_ESP8266_AliosThings_Driver/blink