如何 运行 TM4C129EXL 上的 FreeRTOS?

How to run FreeRTOS on TM4C129EXL?

我正在为大学开发一个 C 项目,其中 CoAP 服务器将托管在 TM4C129EXL 上。选择一款FreeRTOS操作系统尤为重要。不幸的是,我不得不得知 Texas Instruments 已经停止支持 FreeRTOS。我没有切换到另一个操作系统的选项。正是出于这个原因,我求助于您。

我正在寻找一个在 TM4C129EXL 板上执行 Free RTOS 的示例程序。在最好的情况下,我会很高兴有一个 Code Composer Studio 项目,因为这是我们在大学合作的 IDE。

如果您没有任何示例代码,我很乐意收到有关 FreeRTOS 和 CoAP 的任何其他信息,当然是参考 TM4C129EXL。

您没有说明您是否对 FreeRTOS 版本有任何要求,但您可以:

  • 按原样使用文件 SW-EK-TM4C1294XL-2.1.4.178.exe 中提供的演示,该演示可在 TI WEB 网站上获得 - 您可以在目录 examples\boards\ek-tm4c1294xl-boostxl-senshub\senshub_iot
  • 中找到它
  • 以这个例子为基础来使用更新版本的 FreeRTOS:你只需要用最新的替换 FreeRTOS 源代码,并且可能修改演示中的一些代码:一些函数 names/signatures 可能在主要版本之间发生了变化。

下面的过程逐步描述了如何使用第二种方法在 Windows10 环境中使用 Code Composer Studio 10.3.0 和 FreeRTOS v202104.00 创建极简 FreeRTOS 程序。您可能需要根据您的特定设置调整驱动器号,我使用的是 D:出于本示例的目的..

  • 下载Code Composer Studio 10.3.0, FreeRTOS v202104.00 and SW-EK-TM4C1294XL-2.1.4.178.exe.

  • 安装支持 Tiva-C MCU 系列的 Code Composer Studio。当提示输入工作区名称时,指定 D:\ti\workspace_v10.

  • 解压FreeRTOSv202104.00.zip进入D:\.

  • SW-EK-TM4C1294XL-2.1.4.178.exe解压缩到D:\SW-EK-TM4C1294XL-2.1.4.178

  • 启动 CCS

  • 使用菜单项 File/New/CCS Project,并创建一个“空项目(使用 main.c)。

[]

  • 单击 Finish 按钮。
  • 创建以下目录:
    D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\driverlib
    D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\inc
    D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel
    D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\include
    D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\portable\GCC
    D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\portable\GCC\ARM_CM4F
    D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\portable\MemMang
  • 复制D:\SW-EK-TM4C1294XL-2.1.4.178\examples\boards\ek-tm4c1294xl-boostxl-senshub\senshub_iot\FreeRTOSConfig.hD:\ti\workspace_v10\TM4C129EXL-FreeRTOS
  • 将所有 .h 个文件从 D:\SW-EK-TM4C1294XL-2.1.4.178\driverlib 复制到 D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\driverlib
  • D:\SW-EK-TM4C1294XL-2.1.4.178\driverlib\gcc\libdriver.a复制到D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\driverlib
  • D:\SW-EK-TM4C1294XL-2.1.4.178\inc 中的所有 .h 文件复制到 D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\inc
  • D:\FreeRTOSv202104.00\FreeRTOS\Source\include 中的所有文件复制到 D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\include
  • D:\FreeRTOSv202104.00\FreeRTOS\Source 中存在的所有 .c 文件复制到 D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel
  • D:\FreeRTOSv202104.00\FreeRTOS\Source\portable\GCC\ARM_CM4F 中的所有文件复制到 D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\portable\GCC\ARM_CM4F
  • D:\FreeRTOSv202104.00\FreeRTOS\Source\portable\MemMang\heap_4.c复制到D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOS-Kernel\portable\MemMang
  • 编辑 D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\main.c,并将其内容替换为:
#include "FreeRTOS.h"
#include "task.h"

extern void prvSetupHardware();
extern void main_blinky();

int main(void)
{
    /* Configure the hardware ready to run the demo. */
    prvSetupHardware();

    main_blinky();

    /* Don't expect to reach here. */
    return 0;
}

void vApplicationWhosebugHook( TaskHandle_t xTask, char *pcTaskName)
{
    while(1)
    {
    }
}
  • 创建一个名为 D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\blinky.c 的新文件,内容如下:
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "FreeRTOS.h"
#include "task.h"
#include "sysctl.h"

static void prvLedToggleTask();

