一板网电子技术论坛

发表于: 2019-4-23 11:50:11 | 显示全部楼层

在“使用Eclipse和MCUXpresso IDE调试RV32M1-VEGA RISC-V开发板”中,我们介绍了如何构建和调试基于VEGA RISC-V开发板的应用程序。在本文中,我们将介绍如何基于最新的FreeRTOS V10.2.0版本为RISC-V开发板启用FreeRTOS。

blinky-with-freertos-on-the-vega-risc-v-board.png

在VEGA RISC-V板上运行FreeRTOS闪烁程序


最新发布的FreeRTOS V10.2.0版本提供了对RISC-V ISA的基本支持。本文介绍如何将FreeRTOS添加到VEGA SDK应用程序中,然后使用NXP MCUXpresso IDE或任何其它Eclipse IDE,以及GNU MCU Eclipse插件运行该示例程序:

freertos-on-vega-risc-v-board.png

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.png

McuLibrary


3.    将以下包含添加到编译器包含的库中:

  1. ../McuLib/config
  2. ../McuLib/config/fonts
  3. ../McuLib/fonts
  4. ../McuLib/src
  5. ../McuLib/FreeRTOS/Source/include
  6. ../McuLib/FreeRTOS/Source/portable/GCC/RISC-V
  7. ../McuLib/SEGGER_RTT
  8. ../McuLib/SEGGER_Sysview
  9. ../McuLib/TraceRecorder/config
  10. ../McuLib/TraceRecorder/include
  11. ../McuLib/TraceRecorder/streamports/Jlink_RTT/include
  12. ../McuLib/HD44780
复制代码

mculib-includes.png


4.    使用-include添加全局的包含

  1. "${ProjDirPath}/src/IncludeMcuLibConfig.h"
复制代码

include-setting.png

-include设置


5.  在与-include一起使用的头文件中,指定与RISC-V一起使用的FreeRTOS,以及使用的SDK:

  1. #define McuLib_CONFIG_SDK_VERSION_USED McuLib_CONFIG_SDK_MCUXPRESSO_2_0

  2. #define McuLib_CONFIG_CPU_IS_ARM_CORTEX_M (0)
  3. #define McuLib_CONFIG_CPU_IS_RISC_V (1)

  4. #define McuLib_CONFIG_SDK_USE_FREERTOS (1)

  5. #define McuLib_CONFIG_SDK_VERSION_MAJOR (2)
  6. #define McuLib_CONFIG_SDK_VERSION_MINOR (2)
  7. #define McuLib_CONFIG_SDK_VERSION_BUILD (0)
复制代码

6.    在同一文件中,配置VEGA开发板上LED的引脚:

  1. /* red LED */
  2. #define McuLED1_CONFIG_IS_LOW_ACTIVE   (0)
  3. #define LEDpin1_CONFIG_GPIO_NAME       GPIOA
  4. #define LEDpin1_CONFIG_PORT_NAME       PORTA
  5. #define LEDpin1_CONFIG_PIN_NUMBER      24u
  6. #define LEDpin1_CONFIG_DO_PIN_MUXING   1

  7. /* green LED */
  8. #define McuLED2_CONFIG_IS_LOW_ACTIVE   (0)
  9. #define LEDpin2_CONFIG_GPIO_NAME       GPIOA
  10. #define LEDpin2_CONFIG_PORT_NAME       PORTA
  11. #define LEDpin2_CONFIG_PIN_NUMBER      23u
  12. #define LEDpin2_CONFIG_DO_PIN_MUXING   1

  13. /* blue LED */
  14. #define McuLED3_CONFIG_IS_LOW_ACTIVE   (0)
  15. #define LEDpin3_CONFIG_GPIO_NAME       GPIOA
  16. #define LEDpin3_CONFIG_PORT_NAME       PORTA
  17. #define LEDpin3_CONFIG_PIN_NUMBER      22u
  18. #define LEDpin3_CONFIG_DO_PIN_MUXING   1

  19. /* sts LED */
  20. #define McuLED4_CONFIG_IS_LOW_ACTIVE   (0)
  21. #define LEDpin4_CONFIG_GPIO_NAME       GPIOE
  22. #define LEDpin4_CONFIG_PORT_NAME       PORTE
  23. #define LEDpin4_CONFIG_PIN_NUMBER      0u
  24. #define LEDpin4_CONFIG_DO_PIN_MUXING   1
复制代码

