关于CONTIKI NG的LEDS,我们首先把它的概念、目的搞清楚。LEDS是\os\dev标准驱动库,主要是用于管理所有LED灯的,有三大文件
\os\dev内核的:leds.h、leds.c
\user\src用户实现的: leds-arch.c
leds.h都是一些功能函数的申请明,而leds.c则实现它功能,发现leds.c里面是在使用\user\cc2538-dev的gpio-hal-arch.h操作,
这个\user\cc2538-dev的gpio-hal-arch.h此前已经研究过了,可回顾篇 https://www.cnblogs.com/lijianGX/p/13681844.html 。
leds-arch.c是实现了一个结构体类型的数组,因为它在leds.c被使用到,即然内核都使用到了,它可能是标准的方法了
我们把这它们都放在一起,看看它们的模样:
1 /************* \os\dev内核的:leds.h,部份代码*******/ 2 /*---------------------------------------------------------------------------*/ 3 /** 4 * \brief 不存在的LED的默认LED颜色 5 */ 6 #define LEDS_COLOUR_NONE 0x00 7 8 9 /*----------------------红+绿+蓝+黄+橙---------------------------------------*/ 10 /* LED 颜色到数字映射。适用于两个 API */ 11 #ifdef LEDS_CONF_RED 12 #define LEDS_RED LEDS_CONF_RED 13 #else 14 #define LEDS_RED LEDS_COLOUR_NONE 15 #endif 16 17 #ifdef LEDS_CONF_GREEN //如果有配置绿色LED 18 #define LEDS_GREEN LEDS_CONF_GREEN //有,定义绿色 19 #else 20 #define LEDS_GREEN LEDS_COLOUR_NONE //无,不存在绿色 21 #endif 22 23 #ifdef LEDS_CONF_BLUE 24 #define LEDS_BLUE LEDS_CONF_BLUE 25 #else 26 #define LEDS_BLUE LEDS_COLOUR_NONE 27 #endif 28 29 #ifdef LEDS_CONF_YELLOW 30 #define LEDS_YELLOW LEDS_CONF_YELLOW 31 #else 32 #define LEDS_YELLOW LEDS_COLOUR_NONE 33 #endif 34 35 #ifdef LEDS_CONF_ORANGE 36 #define LEDS_ORANGE LEDS_CONF_ORANGE 37 #else 38 #define LEDS_ORANGE LEDS_COLOUR_NONE 39 #endif 40 41 42 typedef uint8_t leds_num_t; 43 typedef uint8_t leds_mask_t; 44 45 /*---------------------------------------------------------------------------*/ 46 #ifdef LEDS_CONF_COUNT 47 #define LEDS_COUNT LEDS_CONF_COUNT 48 #else 49 /** 50 * \brief 设备上存在的 LED 数量 51 */ 52 #define LEDS_COUNT 0 53 #endif 54 55 /*---------------------------------------------------------------------------*/ 56 /** 57 * \brief 所有设备 LED 的 OR 掩码表示 58 */ 59 #define LEDS_ALL ((1 << LEDS_COUNT) - 1) 60 61 62 /*----------------------------就是LINE:xx的5个灯-----------------------------*/ 63 #define LEDS_LED1 0x00 /**< Convenience macro to refer 到第一个LED(LED 1)*/ 64 #define LEDS_LED2 0x01 /**< Convenience macro to refer to the 2nd LED (LED 2) */ 65 #define LEDS_LED3 0x02 /**< Convenience macro to refer to the 3rd LED (LED 3) */ 66 #define LEDS_LED4 0x03 /**< Convenience macro to refer to the 4th LED (LED 4) */ 67 #define LEDS_LED5 0x04 /**< Convenience macro to refer to the 5th LED (LED 5) */ 68 69 70 // leds-arch.c有用到这个leds_t 71 typedef struct leds_s { 72 gpio_hal_pin_t pin; 73 #if GPIO_HAL_PORT_PIN_NUMBERING 74 gpio_hal_port_t port; 75 #endif 76 bool negative_logic; 77 } leds_t; 78 79 80 /*---------------------------------------------------------------------------*/ 81 /** 82 * [简要 将 LED 编号转换为掩码表示形式 83 * =param l 引脚编号(通常是类型leds_num_t) 84 * = 返回类型为 leds_mask_t 85 */ 86 #define LEDS_NUM_TO_MASK(l) (1 << (l)) 87 88 89 /*---------------------------------------------------------------------------*/ 90 /** 91 * [ 简要初始化 LED 92 * 93 * 此功能将设置相应的 LED GPIO 引脚输出,也将 94 * 将所有 LED 的初始状态设置为关闭。 95 */ 96 void leds_init(void); 97 98 99 100 101 /************* \os\dev内核的:leds.c,部份代码 */ 102 /*------------------------------全是新版的LEDS-------------------------------*/ 103 #if LEDS_COUNT // leds的总数量 104 extern const leds_t leds_arch_leds[]; 105 #else 106 static const leds_t *leds_arch_leds = NULL; // static const去修饰指针,能变动吗? 107 #endif 108 109 110 /*---------------------------------------------------------------------------*/ 111 #if GPIO_HAL_PORT_PIN_NUMBERING // 为0的 112 #define LED_PORT(led) (led).port 113 #else 114 #define LED_PORT(led) GPIO_HAL_NULL_PORT // 就CC2538来看,是选定这一项,不用PORT 115 #endif 116 117 118 /*---------------------------------------------------------------------------*/ 119 void 120 leds_init() 121 { 122 leds_num_t led; 123 124 for(led = 0; led < LEDS_COUNT; led++) { //执行完这个功能后,LED才会有作用!! 125 gpio_hal_arch_pin_set_output(LED_PORT(leds_arch_leds[led]), 126 leds_arch_leds[led].pin); 127 } 128 //leds_off(LEDS_ALL); 硬件反的 129 leds_on(LEDS_ALL); //硬件反的,ON才是OFF 130 } 131 132 133 134 /******** \user\src用户实现的: leds-arch.c */ 135 /*---------------------------------------------------------------------------*/ 136 const leds_t leds_arch_leds[] = { 137 { 138 .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L1_PORT, LEDS_ARCH_L1_PIN), 139 .negative_logic = false // 所谓的负逻辑就是,当低电平时,LED才亮起来 140 }, 141 { 142 .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L2_PORT, LEDS_ARCH_L2_PIN), 143 .negative_logic = false // 当为true时,为正逻辑,高电平时灯亮起 144 }, 145 { 146 .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L3_PORT, LEDS_ARCH_L3_PIN), 147 .negative_logic = false 148 }, 149 #if !USB_SERIAL_CONF_ENABLE 150 { 151 .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L4_PORT, LEDS_ARCH_L4_PIN), 152 .negative_logic = false 153 }, 154 #endif 155 };
可以看到,要用户实现内容比较少了,leds-arch.c值得好好分析一下,leds.h、leds.c属OS的内核部份,为了通用性我们不要去更改它。最近在搬家,晚些日子再深入研究。。。
日期2020-10-26
要重新研究一下,有几个特别的宏定义,很重要:
1 /***************************************************************************** 2 Function : C03测试 3 Description : 用CONTIKI的ubuntu进行测试,GCC用makefile方式的, 4 在这里写好代码后gcc 03.c&&./a.out看执行效果 5 Input : None 6 Output : None 7 Return : None 8 *****************************************************************************/ 9 10 // ALL Includes 11 #include "stdio.h" 12 #include "stdlib.h" 13 #include "string.h" 14 #include <stdint.h> 15 #include <stdbool.h> 16 #include <stddef.h> 17 18 //reg.h 19 #define REG(x) (*((volatile unsigned long *)(x))) 20 #define REG_H(x) (*((volatile unsigned short *)(x))) 21 #define REG_B(x) (*((volatile unsigned char *)(x))) 22 #define REG_BIT_W(x, b) \ 23 REG(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \ 24 (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2)) 25 #define REG_BIT_H(x, b) \ 26 REG_H(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \ 27 (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2)) 28 #define REG_BIT_B(x, b) \ 29 REG_B(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \ 30 (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2)) 31 32 33 //gpio.h 34 #define GPIO_A_NUM 0 /**< GPIO_A: 0 */ 35 #define GPIO_B_NUM 1 /**< GPIO_B: 1 */ 36 #define GPIO_C_NUM 2 /**< GPIO_C: 2 */ 37 #define GPIO_D_NUM 3 /**< GPIO_D: 3 */ 38 39 #define GPIO_DATA 0x00000000 /**< 数据寄存器 */ 40 #define GPIO_DIR 0x00000400 /**< 数据方向寄存器 */ 41 #define GPIO_IS 0x00000404 /**< 中断感*/ 42 #define GPIO_IBE 0x00000408 /**< 中断两个边缘 */ 43 #define GPIO_IEV 0x0000040C /**< 中断事件 */ 44 #define GPIO_IE 0x00000410 /**< 中断屏蔽 */ 45 #define GPIO_RIS 0x00000414 /**< 中断状态 - 原始 */ 46 #define GPIO_MIS 0x00000418 /**< 中断状态-已屏蔽*/ 47 #define GPIO_IC 0x0000041C /**< 中断清除 */ 48 #define GPIO_AFSEL 0x00000420 /**< 模式控制选择 */ 49 #define GPIO_GPIOLOCK 0x00000520 /**< GPIO 提交解锁 */ 50 #define GPIO_GPIOCR 0x00000524 /**< GPIO提交 */ 51 #define GPIO_PMUX 0x00000700 /**< PMUX寄存器 */ 52 #define GPIO_P_EDGE_CTRL 0x00000704 /**< 端口边缘控制 */ 53 #define GPIO_USB_CTRL 0x00000708 /**< USB输入上电边缘ctrl */ 54 #define GPIO_PI_IEN 0x00000710 /**< 上电中断使能 */ 55 #define GPIO_IRQ_DETECT_ACK 0x00000718 /**< IRQ detect ACK - I/O ports */ 56 #define GPIO_USB_IRQ_ACK 0x0000071C /**< IRQ detect ACK - USB */ 57 #define GPIO_IRQ_DETECT_UNMASK 0x00000720 /**< IRQ detect ACK - masked */ 58 59 #define GPIO_A_BASE 0x400D9000 /**< GPIO_A 与数据手册上一致的 */ 60 #define GPIO_B_BASE 0x400DA000 /**< GPIO_B */ 61 #define GPIO_C_BASE 0x400DB000 /**< GPIO_C */ 62 #define GPIO_D_BASE 0x400DC000 /**< GPIO_D */ 63 64 #define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK) \ 65 do { REG((PORT_BASE) + GPIO_AFSEL) &= ~(PIN_MASK); } while(0) 66 67 68 #define GPIO_PIN_MASK(PIN) (1 << (PIN)) 69 70 71 #define GPIO_PORT_TO_BASE(PORT) (GPIO_A_BASE + ((PORT) << 12)) 72 73 74 #define GPIO_PORT_PIN_TO_GPIO_HAL_PIN(PORT, PIN) (((PORT) << 3) + (PIN)) 75 76 77 #define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK) \ 78 do { REG((PORT_BASE) + GPIO_DIR) |= (PIN_MASK); } while(0) 79 80 81 //gpio-hal-arch.h 82 #define gpio_hal_arch_pin_set_output(port, p) do { \ 83 GPIO_SOFTWARE_CONTROL(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ 84 GPIO_SET_OUTPUT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ 85 } while(0); 86 87 88 //gpio-hal.h 89 #define GPIO_HAL_NULL_PORT 0 //暂时理解为,不使用PORT端口参数 90 91 92 //board.h 93 #define LEDS_CONF_YELLOW 1 //黄灯 94 #define LEDS_CONF_GREEN 2 //绿灯 95 #define LEDS_CONF_ORANGE 4 //橘黄色,在开发板上是蓝色灯 96 97 #define LEDS_ARCH_L1_PORT GPIO_C_NUM //C端口的第1 PIN 98 #define LEDS_ARCH_L1_PIN 1 99 #define LEDS_ARCH_L2_PORT GPIO_C_NUM 100 #define LEDS_ARCH_L2_PIN 2 101 #define LEDS_ARCH_L3_PORT GPIO_C_NUM 102 #define LEDS_ARCH_L3_PIN 3 103 104 105 //gpio-hal-arch.h 106 #define PIN_TO_PORT(pin) (pin >> 3) 107 #define PIN_TO_NUM(pin) (pin % 8) 108 #define PIN_TO_PORT_BASE(pin) GPIO_PORT_TO_BASE(PIN_TO_PORT(pin)) 109 #define GPIO_PORT_TO_BASE(PORT) (GPIO_A_BASE + ((PORT) << 12)) 110 111 //主main 112 int main(void) { 113 114 115 gpio_hal_arch_pin_set_output(GPIO_HAL_NULL_PORT,GPIO_PORT_PIN_TO_GPIO_HAL_PIN(GPIO_C_NUM, LEDS_ARCH_L3_PIN)); //OK 0, 2, 3 116 // gpio_hal_arch_pin_set_output(0,13); //OK 0, 2, 3 117 printf("This is C dbg 43 PASS!\r\n\r\n\r\n");//执行到这一步,说明测试正常退出! 118 return 0; 119 }
以上就是LEDS的所有内容了,但是在单独执行时,会报错!这个太难了。。这个是高级错误。我只是想单独仿真一下看看,竟然报这个core dumped错误!!!

