查看: 815|回复: 0

Contiki简单的实例——led驱动

[复制链接]

该用户从未签到

发表于 2016-2-25 09:28:49 | 显示全部楼层 |阅读模式
分享到:
1、前言
     Contiki是一款小型开源,易于移植的多任务操作系统,专门为无线传感网设计,适合内存受限制的网络系统。
     由于Contiki需要适应多种平台 ,所以一般的驱动分为抽像接口和具体实现两部分。

     上一篇分析了Contiki的移植过程

  [EVAL-WSN]操作系统篇——Contiki移植分析,链接https://www.eeboard.com/bbs/forum.php?mod=viewthread&tid=46002&fromuid=23447

这里做个实例有个感观认识。

2、代码分析
    以最简单的led驱动为例:
     Contiki的led驱动可简单分为抽象接口和具体实现两部分
     LED 属于外设备,抽像接口一般在 contiki-2.5\core\dev\目录下,具体实现contiki-2.5\cpu\目录下(一般以-arch结尾)
2.2)抽像接口
leds.h

  • /**
  • * \defgroup leds LEDs API
  • *
  • * The LEDs API defines a set of functions for accessing LEDs for
  • * Contiki plaforms with LEDs.
  • *
  • * A platform with LED support must implement this API.
  • * @{
  • */

  • #ifndef __LEDS_H__
  • #define __LEDS_H__

  • void leds_init(void);

  • /**
  • * Blink all LEDs.
  • */
  • void leds_blink(void);

  • /*ledv 进行位设置 有且仅有以下四种可能
  • 0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x80
  • unsigned char leds_arch_get(void)
  • 等等,定义了 unsigned char = 8bit
  • 当修改即可以
  • */
  • #ifndef LEDS_GREEN
  • #define LEDS_GREEN 1
  • #endif /* LEDS_GREEN */
  • #ifndef LEDS_YELLOW
  • #define LEDS_YELLOW 2
  • #endif /* LEDS_YELLOW */
  • #ifndef LEDS_RED
  • #define LEDS_RED 4
  • #endif /* LEDS_RED */
  • #ifndef LEDS_BLUE
  • #define LEDS_BLUE LEDS_YELLOW
  • #endif /* LEDS_BLUE */

  • #ifdef LEDS_CONF_ALL
  • #define LEDS_ALL    LEDS_CONF_ALL
  • #else /* LEDS_CONF_ALL */
  • #define LEDS_ALL    7
  • #endif /* LEDS_CONF_ALL */

  • /**
  • * Returns the current status of all leds (respects invert)
  • */
  • unsigned char leds_get(void);
  • void leds_on(unsigned char leds);
  • void leds_off(unsigned char leds);
  • void leds_toggle(unsigned char leds);
  • void leds_invert(unsigned char leds);

  • /**
  • * Leds implementation 具体实现
  • */
  • void leds_arch_init(void);
  • unsigned char leds_arch_get(void);
  • void leds_arch_set(unsigned char leds);

  • #endif /* __LEDS_H__ */
复制代码
leds.c

  • #include "dev/leds.h"
  • #include "sys/clock.h"
  • #include "sys/energest.h"

  • static unsigned char leds, invert;
  • /*---------------------------------------------------------------------------*/
  • static void
  • show_leds(unsigned char changed)
  • {
  • if(changed & LEDS_GREEN) {
  •     /* Green did change */
  •     if((invert ^ leds) & LEDS_GREEN) {
  •      ENERGEST_ON(ENERGEST_TYPE_LED_GREEN);//方便跟踪节能设计了energest模块
  •     } else {
  •      ENERGEST_OFF(ENERGEST_TYPE_LED_GREEN);
  •     }
  • }
  • if(changed & LEDS_YELLOW) {
  •     if((invert ^ leds) & LEDS_YELLOW) {
  •      ENERGEST_ON(ENERGEST_TYPE_LED_YELLOW);
  •     } else {
  •      ENERGEST_OFF(ENERGEST_TYPE_LED_YELLOW);
  •     }
  • }
  • if(changed & LEDS_RED) {
  •     if((invert ^ leds) & LEDS_RED) {
  •      ENERGEST_ON(ENERGEST_TYPE_LED_RED);
  •     } else {
  •      ENERGEST_OFF(ENERGEST_TYPE_LED_RED);
  •     }
  • }
  • leds_arch_set(leds ^ invert);
  • }
  • /*---------------------------------------------------------------------------*/
  • void
  • leds_init(void)
  • {
  • leds_arch_init();
  • leds = invert = 0;
  • }
  • /*---------------------------------------------------------------------------*/
  • void
  • leds_blink(void)
  • {
  • /* Blink all leds. */
  • unsigned char inv;
  • inv = ~(leds ^ invert);
  • leds_invert(inv);

  • clock_delay(400);

  • leds_invert(inv);
  • }
  • /*---------------------------------------------------------------------------*/
  • unsigned char
  • leds_get(void) {
  • return leds_arch_get();
  • }
  • /*---------------------------------------------------------------------------*/
  • void
  • leds_on(unsigned char ledv)
  • {
  • unsigned char changed;
  • changed = (~leds) & ledv;
  • leds |= ledv;
  • show_leds(changed);
  • }
  • /*---------------------------------------------------------------------------*/
  • void
  • leds_off(unsigned char ledv)
  • {
  • unsigned char changed;
  • changed = leds & ledv;
  • leds &= ~ledv;
  • show_leds(changed);
  • }
  • /*---------------------------------------------------------------------------*/
  • void
  • leds_toggle(unsigned char ledv)
  • {
  • leds_invert(ledv);
  • }
  • /*---------------------------------------------------------------------------*/
  • /*   invert the invert register using the leds parameter */
  • void
  • leds_invert(unsigned char ledv) {
  • invert = invert ^ ledv;
  • show_leds(ledv);
  • }
  • /*---------------------------------------------------------------------------*/