7.    将标准启动代码替换为FreeRTOS特定的版本的启动代码。 此版本使用freertos_risc_v_trap_handler作为默认陷阱处理程序。 此版本取自V10.2.0的FreeRTOS发行版:

  1. /* ------------------------------------------------------------------------- */
  2. /*  @file:    startup_RV32M1_ri5cy.s                                         */
  3. /*  @purpose: RI5CY Core Device Startup File                                 */
  4. /*            RV32M1_ri5cy                                                   */
  5. /*  @version: 1.0                                                            */
  6. /*  @date:    2018-10-2                                                      */
  7. /*  @build:   b180926                                                        */
  8. /* ------------------------------------------------------------------------- */
  9. /*                                                                           */
  10. /* Copyright 1997-2016 Freescale Semiconductor, Inc.                         */
  11. /* Copyright 2016-2018 NXP                                                   */
  12. /* All rights reserved.                                                      */
  13. /*                                                                           */
  14. /* SPDX-License-Identifier: BSD-3-Clause                                     */


  15. // Copyright 2017 ETH Zurich and University of Bologna.
  16. // Copyright and related rights are licensed under the Solderpad Hardware
  17. // License, Version 0.51 (the "License"); you may not use this file except in
  18. // compliance with the License.  You may obtain a copy of the License at
  19. // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
  20. // or agreed to in writing, software, hardware and materials distributed under
  21. // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  22. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  23. // specific language governing permissions and limitations under the License.

  24. .extern freertos_risc_v_trap_handler

  25. #define EXCEPTION_STACK_SIZE 0x58

  26.     .text
  27.     .section .vectors, "ax"
  28.     .option norvc;

  29.     jal x0, freertos_risc_v_trap_handler
  30.     jal x0, freertos_risc_v_trap_handler
  31.     jal x0, freertos_risc_v_trap_handler
  32.     jal x0, freertos_risc_v_trap_handler
  33.     jal x0, freertos_risc_v_trap_handler
  34.     jal x0, freertos_risc_v_trap_handler
  35.     jal x0, freertos_risc_v_trap_handler
  36.     jal x0, freertos_risc_v_trap_handler
  37.     jal x0, freertos_risc_v_trap_handler
  38.     jal x0, freertos_risc_v_trap_handler
  39.     jal x0, freertos_risc_v_trap_handler
  40.     jal x0, freertos_risc_v_trap_handler
  41.     jal x0, freertos_risc_v_trap_handler
  42.     jal x0, freertos_risc_v_trap_handler
  43.     jal x0, freertos_risc_v_trap_handler
  44.     jal x0, freertos_risc_v_trap_handler
  45.     jal x0, freertos_risc_v_trap_handler
  46.     jal x0, freertos_risc_v_trap_handler
  47.     jal x0, freertos_risc_v_trap_handler
  48.     jal x0, freertos_risc_v_trap_handler
  49.     jal x0, freertos_risc_v_trap_handler
  50.     jal x0, freertos_risc_v_trap_handler
  51.     jal x0, freertos_risc_v_trap_handler
  52.     jal x0, freertos_risc_v_trap_handler
  53.     jal x0, freertos_risc_v_trap_handler
  54.     jal x0, freertos_risc_v_trap_handler
  55.     jal x0, freertos_risc_v_trap_handler
  56.     jal x0, freertos_risc_v_trap_handler
  57.     jal x0, freertos_risc_v_trap_handler
  58.     jal x0, freertos_risc_v_trap_handler
  59.     jal x0, freertos_risc_v_trap_handler
  60.     jal x0, freertos_risc_v_trap_handler

  61.     // reset vector
  62.     jal x0, Reset_Handler

  63.     // Illegal instrution exception
  64.     jal x0, IllegalInstruction_Handler

  65.     // ecall handler
  66.     jal x0, freertos_risc_v_trap_handler

  67.     // LSU error
  68.     jal x0, LSU_Handler

  69.     .section .startup

  70. /* Reset Handler */
  71. Reset_Handler:

  72.     # Disable global interrupt. */
  73.     csrci mstatus, 8

  74.     # initialize stack pointer
  75.     la sp, __StackTop

  76.     # initialize global pointer
  77.     la gp, __global_pointer

  78. #ifndef __NO_SYSTEM_INIT
  79.     jal SystemInit
  80. #endif

  81.     call __libc_init_array

  82.     # Enable global interrupt. */
  83.     csrsi mstatus, 8

  84.     jal main
  85.     ebreak

  86.     .size Reset_Handler, . - Reset_Handler

  87.     .global _init
  88.     .global _fini
  89. _init:
  90. _fini:
  91.     ret

  92.   // saves all caller-saved registers (except return address)
  93. store_regs:
  94.     sw  x3, 0x00(x2)  // gp
  95.     sw  x4, 0x04(x2)  // tp
  96.     sw  x5, 0x08(x2)  // t0
  97.     sw  x6, 0x0c(x2)  // t1
  98.     sw  x7, 0x10(x2)  // t2
  99.     sw x10, 0x14(x2)  // a0
  100.     sw x11, 0x18(x2)  // a1
  101.     sw x12, 0x1c(x2)  // a2
  102.     sw x13, 0x20(x2)  // a3
  103.     sw x14, 0x24(x2)  // a4
  104.     sw x15, 0x28(x2)  // a5
  105.     sw x16, 0x2c(x2)  // a6
  106.     sw x17, 0x30(x2)  // a7

  107.     csrr a0, 0x7B0
  108.     csrr a1, 0x7B1
  109.     csrr a2, 0x7B2
  110.     sw a0, 0x34(x2)  // lpstart[0]
  111.     sw a1, 0x38(x2)  // lpend[0]
  112.     sw a2, 0x3c(x2)  // lpcount[0]
  113.     csrr a0, 0x7B4
  114.     csrr a1, 0x7B5
  115.     csrr a2, 0x7B6
  116.     sw a0, 0x40(x2)  // lpstart[1]
  117.     sw a1, 0x44(x2)  // lpend[1]
  118.     sw a2, 0x48(x2)  // lpcount[1]

  119.     csrr a0, 0x341
  120.     sw a0, 0x4c(x2)  // mepc
  121.     csrr a1, 0x300
  122.     sw a1, 0x50(x2)  // mstatus
  123.     jalr x0, x1

  124.     // load back registers from stack
  125. end_except:
  126.     lw a1, 0x50(x2)  // mstatus
  127.     csrrw x0, 0x300, a1
  128.     lw a0, 0x4c(x2)  // mepc
  129.     csrrw x0, 0x341, a0

  130.     lw a0, 0x40(x2)  // lpstart[1]
  131.     lw a1, 0x44(x2)  // lpend[1]
  132.     lw a2, 0x48(x2)  // lpcount[1]
  133.     csrrw x0, 0x7B4, a0
  134.     csrrw x0, 0x7B5, a1
  135.     csrrw x0, 0x7B6, a2
  136.     lw a0, 0x34(x2)  // lpstart[0]
  137.     lw a1, 0x38(x2)  // lpend[0]
  138.     lw a2, 0x3c(x2)  // lpcount[0]
  139.     csrrw x0, 0x7B0, a0
  140.     csrrw x0, 0x7B1, a1
  141.     csrrw x0, 0x7B2, a2

  142.     lw  x3, 0x00(x2)  // gp
  143.     lw  x4, 0x04(x2)  // tp
  144.     lw  x5, 0x08(x2)  // t0
  145.     lw  x6, 0x0c(x2)  // t1
  146.     lw  x7, 0x10(x2)  // t2
  147.     lw x10, 0x14(x2)  // a0
  148.     lw x11, 0x18(x2)  // a1
  149.     lw x12, 0x1c(x2)  // a2
  150.     lw x13, 0x20(x2)  // a3
  151.     lw x14, 0x24(x2)  // a4
  152.     lw x15, 0x28(x2)  // a5
  153.     lw x16, 0x2c(x2)  // a6
  154.     lw x17, 0x30(x2)  // a7

  155.     lw  x1, 0x54(x2)
  156.     addi x2, x2, EXCEPTION_STACK_SIZE
  157.     mret

  158.     .weak IRQ_Handler
  159.     .type IRQ_Handler, %function
  160. IRQ_Handler:
  161.     addi x2, x2, -EXCEPTION_STACK_SIZE
  162.     sw x1, 0x54(x2)
  163.     jal x1, store_regs
  164.     la x1, end_except
  165.     csrr a0, mcause
  166.     jal x0, SystemIrqHandler
  167.     .size IRQ_Handler, . - IRQ_Handler

  168.     .macro define_exception_entry entry_name handler_name
  169.     .weak \entry_name
  170. \entry_name:
  171.     addi x2, x2, -EXCEPTION_STACK_SIZE
  172.     sw x1, 0x54(x2)
  173.     jal x1, store_regs
  174.     la x1, end_except
  175.     jal x0, \handler_name
  176.     .endm

  177. define_exception_entry IllegalInstruction_Handler IllegalInstruction_HandlerFunc
  178. define_exception_entry Ecall_Handler Ecall_HandlerFunc
  179. define_exception_entry LSU_Handler LSU_HandlerFunc

  180.     .weak IllegalInstruction_HandlerFunc
  181.     .type IllegalInstruction_HandlerFunc, %function
  182. IllegalInstruction_HandlerFunc:
  183.     j .
  184.     .size IllegalInstruction_HandlerFunc, . - IllegalInstruction_HandlerFunc

  185.     .weak Ecall_HandlerFunc
  186.     .type Ecall_HandlerFunc, %function
  187. Ecall_HandlerFunc:
  188.     j .
  189.     .size Ecall_HandlerFunc, . - Ecall_HandlerFunc

  190.     .weak LSU_HandlerFunc
  191.     .type LSU_HandlerFunc, %function
  192. LSU_HandlerFunc:
  193.     j .
  194.     .size LSU_HandlerFunc, . - LSU_HandlerFunc
