查看: 783|回复: 2

【瑞萨RA4系列开发板体验】KEIL环境搭建+STLINK调试+FreeRTOS...

[复制链接]

116

主题

134

帖子

3778

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3778
发表于 2023-2-8 14:38:02 | 显示全部楼层 |阅读模式
【瑞萨RA4系列开发板体验】KEIL环境搭建+STLINK调试+FreeRTOS使用
作者hehung

下面是之前发的帖子,请参考:
【瑞萨RA4系列开发板体验】新建工程+按键控制LED

前言
上一篇帖子讲解了如何基于e2从头创建一个新的工程,但是因为没有JLINK,下载软件很麻烦,而且也不能在线DEBUG,所以想着在MDK上搭建环境,因为MDK上支持多种调试器,可以利用手头的ST-LINK来作为调试器下载与debug。
本文实现主要内容:
  • MDK环境搭建以及ST-LINK调试配置;
  • 使用freeRTOS实现按键以及LED功能。


MDK环境搭建
MDK的环境搭建还是比较简单,官网给了教程,点击下载:
[color=rgb(12, 147, 228) !important]https://sq.ramcu.cn/forum.php?mod=attachment&aid=Njg3fGZlNmU0OGQwfDE2Njk1MzIwNDF8NDcyfDE4Mw%3D%3D
MDK也需要RASC配置工具的支持,所以也需要下载配置工具,可以到瑞萨的官网下载,提供了百度云,也可以到github下载,但是比较慢。
瑞萨工具下载(官网):[color=rgb(12, 147, 228) !important]https://ramcu.cn/lists/21.html[url]https://ramcu.cn/lists/21.html[/url]

百度云:[color=rgb(12, 147, 228) !important]https://pan.baidu.com/s/1h-qcTIGobEBK88NgHODUhg?pwd=odqe#list/path=%2F
环境搭建过程不在赘述,参考文档即可,我这里主要说一下基于RA4M2搭建以及使用ST-LINK调试时需要注意的事项。
  • 根据手头的调试器选择自己的调试工具,我手头的是ST-LINK



2.加载下载算法文件以及算法存放在RAM中的地址

算法下载地址是根据RA4M2的地址分布来确定的,算法需要下载到RAM中, 需要的大小可以自己确定,这里选择0x1000,如果不够的话下载不成功。


FreeRTOS使用
我在创建工程的时候选择了使用FreeRTOS,RASC会默认配置一个最小配置项的freeRTOS环境,只支持基本的功能,很多扩展功能都不支持,只支持静态创建任务,我还没找到在哪里可以配置,因为直接修改配置文件不行,RASC再次生成的时候会覆盖。
虽然freeRTOS只支持静态配置以及一些基础功能,但是也够我们使用了,下面开始实现我的逻辑。
  • 实现Idle任务的Stack分配函数
因为是静态分配栈,所以该部分功能需要我们自己实现,FreeRTOS提供了接口。

  1. /* Implement the Idle task memory static alocation */
  2. void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
  3.                                    StackType_t ** ppxIdleTaskStackBuffer,
  4.                                    uint32_t * pulIdleTaskStackSize)
  5. {
  6.     *ppxIdleTaskTCBBuffer = &xIdleTaskTcb;
  7.     *ppxIdleTaskStackBuffer = xIdleTaskStack;
  8.     *pulIdleTaskStackSize = 1024;
  9. }
复制代码
  • 实现Timer任务的Stack分配函数
因为是静态分配栈,所以该部分功能需要我们自己实现,FreeRTOS提供了接口。

  1. /* Implement the Timer task memory static alocation */
  2. void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
  3.                                     StackType_t **ppxTimerTaskStackBuffer,
  4.                                     uint32_t *pulTimerTaskStackSize)
  5. {
  6.         *ppxTimerTaskTCBBuffer = &xTimerTaskTcb;
  7.         *ppxTimerTaskStackBuffer = xTiemrTaskStack;
  8.         *pulTimerTaskStackSize = 2048;
  9. }
