原理图
LED 原理图如下图所示,连接GPIO19,GPIO21,GPIO22。
源码
// See LICENSE for license details.
#include <stdio.h>
#include <stdlib.h>
#include "platform.h"
#include <string.h>
#include "plic/plic_driver.h"
#include "encoding.h"
#include <unistd.h>
#include "stdatomic.h"
//计时器中断处理函数
void handle_m_time_interrupt(){
clear_csr(mie, MIE_MTIE);
// Reset the timer for 3s in the future.
// This also clears the existing timer interrupt.
volatile uint64_t * mtime = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIME);
volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
uint64_t now = *mtime;
uint64_t then = now + 1 * RTC_FREQ;
*mtimecmp = then;
GPIO_REG(GPIO_OUTPUT_VAL) ^= (0x1 << RED_LED_GPIO_OFFSET);
GPIO_REG(GPIO_OUTPUT_VAL) ^= (0x1 << GREEN_LED_GPIO_OFFSET);
GPIO_REG(GPIO_OUTPUT_VAL) ^= (0x1 << BLUE_LED_GPIO_OFFSET);
// Re-enable the timer interrupt.
set_csr(mie, MIE_MTIE);
}
//计时器初始化
void setup_mtime (){
// Set the machine timer to go off in 3 seconds.
// The
volatile uint64_t * mtime = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIME);
volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
uint64_t now = *mtime;
uint64_t then = now + 10 * RTC_FREQ;
*mtimecmp = then;
}
int main(int argc, char **argv)
{
//关闭GPIO的输入使能
GPIO_REG(GPIO_INPUT_EN) &= ~((0x1<< RED_LED_GPIO_OFFSET) | (0x1<< GREEN_LED_GPIO_OFFSET) | (0x1 << BLUE_LED_GPIO_OFFSET)) ;
//打开GPIO的输出使能:三个颜色的LED灯
GPIO_REG(GPIO_OUTPUT_EN) |= ((0x1<< RED_LED_GPIO_OFFSET)| (0x1<< GREEN_LED_GPIO_OFFSET) | (0x1 << BLUE_LED_GPIO_OFFSET)) ;
//设置GPIO的输出值
GPIO_REG(GPIO_OUTPUT_VAL) |= (0x1 << RED_LED_GPIO_OFFSET) ;
GPIO_REG(GPIO_OUTPUT_VAL) |= (0x1 << GREEN_LED_GPIO_OFFSET) ;
GPIO_REG(GPIO_OUTPUT_VAL) |= (0x1 << BLUE_LED_GPIO_OFFSET) ;
//关闭计时器中断局部使能
clear_csr(mie, MIE_MTIE);
//计时器初始化
setup_mtime();
//打开计时器中断局部使能
set_csr(mie, MIE_MTIE);
//打开中断的全局使能
set_csr(mstatus, MSTATUS_MIE);
return 0;
}
实验结果
每间隔 1 秒,可以看到 LED 灯闪烁一次。