木子剑
生命不熄,学习不止!

有了前面的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多天时间,功夫不负有心人!为自己加油

posted on 2020-11-04 23:51  木子剑  阅读(286)  评论(0编辑  收藏  举报