先来说下,这里为什么既涉及龙芯1c库,又涉及RT-Thread。中断相关函数是RT-Thread已经封装好的,比如设置中断处理函数,中断使能;但GPIO相关的函数却是使用龙芯1c库中的,比如GPIO初始化,将GPIO设为输入模式,设置GPIO中断类型(下降沿中断)等。
龙芯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官方源码中。
这里选择三个按键中的S3,所在GPIO为GPIO85/I2C_SDA0,led选择靠近RJ45的D2,所在GPIO为GPIO32,这个led在智龙的首发版、V2.0和V2.1中都有。
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;
}
感谢耐心看到这里!