日期2020-11-2
我们用GPIO.H操作时,如之前的所示
GPIO_SET_OUTPUT(GPIO_C_BASE, GPIO_PIN_MASK(3));//操作PORTC-PIN3为输出
当我们用操作系统LEDS时,在gpio-hal-arch.h就成这样了
GPIO_SET_OUTPUT(PIN_TO_PORT_BASE(GPIO_PORT_PIN_TO_GPIO_HAL_PIN(GPIO_C_NUM, LEDS_ARCH_L3_PIN)),\ GPIO_PIN_MASK((GPIO_PORT_PIN_TO_GPIO_HAL_PIN(GPIO_C_NUM, LEDS_ARCH_L3_PIN)) % 8));
为什么要把简单的事情搞复杂,有点无耐了。GPIO_SET_OUTPUT(x,x)可以很简单,也可以很复杂!系统源码多处提示不建议直接寄存PORT,哈哈!!
回顾一下知识点,在gpio-hal-arch.h中
1 /* 端口引脚配置成输出 */ 2 #define gpio_hal_arch_pin_set_output(port, p) do { \ 3 GPIO_SOFTWARE_CONTROL(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ 4 GPIO_SET_OUTPUT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ 5 } while(0);
GPIO_SOFTWARE_CONTROL这是模式选择,是软件直接操作GPIO?还是接入外设,如IIC ADC等?默认是软件操作的,所以我们不用去管它。
日期2020-11-3
虽然我们还是比较喜欢直接操作寄存,说白这是裸机编程留下的习惯;但是我们在学NG操作系统,必须学习系统的方法,再难也要慢慢磨下去!!
我手上的CONTIKI NG版本,实现了4个LEDS
* - LED1 (Red) -> PC0 * - LED2 (Yellow) -> PC1 * - LED3 (Green) -> PC2 * - LED4 (Orange) -> PC3
现在要自己实现BLUE蓝灯,说实话!随便用哪个GPIO都行,我就用随意一下,就PORTD口的PIN4脚吧。
你会发现非常的简单,在board.h编写:
/*---------------------------------------------------------------------------*/ /** \name SmartRF LED configuration * * LEDs on the SmartRF06 (EB and BB) are connected as follows: * - LED1 (Red) -> PC0 * - LED2 (Yellow) -> PC1 * - LED3 (Green) -> PC2 * - LED4 (Orange) -> PC3 * - LED5 (BLUE) -> PD4 // 2020-11-2增加 * LED1 shares the same pin with the USB pullup * @{ */ /*---------------------------------------------------------------------------*/ #define LEDS_CONF_YELLOW 1 //黄灯 #define LEDS_CONF_GREEN 2 //绿灯 #define LEDS_CONF_ORANGE 4 //橘黄色,在开发板上是蓝色灯 #define LEDS_CONF_BLUE 5 //蓝灯 2020-11-2增加 #define LEDS_ARCH_L1_PORT GPIO_C_NUM //C端口的第1 PIN #define LEDS_ARCH_L1_PIN 1 #define LEDS_ARCH_L2_PORT GPIO_C_NUM #define LEDS_ARCH_L2_PIN 2 #define LEDS_ARCH_L3_PORT GPIO_C_NUM #define LEDS_ARCH_L3_PIN 3 #define LEDS_ARCH_L5_PORT GPIO_D_NUM // 2020-11-2增加 #define LEDS_ARCH_L5_PIN 4 #if USB_SERIAL_CONF_ENABLE #define LEDS_CONF_COUNT 3 #else #define LEDS_ARCH_L4_PORT GPIO_C_NUM #define LEDS_ARCH_L4_PIN 0 #define LEDS_CONF_RED 8 //红灯 #define LEDS_CONF_COUNT 5 //原来是4,2020-11-2增加改成5 #endif
上面有“2020-11-2增加”就是新加的,灯的总数量5个(0-4);
接着在leds-arch.c编写:
const leds_t leds_arch_leds[] = { { .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L1_PORT, LEDS_ARCH_L1_PIN), .negative_logic = false // 所谓的负逻辑就是,当低电平时,LED才亮起来 }, { .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L2_PORT, LEDS_ARCH_L2_PIN), .negative_logic = false // 当为true时,为正逻辑,高电平时灯亮起 }, { .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L3_PORT, LEDS_ARCH_L3_PIN), .negative_logic = false }, #if !USB_SERIAL_CONF_ENABLE { .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L4_PORT, LEDS_ARCH_L4_PIN), .negative_logic = false }, #endif { .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L5_PORT, LEDS_ARCH_L5_PIN), .negative_logic = false //2020-11-02增加 }, };
同样道理,上面有“2020-11-2增加”就是新加的,为什么要写这个,因为系统在初次化LEDS时,会使用的。
给出contiki-main.c关键源码部分,只是测试,没跑系统的。
gpio_hal_arch_pin_set_output(GPIO_HAL_NULL_PORT,GPIO_PORT_PIN_TO_GPIO_HAL_PIN(GPIO_D_NUM, LEDS_ARCH_L5_PIN)); GPIO_WRITE_PIN(GPIO_D_BASE, GPIO_PIN_MASK(4), ~GPIO_READ_PIN(GPIO_D_BASE, GPIO_PIN_MASK(4))); GPIO_WRITE_PIN(GPIO_D_BASE, GPIO_PIN_MASK(4), ~GPIO_READ_PIN(GPIO_D_BASE, GPIO_PIN_MASK(4))); GPIO_WRITE_PIN(GPIO_D_BASE, GPIO_PIN_MASK(4), ~GPIO_READ_PIN(GPIO_D_BASE, GPIO_PIN_MASK(4))); GPIO_WRITE_PIN(GPIO_D_BASE, GPIO_PIN_MASK(4), ~GPIO_READ_PIN(GPIO_D_BASE, GPIO_PIN_MASK(4))); UARTprintf("HAL NO:0x%x\r\n",GPIO_PORT_PIN_TO_GPIO_HAL_PIN(GPIO_D_NUM, LEDS_ARCH_L5_PIN)); //换为GPIO HAL引脚号:0x13,这个3就是引脚号3 while(1);//测试LEDS的
在IAR单步仿真时,示波器测到的波形

PORTD口的PIN4脚已经实现了,这里LEDS的学习到此结束!
深入研究,NG系统级的LEDS只开放了5个LEDS,我们要开放10个也可以的,去leds.h内核文件里改一下就行了。
一般5个确实也够用了。还想玩LEDS的话,就移植到STM32上面去吧,算了,我么有太多时间,继续研究NG系统的其他功能要紧。
浙公网安备 33010602011771号