复制代码
在面对用户层时只调用
void leds_init(void);
void leds_blink(void);
unsigned char leds_get(void);
void leds_on(unsigned char leds);
void leds_off(unsigned char leds);
void leds_toggle(unsigned char leds);
void leds_invert(unsigned char leds);

这么多函数公点在于调用show_leds函数
除屏蔽硬件层的影响外,还有一个更重要的意义就是进行跟踪节能统计与优化(energest模块的功能)


     2.2)具体实现部分
contiki-2.5\cpu\arm\aducrf101\leds-arch.c
  contiki提供了控制LED的三大接口,分别是:

    void leds_arch_init(void)    LED初始化函数
    unsigned char leds_arch_get(void) LED状态获取函数
    void leds_arch_set(unsigned char leds)    LED状态设置函数
    各LED状态按位排列,例如最低位为LED1的状态,最低位为1则LED点亮,最低位为0则LED熄灭。以此类推。



  • #include "contiki-conf.h"
  • #include "dev/leds.h"
  • #include "device.h"
  • #include "gpio.h"


  • #define LED_ARCH_RED   GPIO_LED_RED //P1.2
  • #define LED_ARCH_GREEN GPIO_LED_GREEN //P4.2
  • #define LED_ARCH_BLUE GPIO_LED_BLUE //P4.0

  • void leds_arch_init(void)
  • {
  •     //pADI_GP4->GPCON |= GP4CON_CON0_GPIO | GP4CON_CON1_GPIO | GP4CON_CON2_GPIO | GP4CON_CON3_GPIO;
  •     //pADI_GP4->GPOEN |= GP4OEN_OEN0_OUT | GP4OEN_OEN1_OUT | GP4OEN_OEN2_OUT | GP4OEN_OEN3_OUT;
  •     //pADI_GP4->GPSET |= GP4SET_SET0_SET | GP4SET_SET1_SET | GP4SET_SET2_SET | GP4SET_SET3_SET;
  •     pADI_GP4->GPCON |= GP4CON_CON0_GPIO | GP4CON_CON2_GPIO ;
  •     pADI_GP4->GPOEN |= GP4OEN_OEN0_OUT | GP4OEN_OEN2_OUT ;
  •     pADI_GP4->GPSET |= GP4SET_SET0_SET | GP4SET_SET2_SET ;

  •     // For RED LED on BUNCH Rev-A
  •     pADI_GP1->GPCON |= GP1CON_CON2_GPIO;
  •     pADI_GP1->GPOEN |= GP1OEN_OEN2_OUT;
  •     pADI_GP1->GPCLR |= GP1CLR_CLR2_CLR;
  • }

  • unsigned char leds_arch_get(void)
  • {

  • return ((pADI_GP1->GPOUT & GP1OUT_OUT2) ? 0 : LEDS_RED)
  • | ((pADI_GP4->GPOUT & GP4OUT_OUT2) ? 0 : LEDS_GREEN)
  • | ((pADI_GP4->GPOUT &GP1OUT_OUT0) ? 0 : LEDS_BLUE);

  • }

  • void leds_arch_set(unsigned char leds)
  • {
  • if(leds & LEDS_RED)   { pADI_GP1->GPCLR |= GP1CLR_CLR2; } else { pADI_GP1->GPSET |= GP1SET_SET2_SET; }
  • if(leds & LEDS_GREEN) { pADI_GP4->GPCLR |= GP4CLR_CLR2; } else { pADI_GP4->GPSET |= GP4SET_SET2_SET; }
  • if(leds & LEDS_BLUE) { pADI_GP4->GPCLR |= GP4CLR_CLR0; } else { pADI_GP4->GPSET |= GP4SET_SET0_SET; }
  • }#include "contiki-conf.h"
  • #include "dev/leds.h"
  • #include "device.h"
  • #include "gpio.h"


  • #define LED_ARCH_RED   GPIO_LED_RED //P1.2
  • #define LED_ARCH_GREEN GPIO_LED_GREEN //P4.2
  • #define LED_ARCH_BLUE GPIO_LED_BLUE //P4.0

  • void leds_arch_init(void)
  • {
  •     //pADI_GP4->GPCON |= GP4CON_CON0_GPIO | GP4CON_CON1_GPIO | GP4CON_CON2_GPIO | GP4CON_CON3_GPIO;
  •     //pADI_GP4->GPOEN |= GP4OEN_OEN0_OUT | GP4OEN_OEN1_OUT | GP4OEN_OEN2_OUT | GP4OEN_OEN3_OUT;
  •     //pADI_GP4->GPSET |= GP4SET_SET0_SET | GP4SET_SET1_SET | GP4SET_SET2_SET | GP4SET_SET3_SET;
  •     pADI_GP4->GPCON |= GP4CON_CON0_GPIO | GP4CON_CON2_GPIO ;
  •     pADI_GP4->GPOEN |= GP4OEN_OEN0_OUT | GP4OEN_OEN2_OUT ;
  •     pADI_GP4->GPSET |= GP4SET_SET0_SET | GP4SET_SET2_SET ;

  •     // For RED LED on BUNCH Rev-A
  •     pADI_GP1->GPCON |= GP1CON_CON2_GPIO;
  •     pADI_GP1->GPOEN |= GP1OEN_OEN2_OUT;
  •     pADI_GP1->GPCLR |= GP1CLR_CLR2_CLR;
  • }

  • unsigned char leds_arch_get(void)
  • {

  • return ((pADI_GP1->GPOUT & GP1OUT_OUT2) ? 0 : LEDS_RED)
  • | ((pADI_GP4->GPOUT & GP4OUT_OUT2) ? 0 : LEDS_GREEN)
  • | ((pADI_GP4->GPOUT &GP1OUT_OUT0) ? 0 : LEDS_BLUE);

  • }

  • void leds_arch_set(unsigned char leds)
  • {
  • if(leds & LEDS_RED)   { pADI_GP1->GPCLR |= GP1CLR_CLR2; } else { pADI_GP1->GPSET |= GP1SET_SET2_SET; }
  • if(leds & LEDS_GREEN) { pADI_GP4->GPCLR |= GP4CLR_CLR2; } else { pADI_GP4->GPSET |= GP4SET_SET2_SET; }
  • if(leds & LEDS_BLUE) { pADI_GP4->GPCLR |= GP4CLR_CLR0; } else { pADI_GP4->GPSET |= GP4SET_SET0_SET; }
  • }