/* Priorities at which the tasks are created. */
#define mainTOGGLE_LED_PRIORITY         ( tskIDLE_PRIORITY + 1 )
#define TOGGLE_LED_DELAY_MS             200

void main_blinky()
{
    /* create task */
    xTaskCreate( prvLedToggleTask, "LED", configMINIMAL_STACK_SIZE, NULL, mainTOGGLE_LED_PRIORITY, NULL );

    /* Start the tasks and timer running. */
    vTaskStartScheduler();

}

static void prvLedToggleTask( void *pvParameters )
{
    // Remove compiler warning about unused parameter. */
    ( void ) pvParameters;

    for( ;; )
    {
        //
        // Turn on the LED.
        //
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);

        // Wait a bit
        vTaskDelay( TOGGLE_LED_DELAY_MS);

        //
        // Turn off the LED.
        //
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0x0);

        // Wait a bit
        vTaskDelay( TOGGLE_LED_DELAY_MS );
    }
}

uint32_t g_ui32SysClock;

void prvSetupHardware()
{
    // Configure PLL
    g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                         SYSCTL_OSC_MAIN |
                                         SYSCTL_USE_PLL |
                                         SYSCTL_CFG_VCO_480), 120000000);
    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);

    //
    // Check if the peripheral access is enabled.
    //
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPION))
    {
    }

    //
    // Enable the GPIO pin for the LED (PN0).  Set the direction as output, and
    // enable the GPIO pin for digital function.
    //
    GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);
}
  • 编辑tm4c1294ncpdt_startup_ccs_gcc.c:在包含static void IntDefaultHandler(void);
  • 的行之后添加以下行
extern void xPortPendSVHandler(void);
extern void vPortSVCHandler(void);
extern void xPortSysTickHandler(void);

生成的代码应如下所示:

void ResetISR(void);
static void NmiSR(void);
static void FaultISR(void);
static void IntDefaultHandler(void);