复制代码
  • 新建LED任务
    LED任务实现流水灯功能,每200ms切换一次。
    任务创建:

  1. /* Create static task */
  2.     Task_Led_Handle = xTaskCreateStatic(Task_LedRunning,
  3.                         "Led",          /* Task name */
  4.                         1024,              /* Stack */
  5.                         NULL,              /* Task parameter */
  6.                         4,                 /* Priority */
  7.                         xTaskLedStack,
  8.                         &xTaskLedTcb);            /* Task handler */
复制代码
LED任务实现:
  1. static void Task_LedRunning(void *pvParameters)
  2. {
  3.     (void)pvParameters;
  4.        
  5.     for (;;)
  6.     {
  7.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_HIGH);
  8.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_LOW);
  9.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_LOW);

  10.         /* Delay for 200ms */
  11.         vTaskDelay(pdMS_TO_TICKS(200));

  12.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW);
  13.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_HIGH);
  14.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_LOW);

  15.         /* Delay for 200ms */
  16.         vTaskDelay(pdMS_TO_TICKS(200));

  17.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW);
  18.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_LOW);
  19.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_HIGH);

  20.         /* Delay for 200ms */
  21.         vTaskDelay(pdMS_TO_TICKS(200));
  22.     }
  23. }
复制代码
  • 新建Key任务
    按键实现了对按键SW1与SW2的采集,滤波等功能,任务周期为10ms,滤波时间为40ms。
    当SW1按下,暂停LED任务;
    当SW2按下,恢复LED任务。
    任务创建:

  1. Task_Key_Handle = xTaskCreateStatic(Task_KeyRunning,
  2.                                                 "Key",          /* Task name */
  3.                                                 1024,              /* Stack */
  4.                                                 NULL,              /* Task parameter */
  5.                                                 3,                 /* Priority */
  6.                                                 xTaskKeyStack,
  7.                                                 &xTaskKeyTcb);            /* Task handler */
复制代码
任务实现:
  1. static void Task_KeyRunning(void *pvParameters)
  2. {
  3.     (void)pvParameters;
  4.         bsp_io_level_t key_Status[2] = {BSP_IO_LEVEL_HIGH, BSP_IO_LEVEL_HIGH};
  5.         uint16_t key_press_cnt[2] = {0U, 0U};
  6.        
  7.         for (;;)
  8.         {
  9.         if (FSP_SUCCESS == R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_05, &key_Status[0]))
  10.         {
  11.             if (key_Status[0] == BSP_IO_LEVEL_LOW)
  12.             {
  13.                                 /* Filter */
  14.                                 if (key_press_cnt[0] >= 0U)
  15.                                 {
  16.                                         /* Key SW0 press confirm */
  17.                                         /* Suspend led task */
  18.                                         vTaskSuspend(Task_Led_Handle);
  19.                                 }
  20.                                 else
  21.                                 {
  22.                                         key_press_cnt[0] ++;
  23.                                 }
  24.             }
  25.                         else
  26.                         {
  27.                                 key_press_cnt[0] = 0U;
  28.                         }
  29.         }
  30.                
  31.                 if (FSP_SUCCESS == R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06, &key_Status[1]))
  32.         {
  33.             if (key_Status[1] == BSP_IO_LEVEL_LOW)
  34.             {
  35.                                 /* Filter */
  36.                                 if (key_press_cnt[1] >= 4U)
  37.                                 {
  38.                                         /* Key SW1 press confirm */
  39.                                         /* Resume led task */
  40.                                         vTaskResume(Task_Led_Handle);
  41.                                 }
  42.                                 else
  43.                                 {
  44.                                         key_press_cnt[1] ++;
  45.                                 }
  46.             }
  47.                         else
  48.                         {
  49.                                 key_press_cnt[1] = 0U;
  50.                         }
  51.         }

  52.                 vTaskDelay(pdMS_TO_TICKS(10));               
  53.         }
  54. }
复制代码


