Zephyr程序初探(5):thread程序

這次的程序使用了中斷、thread、semaphore,按鍵被按下後GPIO的中斷callback被執行,發送semaphore使檢測按鍵的thread得以執行,然後判斷長按或者短按發送相應semaphore讓相應的thread執行,除輸出信息外LED會根據短按或者長按來閃爍1或者2次。

#include <zephyr.h>
#include <board.h>
#include <device.h>
#include <gpio.h>
#include <misc/util.h>
#include <misc/printk.h>

/* define LED and Button pin */
#define LED_PORT    LED0_GPIO_PORT
#define LED_PIN     LED0_GPIO_PIN
#define LED_FLASH_TIME  100//ms

#define BTN_PORT    SW0_GPIO_NAME
#define BTN_PIN     SW0_GPIO_PIN

/* define semaphore */
K_SEM_DEFINE(semPress, 0, 1);
K_SEM_DEFINE(semHold, 0, 1);
K_SEM_DEFINE(semBtnIntr, 0, 1);

/* define global device */
struct device *gDevLed;
struct device *gDevBtn;

static struct gpio_callback gpio_cb;

/* define thread parameter */
#define STACKSIZE   1024
#define PRIORITY_EVENT  7
#define PRIORITY_INTR   6

void ledOnOff(uint32_t on)
{
    gpio_pin_write(gDevLed, LED_PIN, !on);
}
void ledFlash(uint32_t times)
{
    while(times) {
        ledOnOff(1);
        k_sleep(LED_FLASH_TIME);
        ledOnOff(0);

        if(--times)
            k_sleep(LED_FLASH_TIME);
    }
}
uint32_t isKeyDown(void)
{
    uint32_t val;
    gpio_pin_read(gDevBtn, BTN_PIN, &val);
    return !val;
}

void threadPress(void *dummy1, void *dummy2, void *dummy3)
{
    ARG_UNUSED(dummy1);
    ARG_UNUSED(dummy2);
    ARG_UNUSED(dummy3);
    while(1) {
        k_sem_take(&semPress, K_FOREVER);
        printk("btn pressed\n");
        ledFlash(1);
    }
}
void threadHold(void *dummy1, void *dummy2, void *dummy3)
{
    ARG_UNUSED(dummy1);
    ARG_UNUSED(dummy2);
    ARG_UNUSED(dummy3);
    while(1) {
        k_sem_take(&semHold, K_FOREVER);
        printk("btn hold\n");
        ledFlash(2);
    }
}
void threadBtnIntr(void *dummy1, void *dummy2, void *dummy3)
{
    ARG_UNUSED(dummy1);
    ARG_UNUSED(dummy2);
    ARG_UNUSED(dummy3);
    uint32_t count;
    bool bHold;
    while(1) {
        k_sem_take(&semBtnIntr, K_FOREVER);
        count = 0;
        bHold = false;
        do {
            k_sleep(50);
            count++;
            if(count > 6) {
                bHold = true;
                break;
            }
        }while(isKeyDown());

        if(bHold)
            k_sem_give(&semHold);
        else
            k_sem_give(&semPress);
    }
}


K_THREAD_DEFINE(threadPress_id, STACKSIZE, threadPress, NULL, NULL, NULL, 
        PRIORITY_EVENT, 0, K_NO_WAIT);
K_THREAD_DEFINE(threadHold_id, STACKSIZE, threadHold, NULL, NULL, NULL, 
        PRIORITY_EVENT, 0, K_NO_WAIT);
K_THREAD_DEFINE(threadBtnIntr_id, STACKSIZE, threadBtnIntr, NULL, NULL, NULL, 
        PRIORITY_INTR, 0, K_NO_WAIT);

void btnIntrCb(struct device *gpio, struct gpio_callback *cb, uint32_t pin)
{
    k_sem_give(&semBtnIntr);
}

void helloMsg(void)
{
    printk("\n************************************************\n");
    printk("**\n");
    printk("** Welcome to visit http://blog.csdn.net/veabol\n");
    printk("** Thread program start!\n");
    printk("**\n");
    printk("************************************************\n");
}

void main (void)
{

    helloMsg();

    printk("configure led\n");
    gDevLed = device_get_binding(LED_PORT);
    if (!gDevLed) {
        printk("error\n");
        return;
    }
    gpio_pin_configure(gDevLed, LED_PIN, GPIO_DIR_OUT);
    ledOnOff(0);

    printk("configure button\n");
    gDevBtn = device_get_binding(BTN_PORT);
    if (!gDevBtn) {
        printk("error\n");
        return;
    }
    gpio_pin_configure(gDevBtn, BTN_PIN, 
        GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW | GPIO_PUD_PULL_UP);
    gpio_init_callback(&gpio_cb, btnIntrCb, BIT(BTN_PIN));
    gpio_add_callback(gDevBtn, &gpio_cb);
    gpio_pin_enable_callback(gDevBtn, BTN_PIN);
}

通過系統函數K_SEM_DEFINE定義三個信號量semPress,semHold,semBtnIntrK_THREAD_DEFINE初始化三個thread,分別用於等待按鍵中斷和短按和長按的事件,threadBtnIntr()等待semBtnIntr即按鍵中斷的發生,threadPress()是短按的線程等待semPress被髮送,threadHold()是長按的線程等待semHold被髮送。
main()函數初始化LED和按鍵,註冊並使能按鍵的callback函數btnIntrCb(),當中斷髮生時btnIntrCb()被調用,並且發送信號使threadBtnIntr()得以繼續執行,根據按鍵持續的時間長短分別發送短按和長按的信號 ,相應的線程也得以執行,測試時對按鍵進行短按和長按能夠看到LED閃爍1次或者2次,通過串口能夠看到如何信息:

************************************************
**
** Welcome to visit http://blog.csdn.net/veabol
** Thread program start!
**
************************************************
configure led
configure button
btn pressed
btn pressed
btn hold
btn hold
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章