用龙芯1c库在RT-Thread下实现外部中断(GPIO中断、按键中断)

简介

先来说下,这里为什么既涉及龙芯1c库,又涉及RT-Thread。中断相关函数是RT-Thread已经封装好的,比如设置中断处理函数,中断使能;但GPIO相关的函数却是使用龙芯1c库中的,比如GPIO初始化,将GPIO设为输入模式,设置GPIO中断类型(下降沿中断)等。

龙芯1c库和RT-Thread分别是什么

龙芯1c库的git是  http://git.oschina.net/caogos/OpenLoongsonLib1c
RT-Thread的git是  https://github.com/RT-Thread/rt-thread
龙芯1c库是为龙芯1c单片机封装的常用外设接口集合,类似于STM32库。不仅可以用于裸机编程,还可以和实时系统(比如RT-Thread等)配合使用。这里就是将龙芯1c库和RT-Thread配合使用,其中龙芯1c库中GPIO相关接口已经移植到RT-Thread,并且合并到RT-Thread官方源码中。

测试用的硬件

实物图

用龙芯1c库在RT-Thread下实现外部中断(GPIO中断、按键中断)_第1张图片

这里选择三个按键中的S3,所在GPIO为GPIO85/I2C_SDA0,led选择靠近RJ45的D2,所在GPIO为GPIO32,这个led在智龙的首发版、V2.0和V2.1中都有。

原理图

按键原理图

用龙芯1c库在RT-Thread下实现外部中断(GPIO中断、按键中断)_第2张图片

Led原理图

用龙芯1c库在RT-Thread下实现外部中断(GPIO中断、按键中断)_第3张图片

测试用的软件

重难点

RT-Thread中首先需要新建一个线程,然后再该线程中初始化led,初始化按键并注册中断。
首先调用rt_thread_init(&thread_test,   
                            "thread_test",  
                            thread_test_entry,  
                            RT_NULL,  
                            &thread_test_stack[0],  
                            sizeof(thread_test_stack),  
                            THREAD_TEST_PRIORITY,  
                            THREAD_TEST_TIMESLICE);  
新建一个线程thread_test;然后再线程中对按键和led初始化等。
龙芯1c库中有封装好的led接口led_init()led_init(led_gpio); led_off(led_gpio);和led_on(led_gpio);
按键的初始化只需要将对应的GPIO设置为输入的普通GPIO就行,调用函数gpio_init(key_gpio, gpio_mode_input);
然后调用gpio_set_irq_type(key_gpio, IRQ_TYPE_EDGE_FALLING);设置中断的类型;
再后就是调用rt_hw_interrupt_install(key_irq, ls1c_test_key_irqhandler, RT_NULL, "KeyS3")注册中断处理函数;
最后调用rt_hw_interrupt_umask(key_irq);使能中断。
一旦发生中断,则置标志为1,代码如下

void ls1c_test_key_irqhandler(int irq, void *param)
{
    key_irq_flag = 1;
}

在线程中不断查询这个标志,一旦标志被置1,则延时10ms消抖后,闪一下led,并在串口输出提示。源码如下

  
// 测试用的线程的入口  
void thread_test_entry(void *parameter)  
{
    unsigned int key_gpio = 85;     // GPIO85/I2C_SDA0
    int key_irq = LS1C_GPIO_TO_IRQ(key_gpio);

    // 初始化按键中断
    gpio_init(key_gpio, gpio_mode_input);
    gpio_set_irq_type(key_gpio, IRQ_TYPE_LEVEL_LOW);
    rt_hw_interrupt_install(key_irq, ls1c_test_key_irqhandler, RT_NULL, "KeyS3");
    rt_hw_interrupt_umask(key_irq);
    
    while (1)  
    {  
        if (1 == key_irq_flag)
        {
            // 延迟10ms,消抖
            rt_thread_delay(RT_TICK_PER_SECOND/100);
            key_irq_flag = 0;
            rt_thread_delay(1);
            rt_kprintf("[%s] Key press\n", __FUNCTION__);
        }
        rt_thread_delay(RT_TICK_PER_SECOND);  
    }  
}  
仅保留了按键中断相关代码,led的代码从中删掉了。