复制代码

8.    在链接器文件中,添加一个符号以标记IRQ堆栈的结尾:

  1. __freertos_irq_stack_top = .;
复制代码

freertos_irq_stack_top.png

__freertos_irq_stack_top


9.  通过以上设置,我就可以在VEGA开发板上使用FreeRTOS和RISC-V。


演示应用程序

我已经在GitHub上添加了一个简单的“blinky”应用程序,代码如下:

  1. /*
  2. * Application.c
  3. *
  4.   *      Author: Erich Styger
  5. */
  6. #include "Application.h"
  7. #include "McuLib.h"
  8. #include "McuWait.h"
  9. #include "McuLED1.h"
  10. #include "McuLED2.h"
  11. #include "McuLED3.h"
  12. #include "McuLED4.h"
  13. #include "McuRTOS.h"
  14. #include "FreeRTOS.h"
  15. #include "task.h"

  16. static void AppTask(void *pv) {
  17.   for(;;) {
  18.     McuLED1_On();
  19.     vTaskDelay(pdMS_TO_TICKS(100));
  20.     McuLED1_Off();
  21.     McuLED2_On();
  22.     vTaskDelay(pdMS_TO_TICKS(100));
  23.     McuLED2_Off();
  24.     McuLED3_On();
  25.     vTaskDelay(pdMS_TO_TICKS(100));
  26.     McuLED3_Off();
  27.     McuLED4_On();
  28.     vTaskDelay(pdMS_TO_TICKS(100));
  29.     McuLED4_Off();
  30.     vTaskDelay(pdMS_TO_TICKS(500));
  31.     McuLED4_Neg();
  32.   }
  33. }

  34. void APP_Run(void) {
  35.   /* initialize McuLib drivers */
  36.   McuLib_Init();
  37.   McuRTOS_Init();
  38.   McuWait_Init();
  39.   McuLED1_Init(); /* red */
  40.   McuLED2_Init(); /* green */
  41.   McuLED3_Init(); /* blue */
  42.   McuLED4_Init(); /* red status */

  43.   if (xTaskCreate(AppTask, "App", 500/sizeof(StackType_t), NULL, tskIDLE_PRIORITY+1, NULL) != pdPASS) {
  44.     for(;;){} /* error */
  45.   }
  46.   vTaskStartScheduler();
  47.   /* shoul not end up here... */
  48.   for(;;) { }
  49. }
复制代码

以下是使用NXP MCUXpresso IDE 10.3.1在VEGA开发板上调试应用程序的屏幕截图:

debugging-risc-v-freertos-applicaiton-with-mcuxpresso-ide-on.png

使用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:

  1. #define TIMER_LEGACY_API   (1)  /* << EST: needed to have TAD working */
复制代码

●    OpenOCD不再能提供适当的FreeRTOS线程感知。如果尝试使用FreeRTOS感知,我只会收到一条错误消息:

  1. Error: Could not find target in FreeRTOS compatibility list
复制代码

总结

我现在可以使用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

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 44 | 回复: 61



手机版|

GMT+8, 2019-11-14 07:29 , Processed in 0.031249 second(s), 31 queries . Powered by Discuz! X3.4

YiBoard一板网 © 2015-2018 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表