查看: 3145|回复: 1

[EVAL-WSN]操作系统篇——Contiki最简单的实例

[复制链接]
  • TA的每日心情
    奋斗
    2023-7-8 16:17
  • 签到天数: 971 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2016-1-10 21:26:57 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 dvd1478 于 2016-1-10 21:34 编辑

    1、前言
        Contiki是一款小型开源,易于移植的多任务操作系统,专门为无线传感网设计,适合内存受限制的网络系统。
        由于Contiki需要适应多种平台 ,所以一般的驱动分为抽像接口和具体实现两部分。

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

    [EVAL-WSN]操作系统篇——Contiki移植分析https://www.cirmall.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
    1. /**
    2. * \defgroup leds LEDs API
    3. *
    4. * The LEDs API defines a set of functions for accessing LEDs for
    5. * Contiki plaforms with LEDs.
    6. *
    7. * A platform with LED support must implement this API.
    8. * @{
    9. */

    10. #ifndef __LEDS_H__
    11. #define __LEDS_H__

    12. void leds_init(void);

    13. /**
    14. * Blink all LEDs.
    15. */
    16. void leds_blink(void);

    17. /*ledv 进行位设置  有且仅有以下四种可能
    18. 0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x80
    19. unsigned char leds_arch_get(void)
    20. 等等,定义了 unsigned char = 8bit
    21. 当修改即可以
    22. */
    23. #ifndef LEDS_GREEN
    24. #define LEDS_GREEN  1
    25. #endif /* LEDS_GREEN */
    26. #ifndef LEDS_YELLOW
    27. #define LEDS_YELLOW  2
    28. #endif /* LEDS_YELLOW */
    29. #ifndef LEDS_RED
    30. #define LEDS_RED  4
    31. #endif /* LEDS_RED */
    32. #ifndef LEDS_BLUE
    33. #define LEDS_BLUE  LEDS_YELLOW
    34. #endif /* LEDS_BLUE */

    35. #ifdef LEDS_CONF_ALL
    36. #define LEDS_ALL    LEDS_CONF_ALL
    37. #else /* LEDS_CONF_ALL */
    38. #define LEDS_ALL    7
    39. #endif /* LEDS_CONF_ALL */

    40. /**
    41. * Returns the current status of all leds (respects invert)
    42. */
    43. unsigned char leds_get(void);
    44. void leds_on(unsigned char leds);
    45. void leds_off(unsigned char leds);
    46. void leds_toggle(unsigned char leds);
    47. void leds_invert(unsigned char leds);

    48. /**
    49. * Leds implementation 具体实现
    50. */
    51. void leds_arch_init(void);
    52. unsigned char leds_arch_get(void);
    53. void leds_arch_set(unsigned char leds);

    54. #endif /* __LEDS_H__ */
    复制代码
    leds.c
    1. #include "dev/leds.h"
    2. #include "sys/clock.h"
    3. #include "sys/energest.h"

    4. static unsigned char leds, invert;
    5. /*---------------------------------------------------------------------------*/
    6. static void
    7. show_leds(unsigned char changed)
    8. {
    9.   if(changed & LEDS_GREEN) {
    10.     /* Green did change */
    11.     if((invert ^ leds) & LEDS_GREEN) {
    12.       ENERGEST_ON(ENERGEST_TYPE_LED_GREEN);//方便跟踪节能设计了energest模块
    13.     } else {
    14.       ENERGEST_OFF(ENERGEST_TYPE_LED_GREEN);
    15.     }
    16.   }
    17.   if(changed & LEDS_YELLOW) {
    18.     if((invert ^ leds) & LEDS_YELLOW) {
    19.       ENERGEST_ON(ENERGEST_TYPE_LED_YELLOW);
    20.     } else {
    21.       ENERGEST_OFF(ENERGEST_TYPE_LED_YELLOW);
    22.     }
    23.   }
    24.   if(changed & LEDS_RED) {
    25.     if((invert ^ leds) & LEDS_RED) {
    26.       ENERGEST_ON(ENERGEST_TYPE_LED_RED);
    27.     } else {
    28.       ENERGEST_OFF(ENERGEST_TYPE_LED_RED);
    29.     }
    30.   }
    31.   leds_arch_set(leds ^ invert);
    32. }
    33. /*---------------------------------------------------------------------------*/
    34. void
    35. leds_init(void)
    36. {
    37.   leds_arch_init();
    38.   leds = invert = 0;
    39. }
    40. /*---------------------------------------------------------------------------*/
    41. void
    42. leds_blink(void)
    43. {
    44.   /* Blink all leds. */
    45.   unsigned char inv;
    46.   inv = ~(leds ^ invert);
    47.   leds_invert(inv);

    48.   clock_delay(400);

    49.   leds_invert(inv);
    50. }
    51. /*---------------------------------------------------------------------------*/
    52. unsigned char
    53. leds_get(void) {
    54.   return leds_arch_get();
    55. }
    56. /*---------------------------------------------------------------------------*/
    57. void
    58. leds_on(unsigned char ledv)
    59. {
    60.   unsigned char changed;
    61.   changed = (~leds) & ledv;
    62.   leds |= ledv;
    63.   show_leds(changed);
    64. }
    65. /*---------------------------------------------------------------------------*/
    66. void
    67. leds_off(unsigned char ledv)
    68. {
    69.   unsigned char changed;
    70.   changed = leds & ledv;
    71.   leds &= ~ledv;
    72.   show_leds(changed);
    73. }
    74. /*---------------------------------------------------------------------------*/
    75. void
    76. leds_toggle(unsigned char ledv)
    77. {
    78.   leds_invert(ledv);
    79. }
    80. /*---------------------------------------------------------------------------*/
    81. /*   invert the invert register using the leds parameter */
    82. void
    83. leds_invert(unsigned char ledv) {
    84.   invert = invert ^ ledv;
    85.   show_leds(ledv);
    86. }
    87. /*---------------------------------------------------------------------------*/
    复制代码
    在面对用户层时只调用
    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熄灭。以此类推。
    1. #include "contiki-conf.h"
    2. #include "dev/leds.h"
    3. #include "device.h"
    4. #include "gpio.h"


    5. #define LED_ARCH_RED   GPIO_LED_RED  //P1.2
    6. #define LED_ARCH_GREEN GPIO_LED_GREEN //P4.2
    7. #define LED_ARCH_BLUE  GPIO_LED_BLUE  //P4.0

    8. void leds_arch_init(void)
    9. {
    10.     //pADI_GP4->GPCON |= GP4CON_CON0_GPIO | GP4CON_CON1_GPIO | GP4CON_CON2_GPIO | GP4CON_CON3_GPIO;
    11.     //pADI_GP4->GPOEN |= GP4OEN_OEN0_OUT | GP4OEN_OEN1_OUT | GP4OEN_OEN2_OUT | GP4OEN_OEN3_OUT;
    12.     //pADI_GP4->GPSET |= GP4SET_SET0_SET | GP4SET_SET1_SET | GP4SET_SET2_SET | GP4SET_SET3_SET;
    13.     pADI_GP4->GPCON |= GP4CON_CON0_GPIO | GP4CON_CON2_GPIO ;
    14.     pADI_GP4->GPOEN |= GP4OEN_OEN0_OUT | GP4OEN_OEN2_OUT ;
    15.     pADI_GP4->GPSET |= GP4SET_SET0_SET | GP4SET_SET2_SET ;
    16.    
    17.     // For RED LED on BUNCH Rev-A
    18.     pADI_GP1->GPCON |= GP1CON_CON2_GPIO;
    19.     pADI_GP1->GPOEN |= GP1OEN_OEN2_OUT;
    20.     pADI_GP1->GPCLR |= GP1CLR_CLR2_CLR;
    21. }

    22. unsigned char leds_arch_get(void)
    23. {

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

    27. }

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


    37. #define LED_ARCH_RED   GPIO_LED_RED  //P1.2
    38. #define LED_ARCH_GREEN GPIO_LED_GREEN //P4.2
    39. #define LED_ARCH_BLUE  GPIO_LED_BLUE  //P4.0

    40. void leds_arch_init(void)
    41. {
    42.     //pADI_GP4->GPCON |= GP4CON_CON0_GPIO | GP4CON_CON1_GPIO | GP4CON_CON2_GPIO | GP4CON_CON3_GPIO;
    43.     //pADI_GP4->GPOEN |= GP4OEN_OEN0_OUT | GP4OEN_OEN1_OUT | GP4OEN_OEN2_OUT | GP4OEN_OEN3_OUT;
    44.     //pADI_GP4->GPSET |= GP4SET_SET0_SET | GP4SET_SET1_SET | GP4SET_SET2_SET | GP4SET_SET3_SET;
    45.     pADI_GP4->GPCON |= GP4CON_CON0_GPIO | GP4CON_CON2_GPIO ;
    46.     pADI_GP4->GPOEN |= GP4OEN_OEN0_OUT | GP4OEN_OEN2_OUT ;
    47.     pADI_GP4->GPSET |= GP4SET_SET0_SET | GP4SET_SET2_SET ;
    48.    
    49.     // For RED LED on BUNCH Rev-A
    50.     pADI_GP1->GPCON |= GP1CON_CON2_GPIO;
    51.     pADI_GP1->GPOEN |= GP1OEN_OEN2_OUT;
    52.     pADI_GP1->GPCLR |= GP1CLR_CLR2_CLR;
    53. }

    54. unsigned char leds_arch_get(void)
    55. {

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

    59. }

    60. void leds_arch_set(unsigned char leds)
    61. {
    62. if(leds & LEDS_RED)   { pADI_GP1->GPCLR |= GP1CLR_CLR2; } else { pADI_GP1->GPSET |= GP1SET_SET2_SET; }
    63. if(leds & LEDS_GREEN) { pADI_GP4->GPCLR |= GP4CLR_CLR2; } else { pADI_GP4->GPSET |= GP4SET_SET2_SET; }
    64. if(leds & LEDS_BLUE)  { pADI_GP4->GPCLR |= GP4CLR_CLR0; } else { pADI_GP4->GPSET |= GP4SET_SET0_SET; }  
    65. }
    复制代码
       
       2.3) leds应用函数
    1. #include "contiki.h"
    2. #include "dev/leds.h"
    3. /*---------------------------------------------------------------------------*/
    4. PROCESS(test_etimer_process, "Test ET");
    5. AUTOSTART_PROCESSES(&test_etimer_process);
    6. /*---------------------------------------------------------------------------*/
    7. PROCESS_THREAD(test_etimer_process, ev, data)
    8. {
    9.   static struct etimer et;  
    10.   PROCESS_BEGIN();  
    11.   while(1) {  
    12.     etimer_set(&et, CLOCK_SECOND);                    // etimer溢出周期为1s  
    13.     PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));  
    14.     leds_on(LEDS_GREEN);                               // 打开LEDS_GREEN
    15.     etimer_set(&et, CLOCK_SECOND);  
    16.     PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));  
    17.     leds_off(LEDS_GREEN);  
    18.   }  
    19.   
    20.   PROCESS_END();
    21. }
    22. /*---------------------------------------------------------------------------*/
    复制代码
    2.4)最简单的main函数
    1. int main(void)
    2. {
    3.     init_hw();/*硬件初始化 与 Contiki无关*/
    4.     /*外设设备初始化*/
    5.     leds_init();
    6.     /* Clock */
    7.     clock_init();
    8.     /* Initialize process subsystem */
    9.     process_init();
    10.     /* etimers must be started before ctimer_init */
    11.     process_start(&etimer_process, NULL);//设置etimer_process 进程
    12.     ctimer_init();//设置ctimer_process 进程
    13.    
    14.     /* 默认程序 */
    15.     autostart_start(autostart_processes);
    16.     while(1) {
    17.         process_run();
    18.     }
    19. }
    复制代码
    3、总结


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


    回复

    使用道具 举报

  • TA的每日心情
    开心
    2014-5-20 10:01
  • 签到天数: 41 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2016-1-11 09:14:25 | 显示全部楼层
    不错的分享,顶!
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

    手机版|小黑屋|与非网

    GMT+8, 2024-4-18 08:21 , Processed in 0.123714 second(s), 17 queries , MemCache On.

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

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.