如果想换其他按键测试,直接修改变量key_gpio就行。

使用宏LS1C_GPIO_TO_IRQ(key_gpio),将GPIO编号转换为中断号。

完整的源码清单

测试的所有源码都在文件bsp\ls1cdev\applications\application.c中,源码如下

/*
 * File      : application.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006-2012, RT-Thread Develop Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date                Author         Notes
 * 2010-06-25          Bernard        first version
 * 2011-08-08          lgnq           modified for Loongson LS1B
 * 2015-07-06          chinesebear    modified for Loongson LS1C
 */

#include 
#include "net/synopGMAC.h"
#include 
#include "rthw.h"
#include "ls1c.h"
#include "ls1c_timer.h"
#include "ls1c_public.h"
#include "ls1c_gpio.h"
#include "mipsregs.h"


// 测试用的线程  
#define THREAD_TEST_PRIORITY                    (25)  
#define THREAD_TEST_STACK_SIZE                  (4*1024)        // 4k  
#define THREAD_TEST_TIMESLICE                   (10)  
  
struct rt_thread thread_test;  
ALIGN(8)
rt_uint8_t thread_test_stack[THREAD_TEST_STACK_SIZE];  


volatile rt_int32_t key_irq_flag = 0;

void ls1c_test_key_irqhandler(int irq, void *param)
{
    key_irq_flag = 1;
}
  
// 测试用的线程的入口  
void thread_test_entry(void *parameter)  
{
    unsigned int key_gpio = 85;     // GPIO85/I2C_SDA0
    int key_irq = LS1C_GPIO_TO_IRQ(key_gpio);

    // 初始化按键中断
    gpio_init(key_gpio, gpio_mode_input);
    gpio_set_irq_type(key_gpio, IRQ_TYPE_LEVEL_LOW);
    rt_hw_interrupt_install(key_irq, ls1c_test_key_irqhandler, RT_NULL, "KeyS3");
    rt_hw_interrupt_umask(key_irq);
    
    while (1)  
    {  
        if (1 == key_irq_flag)
        {
            // 延迟10ms,消抖
            rt_thread_delay(RT_TICK_PER_SECOND/100);
            key_irq_flag = 0;
            rt_thread_delay(1);
            rt_kprintf("[%s] Key press\n", __FUNCTION__);
        }
        rt_thread_delay(RT_TICK_PER_SECOND);  
    }  
}  



void rt_init_thread_entry(void *parameter)
{
	/* initialization RT-Thread Components */
	rt_components_init();

    // 初始化网卡
    rt_hw_eth_init();
}

int rt_application_init(void)
{
	rt_thread_t tid;
    rt_err_t result;

	/* create initialization thread */
	tid = rt_thread_create("init",
							rt_init_thread_entry, RT_NULL,
							4096, RT_THREAD_PRIORITY_MAX/3, 20);
	if (tid != RT_NULL)
		rt_thread_startup(tid);

  
    // 初始化测试用的线程  
    result = rt_thread_init(&thread_test,   
                            "thread_test",  
                            thread_test_entry,  
                            RT_NULL,  
                            &thread_test_stack[0],  
                            sizeof(thread_test_stack),  
                            THREAD_TEST_PRIORITY,  
                            THREAD_TEST_TIMESLICE);  
    if (RT_EOK == result)  
    {  
        rt_thread_startup(&thread_test);  
    }  
    else  
    {  
        return -1;  
    }  

	return 0;
}



感谢耐心看到这里!



你可能感兴趣的:(用龙芯1c库在RT-Thread下实现外部中断(GPIO中断、按键中断))