有了前面的GPIO-HAL和LEDS的学习经验,这次学习button传感器会非常的简单。
阅读源码,得出下面信息:
\os\dev内核的,button-hal.c, button-hal.h, button-sensor.h文件
\MYdemo\user\src用户实现的,board-buttons.c文件
因为按键属于传感器类型,所以简单了解一下 \os\lib内核的sensors.c, sensors.h就可以了。
阅读到这里,我又有一种预感不妙,NND好像也不简单哦,不就是一个GPIO输入功能吗,NG系统为什么又搞这么复杂??
日期2020-11-04:
有个很好的教程ng4.5-develop\examples\dev\button-hal文件button-hal-example.c里面,演示了如何使用,
PROCESS(button_hal_example, "Button HAL Example"); AUTOSTART_PROCESSES(&button_hal_example); /*---------------------------------------------------------------------------*/ PROCESS_THREAD(button_hal_example, ev, data) { button_hal_button_t *btn; PROCESS_BEGIN(); btn = button_hal_get_by_index(0); printf("Button HAL example.\n"); printf("Device button count: %u.\n", button_hal_button_count); if(btn) { printf("%s on pin %u with ID=0, Logic=%s, Pull=%s\n", BUTTON_HAL_GET_DESCRIPTION(btn), btn->pin, btn->negative_logic ? "Negative" : "Positive", btn->pull == GPIO_HAL_PIN_CFG_PULL_UP ? "Pull Up" : "Pull Down"); } while(1) { PROCESS_YIELD(); if(ev == button_hal_press_event) { btn = (button_hal_button_t *)data; printf("Press event (%s)\n", BUTTON_HAL_GET_DESCRIPTION(btn)); if(btn == button_hal_get_by_id(BUTTON_HAL_ID_BUTTON_ZERO)) { printf("This was button 0, on pin %u\n", btn->pin); } } else if(ev == button_hal_release_event) { btn = (button_hal_button_t *)data; printf("Release event (%s)\n", BUTTON_HAL_GET_DESCRIPTION(btn)); } else if(ev == button_hal_periodic_event) { btn = (button_hal_button_t *)data; printf("Periodic event, %u seconds (%s)\n", btn->press_duration_seconds, BUTTON_HAL_GET_DESCRIPTION(btn)); if(btn->press_duration_seconds > 5) { printf("%s pressed for more than 5 secs. Do custom action\n", BUTTON_HAL_GET_DESCRIPTION(btn)); } } } PROCESS_END(); } /*---------------------------------------------------------------------------*/
还有一个\examples\MYdemo\user\inc的board.h有如下信息
/*---------------------------------------------------------------------------*/ /** \name SmartRF Button configuration 按键功能 * * Buttons on the SmartRF06 are connected as follows: * - BUTTON_SELECT -> PA3 * - BUTTON_LEFT -> PC4 * - BUTTON_RIGHT -> PC5 * - BUTTON_UP -> PC6 * - BUTTON_DOWN -> PC7 * @{ */ /** BUTTON_SELECT -> PA3 */ #define BUTTON_SELECT_PORT GPIO_A_NUM #define BUTTON_SELECT_PIN 3 #define BUTTON_SELECT_VECTOR GPIO_A_IRQn /** BUTTON_LEFT -> PC4 */ #define BUTTON_LEFT_PORT GPIO_C_NUM #define BUTTON_LEFT_PIN 4 #define BUTTON_LEFT_VECTOR GPIO_C_IRQn /** BUTTON_RIGHT -> PC5 */ #define BUTTON_RIGHT_PORT GPIO_C_NUM #define BUTTON_RIGHT_PIN 5 #define BUTTON_RIGHT_VECTOR GPIO_C_IRQn /** BUTTON_UP -> PC6 */ #define BUTTON_UP_PORT GPIO_C_NUM #define BUTTON_UP_PIN 6 #define BUTTON_UP_VECTOR GPIO_C_IRQn /** BUTTON_DOWN -> PC7 */ #define BUTTON_DOWN_PORT GPIO_C_NUM #define BUTTON_DOWN_PIN 7 #define BUTTON_DOWN_VECTOR GPIO_C_IRQn /* Notify various examples that we have Buttons */ #define PLATFORM_HAS_BUTTON 1 #define PLATFORM_SUPPORTS_BUTTON_HAL 1 /** @} */
我们再回看一下\user\src的board-buttons.c文件
#include "contiki.h" #include "dev/button-hal.h" /* - BUTTON_SELECT -> PA3 * - BUTTON_LEFT -> PC4 * - BUTTON_RIGHT -> PC5 * - BUTTON_UP -> PC6 * - BUTTON_DOWN -> PC7 /*--------------------------这里定义了5个按键--------------------------------*/ BUTTON_HAL_BUTTON(key_left, "Key Left", \ GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_LEFT_PORT, BUTTON_LEFT_PIN), \ GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_BUTTON_ZERO, true); BUTTON_HAL_BUTTON(key_right, "Key Right", \ GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_RIGHT_PORT, BUTTON_RIGHT_PIN), \ GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_BUTTON_ONE, true); BUTTON_HAL_BUTTON(key_up, "Key Up", \ GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_UP_PORT, BUTTON_UP_PIN), \ GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_BUTTON_TWO, true); BUTTON_HAL_BUTTON(key_down, "Key Down", \ GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_DOWN_PORT, BUTTON_DOWN_PIN), \ GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_BUTTON_THREE, true); BUTTON_HAL_BUTTON(key_select, "Key Select", \ GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_SELECT_PORT, BUTTON_SELECT_PIN), \ GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_BUTTON_FOUR, true); /*---------------------------------------------------------------------------*/ BUTTON_HAL_BUTTONS(&key_left, &key_right, &key_up, &key_down, &key_select); /*---------------------------------------------------------------------------*/ /** * @} * @} */
好像清楚了,不错的,有时间要测试一下这些功能!!
时间:2020-11-5
记得之前,我在CONTIKI 3.0有测试过BUTTONS的,回顾一下https://www.cnblogs.com/lijianGX/p/13181392.html
它的线程是这样的操作的,如果有EV传感器事件,如果DATA是LEFT产生的,则取反一次LED灯!
PROCESS_THREAD(cc2538_demo_process, ev, data) { PROCESS_BEGIN(); while(1) { PROCESS_YIELD(); if(ev == sensors_event) { if(data == &button_left_sensor)leds_toggle(LEDS_RED); } } PROCESS_END(); }
而在CONTIKI NG,功能明显更加强大了,确实NG有天生的优势
PROCESS_THREAD(button_hal_example, ev, data) { button_hal_button_t *btn; PROCESS_BEGIN(); btn = button_hal_get_by_index(0);//0号按键的查询,如果找不到,返回NULL while(1) { PROCESS_YIELD();//开始 if(ev == button_hal_press_event) {//如果是按下的事件 btn = (button_hal_button_t *)data;//指向按键的DATA地址 //查询按钮的文字描述 printf("Press event (%s)\n", BUTTON_HAL_GET_DESCRIPTION(btn)); //查询按钮的唯一ID,如果找不到,返回NULL if(btn == button_hal_get_by_id(BUTTON_HAL_ID_BUTTON_ZERO)) { printf("This was button 0, on pin %u\n", btn->pin); } } }//while(1) PROCESS_END();//结束,与PROCESS_BEGIN()配对 }
我这里只是作了简化,便于分析,可以看到,先是判断是不是有按键压下的事件,为什么呢?因为在NG里面,按键传感器有三大事件,按下事件, 释放事件和N秒保持的事件。
事件功能是非常的具体。然后确认对应的按键的ID号,ID号是唯一的,最后执行一些功能。甚至可以查询到CPU的PIN脚号,真是非常有想法的概念(人的思维真是一个好东西)!
进行NG 和3.0俩个版本对比时。NG操作按键模式好一点,难怪说NG是下一代物联网操作系统。
时间2020-11-14:
这个NG的button驱动,真难消化,真是要搞死人啊。。
用linux平台去make在ng4.5-develop\examples\dev\button-hal的button-hal-example.c,然后将.HEX烧与进CC2538芯片里面去,
测试5个按键功能完全正常,没有任何问题! 真香呀~~~~~~~~~~~~
用WINDOW平台,却很多问题,每一次按下按键后,老是死在HardFault_Handler里面,因为我有打印信息可以看到:
在我改写的startup-gcc.c启动文件里面,再者如果我打开看门狗,CPU会进行复位的重复打印初始信息,调试时一般
不开看门狗的。
void HardFault_Handler(void) { UARTprintf("HardFault_Handler\r\n"); while(1); }
于是我拿官方的源码,进行极限拆解,想看看到底是怎么回事,没想到有意外的收获!!哈哈
被我搞过的contiki-main.c
/*----------------------------加载应头文件-------------------------------------*/ #include "contiki.h" #include "soc.h"//新加入 #include "dev/uart.h"//新加入 #include "dev/button-hal.h"//新加入 #include "dev/serial-line.h"//新加入 #include "dev/ioc.h"//新加入 #include "dev/sys-ctrl.h"//新加入 /*---------------------------------------------------------------------------*/ int main(void) { ioc_init(); sys_ctrl_init(); clock_init(); process_init(); process_start(&etimer_process, NULL); ctimer_init(); uart_init(0); button_hal_init(); autostart_start(autostart_processes); while(1) { do { } while(process_run() > 0); } return 0; }
上面代码是可以正常linux平台直接MAKE的,将HEX文件烧进芯片里面去,测试效果
通过测试发现,原来button驱动,是通过ctimer进行完成的,ctimer是由etimer实现的。所以在IAR平台中,我要先全面测试一下这个ctimer是不是工作正常
最后把\examples\dev\button-hal的button-hal-example.c改成我在IAR的测试代码,在LINUX进行测试,发现也是没有问题的
/*---------------------------------------------------------------------------*/ PROCESS(button_hal_example, "Button HAL Example"); AUTOSTART_PROCESSES(&button_hal_example); /*---------------------------------------------------------------------------*/ PROCESS_THREAD(button_hal_example, ev, data) { button_hal_button_t *btn; PROCESS_BEGIN(); btn = button_hal_get_by_index(0); printf("Button HAL example.\n"); printf("Device button count: %u.\n", button_hal_button_count); if(btn) { printf("%s on pin %u with ID=0, Logic=%s, Pull=%s\n", BUTTON_HAL_GET_DESCRIPTION(btn), btn->pin, btn->negative_logic ? "Negative" : "Positive", btn->pull == GPIO_HAL_PIN_CFG_PULL_UP ? "Pull Up" : "Pull Down"); } while(1) { PROCESS_YIELD(); if(ev == button_hal_press_event) { printf("Press event\n"); } } PROCESS_END(); }
感觉接近成功了,..继续在WINDOWS平台IAR,研究NG的button驱动,希望早日结束它!
时间:2020-11-15
我在IAR的main.c都和LINUX都一样了:
/*----------------------------加载应头文件------------------------------------*/ #include "contiki.h" #include "soc.h"//新加入 #include "uart.h"//新加入 #include "button-hal.h"//新加入 #include "serial-line.h"//新加入 #include "ioc.h"//新加入 #include "sys-ctrl.h"//新加入 /*---------------------当前只是测试,同目录下有MAIN。C备份--------------------*/ void main(void) { //nvic_init(); //中断向量表,报错
ioc_init(); sys_ctrl_init(); clock_init(); process_init(); process_start(&etimer_process, NULL); ctimer_init(); uart_init(0); button_hal_init(); autostart_start(autostart_processes); while(1) { do { } while(process_run() > 0); } }
但是IAR仿真执行的时候还是这个样子:
以为是nvic_init()的问题,但是回头查看了之前LINUX的测试,也是没有初始化这个函数的。所以有点乱了,因为Button是有用到PORTC的
中断号,为什么LINUX时可以正常?另外LINUX是利用MAKEFILE进行MAKE的,会不会有区别?而且启动文件我自己改写了,会不会在IAR执行
存在问题?IAR环境和LINUX环境相差真大呀,难受中。。。。除了测试一下CTIMER外,估计还要硬着头皮去看一下Makefile文件了。
时间:2020-11-16
今天做了一个测试,原来病根在这里,因为这一次没有执行BUTTON按键功能,出现同样的HardFault问题!
contiki-ng-develop\examples\libs\timers的all-timers.c,是etimer, stimer, timer, rtimer是测试代码!
因为OS都是以时间轴为中心,按照一定的协议执行所有的EV事件的。这个必须,必须, 必须,要先测试通过才行!!
可以得出结论:不管移植哪个版本的CONTIKI,etimer, stimer, timer, rtimer这几个TIME是首要验证通过的。
为什么呢?timer正常了,说明clock.c 是PASS; 连带ETIMER也正常了。
RTIMER是细粒定时间器,优先级最高,实时性很强,用于网络通讯的!哪么CONTIKI不就是无线物联网通讯OS吗???
我在LINUX进行RTIMER测试,\examples\libs\timers的all-timers.c更改如下:
PROCESS(timer_process, "ETimer x Timer x STimer Process"); AUTOSTART_PROCESSES(&timer_process); static struct rtimer timer_rtimer; static char contt=0; /*---------------------------------------------------------------------------*/ void rtimer_callback(struct rtimer *timer, void *ptr) { printf("RTimer callback called:%d\r\n",contt++); rtimer_set(&timer_rtimer, RTIMER_NOW() + RTIMER_SECOND / 2, 0, rtimer_callback, NULL); } PROCESS_THREAD(timer_process, ev, data) { PROCESS_BEGIN(); rtimer_set(&timer_rtimer, RTIMER_NOW() + RTIMER_SECOND / 2, 0, rtimer_callback, NULL); while(1) { PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER); } PROCESS_END(); } /*---------------------------------------------------------------------------*/
\arch\cpu\cc2538下的rtimer-arch.c更改如下,主要ISR中断函数:
void rtimer_isr() { /* * If we were in PM1+, call the wake-up sequence first. This will make sure * that the 32MHz OSC is selected as the clock source. We need to do this * before calling the next rtimer_task, since the task may need the RF. */ static char contt=0; lpm_exit(); printf("rtimer_isr:%d\r\n",contt++); next_trigger = 0; NVIC_ClearPendingIRQ(SMT_IRQn); NVIC_DisableIRQ(SMT_IRQn); rtimer_run_next(); }
烧写进在CC2538芯片执行的效果如下:
不管在LINUX怎么玩,都是正常的~~~~~~~~~~~~
时间:2020-11-17
搞定了,哈哈!在WINDOWS IAR开发环境中,这个按键和RTIME全部搞定了,是start_up启动文件的问题,
LINUX下的启动文件要大改的。要不然在IAR没法运行的,能编译成功并不代表能正常执行!!!
从2020年-11月-04日到11月17日,花了10多天时间,功夫不负有心人!为自己加油