前言
織女星開發板是OPEN-ISA社區為中國大陸地區定制的一款體積小、功耗超低和功能豐富的 RISC-V評估開發板,基於NXP半導體四核異構RV32M1主控芯片。
- 兩個RISC-V核:RI5CY + ZERO_RISCY。
- 兩個ARM核: Cortex-M4F + Cortex-M0+ 。
4個核被分為兩個子系統,大核CM4F/RI5CY和小核CM0+/ZERO-RISCY,片上集成1.25 MB Flash 、384 KB SRAM,其中1 MB的Flash被大核所使用,起始地址0x0000_0000,另外的256 KB Flash被小核所使用,起始地址0x0100_0000。利用該開發板,用戶可以快速建立一個使用 RV32M1 的 RISC-V應用和演示系統。詳細的介紹可以參考: 真正的RISC-V開發板——VEGA織女星開發板開箱評測 ,本篇文章介紹如何基於RISC-V RI5CY/ZERO內核來點亮板載的RGB_LED/STS_LED、讀取按鍵輸入,演示GPIO的輸入輸出和外部中斷功能。
准備工作
在進行以下操作之前,要確保開發環境已經搭建完成,而且能正常下載調試。
- 織女星開發板RISC-V開發環境:Eclipse + riscv32 工具鏈 + OpenOCD調試工具
- 織女星開發板SDK包:rv32m1_sdk_riscv
- 織女星開發板的原理圖
- RV32M1參考手冊
以上資料的獲取、開發環境搭建和啟動模式修改等教程,可以到官方中文論壇查找:www.open-isa.cn
或者是參考我分享的以下文章:
- 真正的RISC-V開發板——VEGA織女星開發板開箱評測
- 手把手教你搭建織女星開發板RISC-V開發環境
- 織女星開發板啟動模式修改——從ARM M4核啟動
- 織女星開發板調試器升級為Jlink固件
- 織女星開發板RISC-V內核實現微秒級精確延時
寄存器簡介
根據RV32M1參考手冊GPIO章節的介紹,我們可以獲得關於GPIO相關寄存器信息:
各GPIO組的基地址:
GPIOA——4802_0000h
GPIOB——4802_0040h
GPIOC——4802_0080h
GPIOD——4802_00C0h
GPIOE——4100_F000h
GPIO配置PCR寄存器
這是一個32位的寄存器,每一個引腳都有對應的一個PORTx_PCRn,用來配置GPIO的以下功能:
- 上下拉配置
- 翻轉速率控制
- 開漏使能
- 無源輸入濾波器
- 寄存器鎖定
- 復用功能設置
以PA0控制寄存器,PORTA_PCR0為例:
通過查看參考手冊,可以了解到各Bit的功能:
- ISF:1位,中斷狀態標志
- IRQC:4位,配置中斷方式和DMA功能
- LK:1位,是否鎖定PCR寄存
- MUX:3位,復用功能配置
- ODE:1位,推挽開漏配置
- PFE:1位,濾波器配置
- SRE:1位,翻轉速率配置
- PE:1位,上下拉使能
- PS:1位,上下拉配置
詳細的配置介紹可以查看參考手冊。官方庫fsl_port中的
PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_pin_config_t *config)
PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux)
PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)
PORT_SetPinDriveStrength(PORT_Type* base, uint32_t pin, uint8_t strength)
這些函數就是控制的這個PCR寄存器。
GPIO控制寄存器
主要包括控制GPIO輸入輸出控制,讀取輸入,控制輸出,方向控制等。
寄存器描述和地址偏移量:
RV32M1的GPIO共有6個32位的控制寄存器,從字面意思可以直接知道每個寄存器的功能:
- PDOR:數據輸出寄存器,指定位寫入0/1,輸出0/1
- PSOR:端口置位輸出寄存器,指定位寫1,置位輸出1,寫0狀態不變
- PCOR:端口復位輸出寄存器,指定位寫1,復位輸出0,寫0狀態不變
- PTOR:端口反轉輸出寄存器,指定位寫1,反轉輸出,寫0狀態不變
- PDIR:端口輸入寄存器,讀取指定位輸入狀態
- PDDR:端口方向配置寄存器,指定位寫0作為輸入,寫1作為輸出
官方庫中的fsl_gpio文件中實現的函數就是控制的這幾個寄存器。
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
void GPIO_WritePinOutput(GPIO_Type *base, uint32_t pin, uint8_t output)
void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask)
void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask)
void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t mask)
庫函數簡介
和其他的MCU一樣,由於RV32M1的寄存器眾多,為了方便使用,增強程序的可讀性,官方開發了庫函數,來實現對寄存器的控制,本質上還是操作的寄存器。GPIO控制的庫主要由fsl_gpio和fsl_port兩個文件組成,其中fsl_gpio主要是對GPIO的控制,如讀取輸入,控制輸出,清除中斷標志等,而fsl_port主要實現對GPIO工作的模式進行配置,如復用功能,上拉下拉,開漏推挽,中斷觸發方式,DMA功能等進行設置。
下面簡單介紹幾個常用的函數:
PORT_SetPinConfig
配置GPIO的復用功能,驅動能力,推挽開漏,上下拉,濾波器,翻轉速率等功能,基於PCR寄存器實現。
port_pin_config_t config;
config.driveStrength = kPORT_HighDriveStrength; //驅動能力配置
config.mux = kPORT_MuxAsGpio; //通用GPIO
config.openDrainEnable = kPORT_OpenDrainDisable; //推挽
config.passiveFilterEnable = kPORT_PassiveFilterDisable;//濾波器
config.pullSelect = kPORT_PullUp; //上拉
config.slewRate = kPORT_FastSlewRate; //翻轉速率
PORT_SetPinConfig(PORTA, 22, &config); //配置GPIOA22
PORT_SetPinMux
配置GPIO的復用功能,基於PCR寄存器實現。
//PA22作為普通GPIO使用
PORT_SetPinMux(PORTA, 22, kPORT_MuxAsGpio);
//PA25作為UART1_RX功能
PORT_SetPinMux(PORTA, 25, kPORT_MuxAlt2);
具體復用為哪種功能,不同的引腳有不同的復用功能,對應的ALTn,可以查看參考手冊RV32M1 Pinout介紹。
PORT_SetPinConfig已經包含了PORT_SetPinMux的功能,可以只使用PORT_SetPinConfig來GPIO功能的配置。PORT_SetPinMux函數不推薦和PORT_SetPinsConfig函數一起使用:
This function is NOT recommended to use together with the PORT_SetPinsConfig, because the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux is reset to zero : kPORT_PinDisabledOrAnalog). This function is recommended to use to reset the pin mux
GPIO_PinInit
控制GPIO的輸入輸出方式,及默認輸出電平,基於PDDR、PCOR、PSOR寄存器實現。
gpio_pin_config_t io_init;
//配置輸出/輸出模式
io_init.outputLogic = 0; //默認輸出0
io_init.pinDirection = kGPIO_DigitalOutput; //數字輸出
GPIO_PinInit(LED_RGB_GPIO, LED_RED_Pin, &io_init); //LED引腳配置
GPIO_WritePinOutput
指定引腳輸出高低電平,基於PCOR和PSOR寄存器實現。
GPIO_WritePinOutput(GPIOA, 22, 1); //PA22輸出1
GPIO_TogglePinsOutput
指定引腳輸出翻轉,基於PTOR寄存器實現
GPIO_TogglePinsOutput(GPIOA, 1 << 22); //PA22輸出翻轉
GPIO_ReadPinInput
讀取GPIO輸入狀態,基於PDIR寄存器實現
in = GPIO_ReadPinInput(GPIOA, 22); //讀取PA22輸入狀態
GPIO操作的函數還有很多,詳細的介紹和實現可以直接查看庫函數源碼。
RGB LED的初始化
從原理圖中我們可以得知,織女星開發板上共有4個用戶可控制的LED,包括3個RGB LED和1個紅色LED,均采用MOS來驅動,引腳輸出高電平LED點亮,和GPIO的對應關系如下:
LED_RED——PTA24
LED_GREEN——PTA23
LED_BLUE——PTA22
LED_STS——PTE0
所以我們需要配置PTA22/PTA23/PTA24為普通推挽輸出方式,然后輸出高低電平就可以控制LED閃爍了。
led_driver.c文件內容
#include "led_driver.h"
void LED_RGB_Init(void)
{
gpio_pin_config_t io_init;
port_pin_config_t config;
//配置輸出/輸出模式
io_init.outputLogic = 0;
io_init.pinDirection = kGPIO_DigitalOutput;
config.driveStrength = kPORT_HighDriveStrength; //驅動能力
config.lockRegister = kPORT_LockRegister; //PCR寄存器被鎖定,不能再次改變
config.mux = kPORT_MuxAsGpio; //通用GPIO
config.openDrainEnable = kPORT_OpenDrainDisable; //推挽輸出
config.passiveFilterEnable = kPORT_PassiveFilterDisable;//濾波器
config.pullSelect = kPORT_PullUp; //上拉
config.slewRate = kPORT_FastSlewRate; //翻轉速率
CLOCK_EnableClock(LED_RGB_Clk_Name);
CLOCK_EnableClock(LED_STS_Clk_Name); //GPIOE時鍾必須一直開啟
CLOCK_EnableClock(kCLOCK_Rgpio1); //GPIOE配置需要使能這個時鍾
/*以下兩個函數都可以配置端口功能*/
PORT_SetPinConfig(LED_RGB_Port, LED_RED_Pin, &config); //配置功能更詳細
PORT_SetPinConfig(LED_RGB_Port, LED_GREEN_Pin, &config);
PORT_SetPinConfig(LED_RGB_Port, LED_BLUE_Pin, &config);
PORT_SetPinConfig(LED_STS_Port, LED_STS_Pin, &config);
// PORT_SetPinMux(LED_RGB_Port, LED_RED_Pin, kPORT_MuxAsGpio); //只能配置是否復用
// PORT_SetPinMux(LED_RGB_Port, LED_GREEN_Pin, kPORT_MuxAsGpio);
// PORT_SetPinMux(LED_RGB_Port, LED_BLUE_Pin, kPORT_MuxAsGpio);
// CLOCK_DisableClock(LED_RGB_Clk_Name); //可以在配置完成之后關閉時鍾,不影響使用
GPIO_PinInit(LED_RGB_GPIO, LED_RED_Pin, &io_init);
GPIO_PinInit(LED_RGB_GPIO, LED_GREEN_Pin, &io_init);
GPIO_PinInit(LED_RGB_GPIO, LED_BLUE_Pin, &io_init);
GPIO_PinInit(LED_STS_GPIO, LED_STS_Pin, &io_init);
}
要注意的是,時鍾使能要放在GPIO配置之前,否則不能訪問GPIO配置寄存器,在配置完成之后可以關閉時鍾,也可以一直開啟。其中GPIOE非常特殊,要想使用GPIOE,必須使能Rgpio1快速時鍾,其他的GPIO配置不需要,這是因為GPIOE屬於快速GPIO,和其他幾組GPIO不是同一個總線。
CLOCK_EnableClock(kCLOCK_Rgpio1); //GPIOE配置需要使能這個時鍾
led_driver.h文件內容
#ifndef __LED_DRIVER_H__
#define __LED_DRIVER_H__
#include "fsl_gpio.h"
#include "fsl_port.h"
#include "fsl_clock.h"
/*
LED_RGB_BLUE - A22
LED_RGB_GREEN - A23
LED_RGB_RED - A24
LED_STS - E0
*/
#define LED_RED_Pin 24
#define LED_GREEN_Pin 23
#define LED_BLUE_Pin 22
#define LED_RGB_Port PORTA
#define LED_RGB_GPIO GPIOA
#define LED_RGB_Clk_Name kCLOCK_PortA
#define LED_STS_Pin 0
#define LED_STS_Port PORTE
#define LED_STS_GPIO GPIOE
#define LED_STS_Clk_Name kCLOCK_PortE
#define LED_STS_ON GPIO_WritePinOutput(LED_STS_GPIO, LED_STS_Pin, 1)
#define LED_STS_OFF GPIO_WritePinOutput(LED_STS_GPIO, LED_STS_Pin, 0)
#define LED_STS_TOGGLE GPIO_TogglePinsOutput(LED_STS_GPIO, 1 << LED_STS_Pin)
#define LED_RED_ON GPIO_WritePinOutput(LED_RGB_GPIO, LED_RED_Pin, 1)
#define LED_RED_OFF GPIO_WritePinOutput(LED_RGB_GPIO, LED_RED_Pin, 0)
#define LED_RED_TOGGLE GPIO_TogglePinsOutput(LED_RGB_GPIO, 1 << LED_RED_Pin)
#define LED_GREEN_ON GPIO_WritePinOutput(LED_RGB_GPIO, LED_GREEN_Pin, 1)
#define LED_GREEN_OFF GPIO_WritePinOutput(LED_RGB_GPIO, LED_GREEN_Pin, 0)
#define LED_GREEN_TOGGLE GPIO_TogglePinsOutput(LED_RGB_GPIO, 1 << LED_GREEN_Pin)
#define LED_BLUE_ON GPIO_WritePinOutput(LED_RGB_GPIO, LED_BLUE_Pin, 1)
#define LED_BLUE_OFF GPIO_WritePinOutput(LED_RGB_GPIO, LED_BLUE_Pin, 0)
#define LED_BLUE_TOGGLE GPIO_TogglePinsOutput(LED_RGB_GPIO, 1 << LED_BLUE_Pin)
void LED_RGB_Init(void);
#endif
頭文件中通過宏定義的方式實現了LED的亮滅和翻轉控制。
板載按鍵初始化
按鍵部分硬件原理圖,按下為低電平。
button_driver.c文件內容
#include "button_driver.h"
#include "delay.h"
#include "led_driver.h"
//按鍵使用普通輸入GPIO方式
void Button_Init(void)
{
gpio_pin_config_t io_init;
port_pin_config_t config;
io_init.outputLogic = 0;
io_init.pinDirection = kGPIO_DigitalInput;
config.mux = kPORT_MuxAsGpio; //通用GPIO
config.lockRegister = kPORT_LockRegister; //PCR寄存器被鎖定,不能再次改變
config.pullSelect = kPORT_PullUp; //上拉
config.slewRate = kPORT_FastSlewRate; //翻轉速率
config.lockRegister = kPORT_LockRegister; //PCR寄存器被鎖定,不能再次改變
config.passiveFilterEnable = kPORT_PassiveFilterEnable; //濾波器
CLOCK_EnableClock(BTN_SW2_Clk_Name);
CLOCK_EnableClock(BTN_SW3_Clk_Name);
// CLOCK_EnableClock(BTN_SW4_Clk_Name);
// CLOCK_EnableClock(BTN_SW5_Clk_Name);
CLOCK_EnableClock(kCLOCK_Rgpio1); //GPIOE配置需要使能這個時鍾
//以下兩個函數功能一樣
PORT_SetPinConfig(BTN_SW2_Port, BTN_SW2_Pin, &config);
PORT_SetPinConfig(BTN_SW3_Port, BTN_SW3_Pin, &config);
PORT_SetPinConfig(BTN_SW4_Port, BTN_SW4_Pin, &config);
PORT_SetPinConfig(BTN_SW5_Port, BTN_SW5_Pin, &config);
// PORT_SetPinMux(BTN_SW2_Port, BTN_SW2_Pin, kPORT_MuxAsGpio); //設置IO模式為通用GPIO
// PORT_SetPinMux(BTN_SW3_Port, BTN_SW3_Pin, kPORT_MuxAsGpio); //設置IO模式為通用GPIO
// PORT_SetPinMux(BTN_SW4_Port, BTN_SW4_Pin, kPORT_MuxAsGpio); //設置IO模式為通用GPIO
// PORT_SetPinMux(BTN_SW5_Port, BTN_SW5_Pin, kPORT_MuxAsGpio); //設置IO模式為通用GPIO
GPIO_PinInit(BTN_SW2_GPIO, BTN_SW2_Pin, &io_init);
GPIO_PinInit(BTN_SW3_GPIO, BTN_SW3_Pin, &io_init);
GPIO_PinInit(BTN_SW4_GPIO, BTN_SW4_Pin, &io_init);
GPIO_PinInit(BTN_SW5_GPIO, BTN_SW5_Pin, &io_init);
}
//按鍵使用外部中斷初始化函數
void ButtonInterruptInit(void)
{
gpio_pin_config_t io_init;
port_pin_config_t config;
io_init.outputLogic = 0;
io_init.pinDirection = kGPIO_DigitalInput;
config.mux = kPORT_MuxAsGpio; //通用GPIO
config.lockRegister = kPORT_LockRegister; //PCR寄存器被鎖定,不能再次改變
config.pullSelect = kPORT_PullUp; //上拉
config.slewRate = kPORT_FastSlewRate; //翻轉速率
config.lockRegister = kPORT_LockRegister; //PCR寄存器被鎖定,不能再次改變
config.passiveFilterEnable = kPORT_PassiveFilterEnable; //濾波器
CLOCK_EnableClock(BTN_SW2_Clk_Name);
CLOCK_EnableClock(BTN_SW3_Clk_Name);
// CLOCK_EnableClock(BTN_SW4_Clk_Name);
// CLOCK_EnableClock(BTN_SW5_Clk_Name);
CLOCK_EnableClock(kCLOCK_Rgpio1); //GPIOE配置需要使能這個時鍾
//以下兩個函數功能一樣
PORT_SetPinConfig(BTN_SW2_Port, BTN_SW2_Pin, &config);
PORT_SetPinConfig(BTN_SW3_Port, BTN_SW3_Pin, &config);
PORT_SetPinConfig(BTN_SW4_Port, BTN_SW4_Pin, &config);
PORT_SetPinConfig(BTN_SW5_Port, BTN_SW5_Pin, &config);
//設置中斷觸發方式
PORT_SetPinInterruptConfig(BTN_SW2_Port, BTN_SW2_Pin, kPORT_InterruptFallingEdge); //下降沿觸發中斷
PORT_SetPinInterruptConfig(BTN_SW3_Port, BTN_SW3_Pin, kPORT_InterruptFallingEdge);
PORT_SetPinInterruptConfig(BTN_SW4_Port, BTN_SW4_Pin, kPORT_InterruptFallingEdge);
PORT_SetPinInterruptConfig(BTN_SW5_Port, BTN_SW5_Pin, kPORT_InterruptFallingEdge);
#if defined(CPU_RV32M1_ri5cy)
//RI5CY Core GPIOE需要使能以下兩個函數, ZERO Core不用
INTMUX_Init(INTMUX0);
INTMUX_EnableInterrupt(INTMUX0, 0, PORTE_IRQn);
#endif
EnableIRQ(BTN_SW2_IRQ);
EnableIRQ(BTN_SW3_IRQ);
// EnableIRQ(BTN_SW4_IRQ);
// EnableIRQ(BTN_SW5_IRQ);
GPIO_PinInit(BTN_SW2_GPIO, BTN_SW2_Pin, &io_init);
GPIO_PinInit(BTN_SW3_GPIO, BTN_SW3_Pin, &io_init);
GPIO_PinInit(BTN_SW4_GPIO, BTN_SW4_Pin, &io_init);
GPIO_PinInit(BTN_SW5_GPIO, BTN_SW5_Pin, &io_init);
}
void PORTA_IRQHandler(void)
{
GPIO_ClearPinsInterruptFlags(BTN_SW2_GPIO, 1U << BTN_SW2_Pin);
LED_STS_TOGGLE;
LOG("sw2 is pressed \r\n");
}
//GPIOE外部中斷函數
void PORTE_IRQHandler(void)
{
uint32_t flag;
flag = GPIO_GetPinsInterruptFlags(BTN_SW3_GPIO);
GPIO_ClearPinsInterruptFlags(BTN_SW3_GPIO, 1U << BTN_SW3_Pin);
GPIO_ClearPinsInterruptFlags(BTN_SW4_GPIO, 1U << BTN_SW4_Pin);
GPIO_ClearPinsInterruptFlags(BTN_SW5_GPIO, 1U << BTN_SW5_Pin);
if(flag & (1 << BTN_SW3_Pin)) //SW3產生中斷
{
LED_RED_TOGGLE;
LOG("sw3 is pressed \r\n");
}
else if(flag & (1 << BTN_SW4_Pin))
{
LED_GREEN_TOGGLE;
LOG("sw4 is pressed \r\n");
}
else if(flag & (1 << BTN_SW5_Pin))
{
LED_BLUE_TOGGLE;
LOG("sw5 is pressed \r\n");
}
}
//輪詢方式獲取按鍵狀態
uint8_t GetKey(void)
{
uint8_t key = 1;
//按鍵按下為0
if(BTN_SW2_IN && BTN_SW3_IN && BTN_SW4_IN && BTN_SW5_IN)
{
Delay_ms(10);
if(!BTN_SW2_IN)
key = 2;
else if(!BTN_SW3_IN)
key = 3;
else if(!BTN_SW4_IN)
key = 4;
else if(!BTN_SW5_IN)
key = 5;
while(!(BTN_SW2_IN && BTN_SW3_IN && BTN_SW4_IN && BTN_SW5_IN));
}
return key;
}
按鍵配置為上拉輸入模式,同樣如果使用GPIOE作為通用GPIO輸入,還需要使能Rgpio1時鍾:
CLOCK_EnableClock(kCLOCK_Rgpio1); //GPIOE配置需要使能這個時鍾
如果使用GPIOE的外部中斷功能,還需要使能INTMUX:
#if defined(CPU_RV32M1_ri5cy)
//RI5CY Core GPIOE需要使能以下兩個函數, ZERO Core不用
INTMUX_Init(INTMUX0);
INTMUX_EnableInterrupt(INTMUX0, 0, PORTE_IRQn);
#endif
button_driver.h文件內容
#ifndef __BUTTON_DRIVER_H__
#define __BUTTON_DRIVER_H__
#include "fsl_gpio.h"
#include "fsl_port.h"
#include "fsl_intmux.h"
/*
* SW2 - A0
* SW3 - E12
* SW4 - E8
* SW5 - E9
* */
//按下為低電平
#define BTN_SW2_GPIO GPIOA
#define BTN_SW3_GPIO GPIOE
#define BTN_SW4_GPIO GPIOE
#define BTN_SW5_GPIO GPIOE
#define BTN_SW2_Pin 0
#define BTN_SW3_Pin 12
#define BTN_SW4_Pin 8
#define BTN_SW5_Pin 9
#define BTN_SW2_Port PORTA
#define BTN_SW3_Port PORTE
#define BTN_SW4_Port PORTE
#define BTN_SW5_Port PORTE
#define BTN_SW2_IRQ PORTA_IRQn
#define BTN_SW3_IRQ PORTE_IRQn
#define BTN_SW4_IRQ PORTE_IRQn
#define BTN_SW5_IRQ PORTE_IRQn
#define BTN_SW2_Clk_Name kCLOCK_PortA
#define BTN_SW3_Clk_Name kCLOCK_PortE
#define BTN_SW4_Clk_Name kCLOCK_PortE
#define BTN_SW5_Clk_Name kCLOCK_PortE
#define BTN_SW2_IN GPIO_ReadPinInput(BTN_SW2_GPIO, BTN_SW2_Pin)
#define BTN_SW3_IN GPIO_ReadPinInput(BTN_SW3_GPIO, BTN_SW3_Pin)
#define BTN_SW4_IN GPIO_ReadPinInput(BTN_SW4_GPIO, BTN_SW4_Pin)
#define BTN_SW5_IN GPIO_ReadPinInput(BTN_SW5_GPIO, BTN_SW5_Pin)
/*
#define BTN_SW2_IN ReadGPIO(BTN_SW2_GPIO, BTN_SW2_Pin)
#define BTN_SW3_IN ReadGPIO(BTN_SW3_GPIO, BTN_SW3_Pin)
#define BTN_SW4_IN ReadGPIO(BTN_SW4_GPIO, BTN_SW4_Pin)
#define BTN_SW5_IN ReadGPIO(BTN_SW5_GPIO, BTN_SW5_Pin)
*/
void Button_Init(void);
uint8_t GetKey(void);
void ButtonInterruptInit(void);
#endif
通過GPIO讀取函數來獲取按鍵輸入狀態,或者是通過中斷標志來判斷輸入狀態。
主函數應用
使用外部中斷方式讀取按鍵輸入狀態。
#include "main.h"
extern uint32_t SystemCoreClock;
int main(void)
{
BOARD_BootClockRUN(); //ϵͳʱ֓Ťփ
UART0_Init();
Delay_Init();
LOG("SystemCoreClock: %ld \r\n", SystemCoreClock);
#if defined(CPU_RV32M1_ri5cy)
LOG("RV32M1 RISC-V RI5CY Core Demo \r\n");
#elif defined(CPU_RV32M1_zero_riscy)
LOG("RV32M1 RISC-V ZERO Core Demo \r\n");
#endif
LED_RGB_Init();
// Button_Init();
ButtonInterruptInit();
// LPMTR2_Init();
// LPIT1_CH3_Init();
while (1)
{
}
}
代碼下載
織女星開發板VEGA_Lite支持從4個核啟動,所以在進行程序下載之前,要確認當前的啟動模式和當前的工程是對應的。如當前工程是使用RISC-V RI5CY核來驅動GPIO,那么就需要配置芯片啟動模式為RI5CY核啟動。否則會不能下載。關於啟動模式的修改可以參考:織女星開發板啟動模式修改
- RI5CY驅動GPIO源碼下載:RI5CY_GPIO_Demo.rar
- ZERO驅動GPIO源碼下載:ZERO_GPIO_Demo.rar
總結
RV32M1芯片的GPIOE與其他幾組GPIO配置方法稍有不同,使用時要特別注意。
參考資料
- MCUXpresso SDK API參考手冊
- RV32M1_Vega_Develop_Environment_Setup.pdf
- [RV32M1數據手冊](https://github.com/open-isa-org/open-isa.org/raw/master/Reference Manual and Data Sheet/RV32M1DS_Rev.1.1.pdf)
- [RV32M1參考手冊](https://github.com/open-isa-org/open-isa.org/raw/master/Reference Manual and Data Sheet/RV32M1RM_Rev.1.1.pdf)
- 織女星開發板快速入門指南.pdf
推薦閱讀
- 真正的RISC-V開發板——VEGA織女星開發板開箱評測
- 手把手教你搭建織女星開發板RISC-V開發環境
- 織女星開發板啟動模式修改——從ARM M4核啟動
- 織女星開發板調試器升級為Jlink固件
- 織女星開發板RISC-V內核實現微秒級精確延時
- 個人博客:www.wangchaochao.top
- 我的公眾號:mcu149