完整代码
  1. #include "hal_data.h"
  2. #include "FreeRTOS.h"
  3. #include "task.h"

  4. FSP_CPP_HEADER
  5. void R_BSP_WarmStart(bsp_warm_start_event_t event);
  6. FSP_CPP_FOOTER


  7. /* Stack for Idle task */
  8. static StackType_t xIdleTaskStack[512];
  9. static StaticTask_t xIdleTaskTcb;
  10. /* Stack for Timer task */
  11. static StackType_t xTiemrTaskStack[512];
  12. static StaticTask_t xTimerTaskTcb;

  13. /* Staack for LED task */
  14. static StackType_t xTaskLedStack[1024];
  15. static StaticTask_t xTaskLedTcb;
  16. static TaskHandle_t Task_Led_Handle = NULL;

  17. /* Staack for LED task */
  18. static StackType_t xTaskKeyStack[1024];
  19. static StaticTask_t xTaskKeyTcb;
  20. static TaskHandle_t Task_Key_Handle = NULL;

  21. extern void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
  22.                                           StackType_t ** ppxIdleTaskStackBuffer,
  23.                                           uint32_t * pulIdleTaskStackSize);
  24. extern void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
  25.                                           StackType_t **ppxTimerTaskStackBuffer,
  26.                                           uint32_t *pulTimerTaskStackSize);

  27. static void Task_LedRunning(void *pvParameters);
  28. static void Task_KeyRunning(void *pvParameters);

  29. static void Task_LedRunning(void *pvParameters)
  30. {
  31.     (void)pvParameters;
  32.        
  33.     for (;;)
  34.     {
  35.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_HIGH);
  36.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_LOW);
  37.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_LOW);

  38.         /* Delay for 200ms */
  39.         vTaskDelay(pdMS_TO_TICKS(200));

  40.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW);
  41.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_HIGH);
  42.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_LOW);

  43.         /* Delay for 200ms */
  44.         vTaskDelay(pdMS_TO_TICKS(200));

  45.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW);
  46.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_LOW);
  47.         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_HIGH);

  48.         /* Delay for 200ms */
  49.         vTaskDelay(pdMS_TO_TICKS(200));
  50.     }
  51. }

  52. static void Task_KeyRunning(void *pvParameters)
  53. {
  54.     (void)pvParameters;
  55.         bsp_io_level_t key_Status[2] = {BSP_IO_LEVEL_HIGH, BSP_IO_LEVEL_HIGH};
  56.         uint16_t key_press_cnt[2] = {0U, 0U};
  57.        
  58.         for (;;)
  59.         {
  60.         if (FSP_SUCCESS == R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_05, &key_Status[0]))
  61.         {
  62.             if (key_Status[0] == BSP_IO_LEVEL_LOW)
  63.             {
  64.                                 /* Filter */
  65.                                 if (key_press_cnt[0] >= 0U)
  66.                                 {
  67.                                         /* Key SW0 press confirm */
  68.                                         /* Suspend led task */
  69.                                         vTaskSuspend(Task_Led_Handle);
  70.                                 }
  71.                                 else
  72.                                 {
  73.                                         key_press_cnt[0] ++;
  74.                                 }
  75.             }
  76.                         else
  77.                         {
  78.                                 key_press_cnt[0] = 0U;
  79.                         }
  80.         }
  81.                
  82.                 if (FSP_SUCCESS == R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06, &key_Status[1]))
  83.         {
  84.             if (key_Status[1] == BSP_IO_LEVEL_LOW)
  85.             {
  86.                                 /* Filter */
  87.                                 if (key_press_cnt[1] >= 4U)
  88.                                 {
  89.                                         /* Key SW1 press confirm */
  90.                                         /* Resume led task */
  91.                                         vTaskResume(Task_Led_Handle);
  92.                                 }
  93.                                 else
  94.                                 {
  95.                                         key_press_cnt[1] ++;
  96.                                 }
  97.             }
  98.                         else
  99.                         {
  100.                                 key_press_cnt[1] = 0U;
  101.                         }
  102.         }

  103.                 vTaskDelay(pdMS_TO_TICKS(10));               
  104.         }
  105. }

  106. /* Implement the Idle task memory static alocation */
  107. void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
  108.                                    StackType_t ** ppxIdleTaskStackBuffer,
  109.                                    uint32_t * pulIdleTaskStackSize)
  110. {
  111.     *ppxIdleTaskTCBBuffer = &xIdleTaskTcb;
  112.     *ppxIdleTaskStackBuffer = xIdleTaskStack;
  113.     *pulIdleTaskStackSize = 1024;
  114. }

  115. /* Implement the Timer task memory static alocation */
  116. void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
  117.                                     StackType_t **ppxTimerTaskStackBuffer,
  118.                                     uint32_t *pulTimerTaskStackSize)
  119. {
  120.         *ppxTimerTaskTCBBuffer = &xTimerTaskTcb;
  121.         *ppxTimerTaskStackBuffer = xTiemrTaskStack;
  122.         *pulTimerTaskStackSize = 2048;
  123. }

  124. /*******************************************************************************************************************//**
  125. * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
  126. * is called by main() when no RTOS is used.
  127. **********************************************************************************************************************/
  128. void hal_entry(void)
  129. {
  130.         /* Create static task */
  131.     Task_Led_Handle = xTaskCreateStatic(Task_LedRunning,
  132.                         "Led",          /* Task name */
  133.                         1024,              /* Stack */
  134.                         NULL,              /* Task parameter */
  135.                         4,                 /* Priority */
  136.                         xTaskLedStack,
  137.                         &xTaskLedTcb);            /* Task handler */
  138.        
  139.         Task_Key_Handle = xTaskCreateStatic(Task_KeyRunning,
  140.                                                 "Key",          /* Task name */
  141.                                                 1024,              /* Stack */
  142.                                                 NULL,              /* Task parameter */
  143.                                                 3,                 /* Priority */
  144.                                                 xTaskKeyStack,
  145.                                                 &xTaskKeyTcb);            /* Task handler */

  146.     if (NULL != Task_Led_Handle)
  147.         {
  148.             vTaskStartScheduler();
  149.         }

  150.         while (1) {}

  151. #if BSP_TZ_SECURE_BUILD
  152.     /* Enter non-secure code */
  153.     R_BSP_NonSecureEnter();
  154. #endif
  155. }

  156. /*******************************************************************************************************************//**
  157. * This function is called at various points during the startup process.  This implementation uses the event that is
  158. * called right before main() to set up the pins.
  159. *
  160. * @param[in]  event    Where at in the start up process the code is currently at
  161. **********************************************************************************************************************/
  162. void R_BSP_WarmStart(bsp_warm_start_event_t event)
  163. {
  164.     if (BSP_WARM_START_RESET == event)
  165.     {
  166. #if BSP_FEATURE_FLASH_LP_VERSION != 0

  167.         /* Enable reading from data flash. */
  168.         R_FACI_LP->DFLCTL = 1U;

  169.         /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
  170.          * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
  171. #endif
  172.     }

  173.     if (BSP_WARM_START_POST_C == event)
  174.     {
  175.         /* C runtime environment and system clocks are setup. */

  176.         /* Configure pins. */
  177.         R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
  178.     }
  179. }

  180. #if BSP_TZ_SECURE_BUILD

  181. BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();

  182. /* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
  183. BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
  184. {

  185. }
  186. #endif
复制代码


回复

使用道具 举报

1

主题

9

帖子

1323

积分

金牌会员

Rank: 6Rank: 6

积分
1323
发表于 2023-2-18 22:03:01 | 显示全部楼层

为什么我的STLink不可以调试呢,DAPlink到是可以
回复

使用道具 举报

3

主题

195

帖子

1510

积分

金牌会员

Rank: 6Rank: 6

积分
1510
发表于 2023-3-14 10:23:01 | 显示全部楼层

盗版的jlink不能调试的?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

用户排行榜

RA助手

主题: 116帖子:134精华:0

RA_Lance

主题: 92帖子:132精华:9

lugl

主题: 44帖子:133精华:0

xujiwei263

主题: 16帖子:73精华:0

books咦

主题: 11帖子:11精华:2

Juggernaut

主题: 9帖子:95精华:0
快速回复 返回顶部 返回列表