复制代码

    2.3) leds应用函数



  • #include "contiki.h"
  • #include "dev/leds.h"
  • /*---------------------------------------------------------------------------*/
  • PROCESS(test_etimer_process, "Test ET");
  • AUTOSTART_PROCESSES(&test_etimer_process);
  • /*---------------------------------------------------------------------------*/
  • PROCESS_THREAD(test_etimer_process, ev, data)
  • {
  • static struct etimer et;
  • PROCESS_BEGIN();
  • while(1) {
  •     etimer_set(&et, CLOCK_SECOND);             // etimer溢出周期为1s
  •     PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
  •     leds_on(LEDS_GREEN);                      // 打开LEDS_GREEN
  •     etimer_set(&et, CLOCK_SECOND);
  •     PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
  •     leds_off(LEDS_GREEN);
  • }

  • PROCESS_END();
  • }
  • /*---------------------------------------------------------------------------*/
复制代码
2.4)最简单的main函数


  • int main(void)
  • {
  •     init_hw();/*硬件初始化 与 Contiki无关*/
  •     /*外设设备初始化*/
  •     leds_init();
  •     /* Clock */
  •     clock_init();
  •     /* Initialize process subsystem */
  •     process_init();
  •     /* etimers must be started before ctimer_init */
  •     process_start(&etimer_process, NULL);//设置etimer_process 进程
  •     ctimer_init();//设置ctimer_process 进程

  •     /* 默认程序 */
  •     autostart_start(autostart_processes);
  •     while(1) {
  •      process_run();
  •     }
  • }
复制代码
3、总结

这时看到闪灯的效果,有人做个闪灯有没有必要做得这么复杂,做闪灯并不是重要的目的,重要的目的是为也了解Contiki的运行机制,了解Contiki的外设的开发流程
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /2 下一条

手机版|小黑屋|与非网

GMT+8, 2024-4-27 03:08 , Processed in 0.115023 second(s), 18 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.