有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 sky 于 2020-8-25 18:51 编辑
在“使用Eclipse和MCUXpresso IDE调试RV32M1-VEGA RISC-V开发板”中,我们介绍了如何构建和调试基于VEGA RISC-V开发板的应用程序。在本文中,我们将介绍如何基于最新的FreeRTOS V10.2.0版本为RISC-V开发板启用FreeRTOS。 在VEGA RISC-V板上运行FreeRTOS闪烁程序
最新发布的FreeRTOS V10.2.0版本提供了对RISC-V ISA的基本支持。本文介绍如何将FreeRTOS添加到VEGA SDK应用程序中,然后使用NXP MCUXpresso IDE或任何其它Eclipse IDE,以及GNU MCU Eclipse插件运行该示例程序:
VEGA RISC-V开发板上的FreeRTOS
以下是我们所需的组件: 1. MCUXpresso IDE以及VEGA RISC-V开发板 2. GitHub的McuLib和FreeRTOS 在现有VEGA项目启用FreeRTOS,请执行以下步骤: 1. 在MCUXpresso IDE中新建一个基于VEGA RISC-V(RI5CY)的项目,或使用VEGA SDK for RISC-V中的现有项目 2. 添加McuLib和FreeRTOS端口
McuLibrary
3. 将以下包含添加到编译器包含的库中: - ../McuLib/config
- ../McuLib/config/fonts
- ../McuLib/fonts
- ../McuLib/src
- ../McuLib/FreeRTOS/Source/include
- ../McuLib/FreeRTOS/Source/portable/GCC/RISC-V
- ../McuLib/SEGGER_RTT
- ../McuLib/SEGGER_Sysview
- ../McuLib/TraceRecorder/config
- ../McuLib/TraceRecorder/include
- ../McuLib/TraceRecorder/streamports/Jlink_RTT/include
- ../McuLib/HD44780
复制代码
4. 使用-include添加全局的包含 - "${ProjDirPath}/src/IncludeMcuLibConfig.h"
复制代码
-include设置
5. 在与-include一起使用的头文件中,指定与RISC-V一起使用的FreeRTOS,以及使用的SDK: - #define McuLib_CONFIG_SDK_VERSION_USED McuLib_CONFIG_SDK_MCUXPRESSO_2_0
- #define McuLib_CONFIG_CPU_IS_ARM_CORTEX_M (0)
- #define McuLib_CONFIG_CPU_IS_RISC_V (1)
- #define McuLib_CONFIG_SDK_USE_FREERTOS (1)
- #define McuLib_CONFIG_SDK_VERSION_MAJOR (2)
- #define McuLib_CONFIG_SDK_VERSION_MINOR (2)
- #define McuLib_CONFIG_SDK_VERSION_BUILD (0)
复制代码6. 在同一文件中,配置VEGA开发板上LED的引脚: - /* red LED */
- #define McuLED1_CONFIG_IS_LOW_ACTIVE (0)
- #define LEDpin1_CONFIG_GPIO_NAME GPIOA
- #define LEDpin1_CONFIG_PORT_NAME PORTA
- #define LEDpin1_CONFIG_PIN_NUMBER 24u
- #define LEDpin1_CONFIG_DO_PIN_MUXING 1
- /* green LED */
- #define McuLED2_CONFIG_IS_LOW_ACTIVE (0)
- #define LEDpin2_CONFIG_GPIO_NAME GPIOA
- #define LEDpin2_CONFIG_PORT_NAME PORTA
- #define LEDpin2_CONFIG_PIN_NUMBER 23u
- #define LEDpin2_CONFIG_DO_PIN_MUXING 1
- /* blue LED */
- #define McuLED3_CONFIG_IS_LOW_ACTIVE (0)
- #define LEDpin3_CONFIG_GPIO_NAME GPIOA
- #define LEDpin3_CONFIG_PORT_NAME PORTA
- #define LEDpin3_CONFIG_PIN_NUMBER 22u
- #define LEDpin3_CONFIG_DO_PIN_MUXING 1
- /* sts LED */
- #define McuLED4_CONFIG_IS_LOW_ACTIVE (0)
- #define LEDpin4_CONFIG_GPIO_NAME GPIOE
- #define LEDpin4_CONFIG_PORT_NAME PORTE
- #define LEDpin4_CONFIG_PIN_NUMBER 0u
- #define LEDpin4_CONFIG_DO_PIN_MUXING 1
复制代码7. 将标准启动代码替换为FreeRTOS特定的版本的启动代码。 此版本使用freertos_risc_v_trap_handler作为默认陷阱处理程序。 此版本取自V10.2.0的FreeRTOS发行版: - /* ------------------------------------------------------------------------- */
- /* @file: startup_RV32M1_ri5cy.s */
- /* @purpose: RI5CY Core Device Startup File */
- /* RV32M1_ri5cy */
- /* @version: 1.0 */
- /* @date: 2018-10-2 */
- /* @build: b180926 */
- /* ------------------------------------------------------------------------- */
- /* */
- /* Copyright 1997-2016 Freescale Semiconductor, Inc. */
- /* Copyright 2016-2018 NXP */
- /* All rights reserved. */
- /* */
- /* SPDX-License-Identifier: BSD-3-Clause */
- // Copyright 2017 ETH Zurich and University of Bologna.
- // Copyright and related rights are licensed under the Solderpad Hardware
- // License, Version 0.51 (the "License"); you may not use this file except in
- // compliance with the License. You may obtain a copy of the License at
- // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
- // or agreed to in writing, software, hardware and materials distributed under
- // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- // CONDITIONS OF ANY KIND, either express or implied. See the License for the
- // specific language governing permissions and limitations under the License.
- .extern freertos_risc_v_trap_handler
- #define EXCEPTION_STACK_SIZE 0x58
- .text
- .section .vectors, "ax"
- .option norvc;
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- jal x0, freertos_risc_v_trap_handler
- // reset vector
- jal x0, Reset_Handler
- // Illegal instrution exception
- jal x0, IllegalInstruction_Handler
- // ecall handler
- jal x0, freertos_risc_v_trap_handler
- // LSU error
- jal x0, LSU_Handler
- .section .startup
- /* Reset Handler */
- Reset_Handler:
- # Disable global interrupt. */
- csrci mstatus, 8
- # initialize stack pointer
- la sp, __StackTop
- # initialize global pointer
- la gp, __global_pointer
- #ifndef __NO_SYSTEM_INIT
- jal SystemInit
- #endif
- call __libc_init_array
- # Enable global interrupt. */
- csrsi mstatus, 8
- jal main
- ebreak
- .size Reset_Handler, . - Reset_Handler
- .global _init
- .global _fini
- _init:
- _fini:
- ret
- // saves all caller-saved registers (except return address)
- store_regs:
- sw x3, 0x00(x2) // gp
- sw x4, 0x04(x2) // tp
- sw x5, 0x08(x2) // t0
- sw x6, 0x0c(x2) // t1
- sw x7, 0x10(x2) // t2
- sw x10, 0x14(x2) // a0
- sw x11, 0x18(x2) // a1
- sw x12, 0x1c(x2) // a2
- sw x13, 0x20(x2) // a3
- sw x14, 0x24(x2) // a4
- sw x15, 0x28(x2) // a5
- sw x16, 0x2c(x2) // a6
- sw x17, 0x30(x2) // a7
- csrr a0, 0x7B0
- csrr a1, 0x7B1
- csrr a2, 0x7B2
- sw a0, 0x34(x2) // lpstart[0]
- sw a1, 0x38(x2) // lpend[0]
- sw a2, 0x3c(x2) // lpcount[0]
- csrr a0, 0x7B4
- csrr a1, 0x7B5
- csrr a2, 0x7B6
- sw a0, 0x40(x2) // lpstart[1]
- sw a1, 0x44(x2) // lpend[1]
- sw a2, 0x48(x2) // lpcount[1]
- csrr a0, 0x341
- sw a0, 0x4c(x2) // mepc
- csrr a1, 0x300
- sw a1, 0x50(x2) // mstatus
- jalr x0, x1
- // load back registers from stack
- end_except:
- lw a1, 0x50(x2) // mstatus
- csrrw x0, 0x300, a1
- lw a0, 0x4c(x2) // mepc
- csrrw x0, 0x341, a0
- lw a0, 0x40(x2) // lpstart[1]
- lw a1, 0x44(x2) // lpend[1]
- lw a2, 0x48(x2) // lpcount[1]
- csrrw x0, 0x7B4, a0
- csrrw x0, 0x7B5, a1
- csrrw x0, 0x7B6, a2
- lw a0, 0x34(x2) // lpstart[0]
- lw a1, 0x38(x2) // lpend[0]
- lw a2, 0x3c(x2) // lpcount[0]
- csrrw x0, 0x7B0, a0
- csrrw x0, 0x7B1, a1
- csrrw x0, 0x7B2, a2
- lw x3, 0x00(x2) // gp
- lw x4, 0x04(x2) // tp
- lw x5, 0x08(x2) // t0
- lw x6, 0x0c(x2) // t1
- lw x7, 0x10(x2) // t2
- lw x10, 0x14(x2) // a0
- lw x11, 0x18(x2) // a1
- lw x12, 0x1c(x2) // a2
- lw x13, 0x20(x2) // a3
- lw x14, 0x24(x2) // a4
- lw x15, 0x28(x2) // a5
- lw x16, 0x2c(x2) // a6
- lw x17, 0x30(x2) // a7
- lw x1, 0x54(x2)
- addi x2, x2, EXCEPTION_STACK_SIZE
- mret
- .weak IRQ_Handler
- .type IRQ_Handler, %function
- IRQ_Handler:
- addi x2, x2, -EXCEPTION_STACK_SIZE
- sw x1, 0x54(x2)
- jal x1, store_regs
- la x1, end_except
- csrr a0, mcause
- jal x0, SystemIrqHandler
- .size IRQ_Handler, . - IRQ_Handler
- .macro define_exception_entry entry_name handler_name
- .weak \entry_name
- \entry_name:
- addi x2, x2, -EXCEPTION_STACK_SIZE
- sw x1, 0x54(x2)
- jal x1, store_regs
- la x1, end_except
- jal x0, \handler_name
- .endm
- define_exception_entry IllegalInstruction_Handler IllegalInstruction_HandlerFunc
- define_exception_entry Ecall_Handler Ecall_HandlerFunc
- define_exception_entry LSU_Handler LSU_HandlerFunc
- .weak IllegalInstruction_HandlerFunc
- .type IllegalInstruction_HandlerFunc, %function
- IllegalInstruction_HandlerFunc:
- j .
- .size IllegalInstruction_HandlerFunc, . - IllegalInstruction_HandlerFunc
- .weak Ecall_HandlerFunc
- .type Ecall_HandlerFunc, %function
- Ecall_HandlerFunc:
- j .
- .size Ecall_HandlerFunc, . - Ecall_HandlerFunc
- .weak LSU_HandlerFunc
- .type LSU_HandlerFunc, %function
- LSU_HandlerFunc:
- j .
- .size LSU_HandlerFunc, . - LSU_HandlerFunc
复制代码8. 在链接器文件中,添加一个符号以标记IRQ堆栈的结尾: - __freertos_irq_stack_top = .;
复制代码
__freertos_irq_stack_top
9. 通过以上设置,我就可以在VEGA开发板上使用FreeRTOS和RISC-V。
演示应用程序 我已经在GitHub上添加了一个简单的“blinky”应用程序,代码如下: - /*
- * Application.c
- *
- * Author: Erich Styger
- */
- #include "Application.h"
- #include "McuLib.h"
- #include "McuWait.h"
- #include "McuLED1.h"
- #include "McuLED2.h"
- #include "McuLED3.h"
- #include "McuLED4.h"
- #include "McuRTOS.h"
- #include "FreeRTOS.h"
- #include "task.h"
-
- static void AppTask(void *pv) {
- for(;;) {
- McuLED1_On();
- vTaskDelay(pdMS_TO_TICKS(100));
- McuLED1_Off();
- McuLED2_On();
- vTaskDelay(pdMS_TO_TICKS(100));
- McuLED2_Off();
- McuLED3_On();
- vTaskDelay(pdMS_TO_TICKS(100));
- McuLED3_Off();
- McuLED4_On();
- vTaskDelay(pdMS_TO_TICKS(100));
- McuLED4_Off();
- vTaskDelay(pdMS_TO_TICKS(500));
- McuLED4_Neg();
- }
- }
-
- void APP_Run(void) {
- /* initialize McuLib drivers */
- McuLib_Init();
- McuRTOS_Init();
- McuWait_Init();
- McuLED1_Init(); /* red */
- McuLED2_Init(); /* green */
- McuLED3_Init(); /* blue */
- McuLED4_Init(); /* red status */
-
- if (xTaskCreate(AppTask, "App", 500/sizeof(StackType_t), NULL, tskIDLE_PRIORITY+1, NULL) != pdPASS) {
- for(;;){} /* error */
- }
- vTaskStartScheduler();
- /* shoul not end up here... */
- for(;;) { }
- }
复制代码以下是使用NXP MCUXpresso IDE 10.3.1在VEGA开发板上调试应用程序的屏幕截图:
使用MCUXpresso IDE调试RISC-V FreeRTOS应用程序
限制 该移植过程仍在“正在进行中”: ● 到目前为止,我只在RV32M1 RI5CY上运行它。 ● 它使用LPIT0计时器作为滴答计时器。 ● Tickless Idle模式尚未实现。 ● 尚不支持中断嵌套。 ● SEGGER SystemViewer尚未经过测试 ● Percepio Tracealizer尚未测试
故障排除 ● 目前我必须使用OpenOCD来调试VEGA板,而OpenOCD并不是很慢(与J-Link相比)。如果调试失败,请尝试重新启动电路板和调试器。 ● OpenOCD取代了Windows USB驱动程序,这显然影响了以正常方式使用J-Link。尝试将USB驱动程序恢复为原始驱动程序并重新启动主机。 ● 使用OpenOCD调试任务代码通常会进入中断服务程序:解决方法是设置断点,然后运行。 ● FreeRTOS V10.2.0改变了内部的数据结构,可能破坏RTOS调试过程。例如,FreeRTOS定时器可能无法在调试器中正确显示。作为一种解决方法,我已经为FreeRTOS timers.c添加了一个定义来支持以前的API: - #define TIMER_LEGACY_API (1) /* << EST: needed to have TAD working */
复制代码总结 我现在可以使用Eclipse(MCUXpresso IDE)在VEGA开发板上运行FreeRTOS V10.2.0。 IDE具有非常有用的FreeRTOS调试视图。最大的问题是OpenOCD调试器。它有效,但在使用RTOS时速度很慢且有很多限制。我可能需要探索除OpenOCD之外的其他调试器,以获得更好的调试体验。 参考链接 ◾ FreeRTOS on RISC-V: https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html ◾ FreeRTOS demo for PULP/VEGA: https://www.freertos.org/RTOS-RISC-V-Vegaboard_Pulp.html 本篇完,感谢关注:RISC-V单片机中文网 |