extern void xPortPendSVHandler(void);
extern void vPortSVCHandler(void);
extern void xPortSysTickHandler(void);
  • 编辑 tm4c1294ncpdt_startup_ccs_gcc.c:用数组 g_pfnVectors[] 中的 FreeRTOS 替换默认中断处理程序。
    原码:
  void (* const g_pfnVectors[])(void) =
{
    (void (*)(void))((uint32_t)pui32Stack + sizeof(pui32Stack)),
                                            // The initial stack pointer
    ResetISR,                               // The reset handler
    NmiSR,                                  // The NMI handler
    FaultISR,                               // The hard fault handler
    IntDefaultHandler,                      // The MPU fault handler
    IntDefaultHandler,                      // The bus fault handler
    IntDefaultHandler,                      // The usage fault handler
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // SVCall handler
    IntDefaultHandler,                      // Debug monitor handler
    0,                                      // Reserved
    IntDefaultHandler,                      // The PendSV handler
    IntDefaultHandler,                      // The SysTick handler

结果代码:

void (* const g_pfnVectors[])(void) =
{
    (void (*)(void))((uint32_t)pui32Stack + sizeof(pui32Stack)),
                                            // The initial stack pointer
    ResetISR,                               // The reset handler
    NmiSR,                                  // The NMI handler
    FaultISR,                               // The hard fault handler
    IntDefaultHandler,                      // The MPU fault handler
    IntDefaultHandler,                      // The bus fault handler
    IntDefaultHandler,                      // The usage fault handler
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    vPortSVCHandler,                        // SVCall handler
    IntDefaultHandler,                      // Debug monitor handler
    0,                                      // Reserved
    xPortPendSVHandler,                     // The PendSV handler
    xPortSysTickHandler,                    // The SysTick handler
  • 编辑 GCC 编译器目录的项目属性,并添加以下目录:
    ${workspace_loc:/${ProjName}/FreeRTOS-Kernel/include}
    ${workspace_loc:/${ProjName}/FreeRTOS-Kernel/portable/GCC/ARM_CM4F}
    ${workspace_loc:/${ProjName}
    ${workspace_loc:/${ProjName}/driverlib}
    然后点击 Apply and close 按钮。

  • 编辑 D:\ti\workspace_v10\TM4C129EXL-FreeRTOS\FreeRTOSConfig.h 并删除以下行:
#define configGENERATE_RUN_TIME_STATS       1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()                              \
                                            g_vulRunTimeStatsCountValue = 0ul
#define portGET_RUN_TIME_COUNTER_VALUE()    g_vulRunTimeStatsCountValue
  • 编辑GCC编译器命令行模式,在命令行模式${flags}后添加-mfloat-abi=hard选项:
    ${command} ${flags} -mfloat-abi=hard ${output_flag}${output} ${inputs}

  • 编辑 GNU 链接器命令行模式并在 ${flags} 之后添加 -mfloat-abi=hard 选项:>br/> ${command} ${flags} -mfloat-abi=hard ${output_flag}${output} ${inputs}

  • 编辑GCC链接器库:在-l选项中添加libdriver.a,在-L选项中添加${workspace_loc:/${ProjName}/driverlib},然后点击Apply and close按钮。

  • 构建您的项目 - 构建应该没有任何错误。
  • 通过 运行 刷新您的项目。

在我的例子中,我必须停止项目并按下面板 reset 按钮才能启动程序。

最后,LED 应该开始每 200 毫秒闪烁一次。

一旦项目'cleaned'项目中的完整文件列表最终应该是:

Folder PATH listing for volume DATA
Volume serial number is 0E12-BCA2
D:.
|   .ccsproject
|   .cproject
|   .project
|   blinky.c
|   FreeRTOSConfig.h
|   main.c
|   tm4c1294ncpdt.lds
|   tm4c1294ncpdt_startup_ccs_gcc.c
|   
+---.settings
|       org.eclipse.cdt.codan.core.prefs
|       org.eclipse.cdt.debug.core.prefs
|       org.eclipse.core.resources.prefs
|       
+---Debug
|   |   ccsObjs.opt
|   |   makefile
|   |   objects.mk
|   |   sources.mk
|   |   subdir_rules.mk
|   |   subdir_vars.mk
|   |   TM4C129EXL-FreeRTOS.map
|   |   
|   +---driverlib
|   |       subdir_rules.mk
|   |       subdir_vars.mk
|   |       
|   \---FreeRTOS-Kernel
|       |   subdir_rules.mk
|       |   subdir_vars.mk
|       |   
|       \---portable
|           +---GCC
|           |   \---ARM_CM4F
|           |           subdir_rules.mk
|           |           subdir_vars.mk
|           |           
|           \---MemMang
|                   subdir_rules.mk
|                   subdir_vars.mk
|                   
+---driverlib
|       adc.h
|       aes.h
|       can.h
|       comp.h
|       cpu.h
|       crc.h
|       debug.h
|       des.h
|       eeprom.h
|       emac.h
|       epi.h
|       flash.h
|       fpu.h
|       gpio.h
|       hibernate.h
|       i2c.h
|       interrupt.h
|       lcd.h
|       libdriver.a
|       mpu.h
|       onewire.h
|       pin_map.h
|       pwm.h
|       qei.h
|       rom.h
|       rom_map.h
|       rtos_bindings.h
|       shamd5.h
|       ssi.h
|       sw_crc.h
|       sysctl.h
|       sysexc.h
|       systick.h
|       timer.h
|       uart.h
|       udma.h
|       usb.h
|       watchdog.h
|       
+---FreeRTOS-Kernel
|   |   croutine.c
|   |   event_groups.c
|   |   list.c
|   |   queue.c
|   |   stream_buffer.c
|   |   tasks.c
|   |   timers.c
|   |   
|   +---include
|   |       atomic.h
|   |       croutine.h
|   |       deprecated_definitions.h
|   |       event_groups.h
|   |       FreeRTOS.h
|   |       list.h
|   |       message_buffer.h
|   |       mpu_prototypes.h
|   |       mpu_wrappers.h
|   |       portable.h
|   |       projdefs.h
|   |       queue.h
|   |       semphr.h
|   |       StackMacros.h
|   |       stack_macros.h
|   |       stdint.readme
|   |       stream_buffer.h
|   |       task.h
|   |       timers.h
|   |       
|   \---portable
|       +---GCC
|       |   \---ARM_CM4F
|       |           port.c
|       |           portmacro.h
|       |           
|       \---MemMang
|               heap_4.c
|               
\---inc
        asmdefs.h
        hw_adc.h
        hw_aes.h
        hw_can.h
        hw_ccm.h
        hw_comp.h
        hw_des.h
        hw_eeprom.h
        hw_emac.h
        hw_epi.h
        hw_fan.h
        hw_flash.h
        hw_gpio.h
        hw_hibernate.h
        hw_i2c.h
        hw_ints.h
        hw_lcd.h
        hw_memmap.h
        hw_nvic.h
        hw_onewire.h
        hw_pwm.h
        hw_qei.h
        hw_shamd5.h
        hw_ssi.h
        hw_sysctl.h
        hw_sysexc.h
        hw_timer.h
        hw_types.h
        hw_uart.h
        hw_udma.h
        hw_usb.h
        hw_watchdog.h
        tm4c1294ncpdt.h