续前【RA4E2开发板评测】1、开发板开箱与环境搭建,rfp-cli.exe命令行烧录
背景:大多数操作系统似乎能同时执行多个程序。这称为多任务处理。随着应用程序变得越来越复杂,[单片机]裸机开发已经无法满足对于复杂程序的需求。于是具有多任务调度和实时响应特性的FreeRTOS便越来越受工程师们青睐。
FreeRTOS 由美国的 Richard Barry 于 2003 年发布,Richard Barry 是 FreeRTOS 的拥有者和维护者,在过去的十多年中 FreeRTOS 历经了 9 个版本,与众多半导体厂商合作密切,累计开发者数百万,是目前市场占有率最高的 RTOS。
[瑞萨]RA系列[MCU]兼容[FreeRTOS]系统,开发环境rasc完美支持FreeRTOS可简化工程配置,无需手动移植[FreeRTOS]系统。开发者只需要考虑进程和资源,相当容易使用。
以下介绍如何用瑞萨rasc创建RA4E2开发板的FreeRTOS工程。
作者加入了[亚马逊],之后推出的产品为Amazon FreeRTOS
本次实验要使用FreeRTOS11.1.0嵌入式实时操作系统,之前实验都是在裸机上跑的,但当我们要多线程操作时并简化开发时,就需要用到RTOS(Real-Time Operating System)。
通常我们裸机开发要做软件延时用的是FSP库R_BSP_SoftwareDelay函数,它是阻塞式运行的。而在FreeRTOS实时操作系统开发里面使用到vTaskDelay函数,它是对CPU的时分复用,系统将这个任务挂起,让CPU去执行其他任务,一旦时间到了,就再回到先前的任务继续执行。
在win10系统renesas瑞萨RA系列MCU提供了e2 studio**** 开发环境和为Keil ** 、iar、Cmake 提供的初始化代码生成器
此项目使用RA Smart Configurator+Keil +rfp-cli.exe命令行烧录
RA Smart Configurator软件可以在瑞萨官网进行下载,下载地址:https://www.renesas.cn| setup_fsp_v5_9_0_rasc_v2025-05.exe安装完成后在RenesasRAsc_v eclipse目录中运行rasc.exe
rasc部分
配置keil项目





已经产生文件目录: 
- 根据下图修改pin 增加引脚:和时钟,
- 复位按键与自定义按键**![按键]

LED电路**![LED]
加入3个005 , 113,207:

根据下图时钟不变:
时钟电路**![时钟]
![未标题-2 拷贝.png]
根据板自己带USB-com接口:

配置g_uart0
在Stacks项中 点击Stacks->New Stack->Connectivity -> UART (r_sci_uart)。
r_sci_uart配置如下;
channel 填9
callback 填 user_uart_callback
优先级2

点pins开点任何引脚行后的导向按钮到pins
operation Mode 选择Asynchonous.

准备使用keil中用microlib中printf,在bsp中设置heap为0x2000

在Stacks项中 点击Stacks->New Stack->Analog-> ADC(r_adc)。
选择0通道。
callback 填 adc_callback
优先级3中断回调
点pins开点任何引脚行后的导向按钮到pins
operation Mode 选择custom.
选择p0引脚。
FreeRTOS 部分配置
准备使用按键任务,ADC任务和printf输出任务
点击Stacks选项卡--在左侧的New Thread -- 点击新创建的Thread 属性 -- 修改Name、Symbol以及Priority等,按键切换任务的symbol是Key_Switch_Task,Name是KeySwitch,Stack Size为256,优先级2,内存分配为Dynamic。展开内存分配可以
修改 Support Dynamic Allocation 为 Enabled
修改Total Heap Size堆大小 为12720

在线程配置上方是FreeRTOS 配置,有设置自定义的FreeRTOSConfig.h文件路径等等,暂时采用默认。
内存管理算法选择 :接着为堆选择算法,这里一共有1~5共5个算法可选,每种算法介绍如下:Heap_1:这是最简单的内存分配实现,它不允许释放已分配的内存。这意味着一旦内存被分配出去,就不能被回收,这可能导致内存的快速耗尽。Heap_2:与Heap_1相比,Heap_2允许内存的释放。但是,它不会合并相邻的空闲内存块,因此可能会导致内存碎片化。Heap_3:Heap_3使用标准的malloc()和free()函数来管理内存,因此堆的大小由链接器配置决定,而不是由FreeRTOS的配置文件设置。Heap_4:Heap_4在Heap_2的基础上进行了改进,它会合并相邻的空闲内存块,从而减少内存碎片化的可能性。Heap_4使用“第一次适应算法”来分配内存,通常建议作为内存管理的首选方案。Heap_5:Heap_5与Heap_4类似,但它支持从多个非连续的内存块中分配内存,这对于系统内存不是连续块的情况非常有用。`这里我选择Heap 4算法。
点击KeySwitch -- New Stack -- RTOS -- FreeRTOS Heap4
ADC任务的symbol是ADC_Task,Name是ADC_Voltage,优先级2,Stack Size为1024,内存分配为Dynamic.
printf输出任务的symbol是printf_Task,Name是printF,优先级1,Stack Size为1024,内存分配为Dynamic`.
任务间通信机制创建 :创建队列信号量,二值信号量用于任务同步。
在之前的裸机开发中,都是使用extern一个全局变量来传递数据的,例如,一个模块采集数据后,将结果存入某个全局变量,其他模块通过 extern 声明访问这个变量。这种方式虽然简单直接,但存在一些问题:
- 全局变量数量多,容易混乱,维护困难;
- 没有访问控制,可能被任意地方修改;
- 多个模块同时访问时容易出现竞态条件;
- 不适用于多任务并发的系统。
在FreeRTOS中,队列是一个线程安全的、先进先出(FIFO)缓冲结构,用于任务之间或者任务与中断之间安全传递数据。你可以把它理解为一个 任务之间传纸条的小信箱 ,一方放入数据,另一方接收数据,而且不会因为同时访问而出错。
在Threads下方有一个Object区域,点击New Object-- Queue

创建一个队列,修改symbol为queue_adcValue,由于double类型大小是8字节,Item Size填8,队列长度写3,内存分配选Dynamic。
在Threads下方有一个Object区域,点击New Object-- binary_semaphore
创建一个二值信号量,symbol为semphr_keyChanged,内存分配选Dynamic

完成后点击生成代码即可

rasc部分配置完。
keil编程部分
在已经产生文件目录: 
中打开lu.uvprojx

在lu\src会多出几个*Task_entry.c文件,这些文件是留给我们写线程具体功能的。
**‘在hal_entry.c不需要加入任何代码,所有与os有关代码由[瑞萨]在生成项目时完成了.’ **copy原程序adc和urart等等驱动。编辑各线程程序:在Key_Switch_Task.c中:
#include "Key_Switch_Task.h"
#define KEY1 (BSP_IO_PORT_00_PIN_05)
uint8_t key_driver(void)
{
static uint8_t key_last=0, key_time=2;
uint8_t key_input,key_press,key_return=0;
R_IOPORT_PinRead (&g_ioport_ctrl, KEY1, &key_input);
if(key_input) key_press=0; else key_press=1;
if(key_press!=key_last) {key_last=key_press; key_time=0;}
if(key_time==1) key_return=(key_press==1)?11:1;
if(key_time==50 && key_press==1) key_return=3;
if(++key_time>60) key_time=55;
return key_return;
}
unsigned char key_read(void)
{
static unsigned char key_last =0, key_time_1 = 0;
unsigned char key_return =0,key_temp;
key_temp = key_driver();
if(key_time_1==0)
{
if(key_temp==1&&key_last==11) key_time_1++;
}
else if(++key_time_1<12)
{
if(key_temp==11) {key_return=2; key_temp=key_time_1=0;}
}
else
{
key_return=1;
key_time_1=0;
}
if(key_temp==3&&key_last==11) key_return=3;
if(key_temp) key_last=key_temp;
return key_return;
}
void Key_Switch_Task_entry(void *pvParameters)
{
FSP_PARAMETER_NOT_USED(pvParameters);
uint8_t key_state;
while (1)
{
key_state=key_read();
switch (key_state)
{
case 0:
break;
case 1:
printf("S_key 1 \r\n");
xSemaphoreGive(semphr_keyChanged);
break;
case 2:
break;
case 3: printf("l_key 3 \r\n");
break;
}
vTaskDelay (30);
}
}
在printf_Task_Task.c中:
#include "printf_Task.h"
#include "uart/uart.h"
volatile bool scan_0_3V3_flag= false;
extern volatile bool TBE ;
void printf_Task_entry(void * pvParameters)
{
FSP_PARAMETER_NOT_USED(pvParameters);
uint8_t buffer[7];
uint8_t * bufferQ=buffer;
uint32_t num = 0;
uint32_t adcValue = 0;
static bool adc_task_active = true;
bool display_flag;
uart_initialize();
int i=0;
while(true)
{
i++;
if (xSemaphoreTake(semphr_keyChanged, 0) == pdTRUE)
{
scan_0_3V3_flag=!scan_0_3V3_flag;
}
vTaskDelay(10);
if(i==100){
printf("Hello World!\r\n");
i=0;
}
if (xQueueReceive (queue_adcValue, &num, 0) == pdTRUE )
{
printf("ADC:%d\r\n", num);
buffer[3]=(uint8_t *)(num>8);
buffer[4]=(uint8_t *)(num&0xff);
buffer[0]=0xff;
buffer[1]=0xfe;
buffer[2]=0x01;
buffer[5]=0x0;
TBE = false;
R_SCI_UART_Write(&g_uart0_ctrl, bufferQ, 6);
while(TBE == false);
TBE = false;
}
}
}
在ADC_Task_Task.c中:
#include "ADC_Task.h"
#include "adc/adc.h"
extern volatile bool scan_0_3V3_flag;
extern uint16_t adc_data[10];
void ADC_Task_entry(void * pvParameters)
{
FSP_PARAMETER_NOT_USED(pvParameters);
double adcValue = 0.0;
ADC_Init();
while(1)
{
if (scan_0_3V3_flag)
{
adcValue = Read_ADC_Voltage_Value();
xQueueSend(queue_adcValue, &adcValue, 0);
}
vTaskDelay(10);
}
}
‘在hal_entry.c不需要加入任何代码,所有与os有关代码由[瑞萨]在生成项目时完成了.’
这次编译没有出错:
compiling vector_data.c...
linking...
Program Size: Code=14436 RO-data=2184 RW-data=12 ZI-data=24980
FromELF: creating hex file...
After Build - User command #1: cmd /c ""E:\lst\ra4l1\ra4-e2-64\lu\rasc_launcher.bat" "E:\lst\ra4l1\ra4-e2-64\lu\rasc_version.txt" -nosplash --launcher.suppressErrors --gensmartbundle --compiler ARMv6 --devicefamily ra "E:\lst\ra4l1\ra4-e2-64\lu\configuration.xml" "E:\lst\ra4l1\ra4-e2-64\lu\Objects\lu.axf" 2> "%TEMP%\rasc_stderr.out""
[INFO] Input file "E:\lst\ra4l1\ra4-e2-64\lu\Objects\lu.axf" is newer than output file "E:\lst\ra4l1\ra4-e2-64\lu\Objects\lu.sbd". Proceeding with RASC invocation...
Generating Smart Bundle..
".\Objects\lu.axf" - 0 Error(s), 94 Warning(s).
Build Time Elapsed: 00:00:22
rfp-cli.exe命令行烧录部分 :
- MODE CONFIG**
配置成sci boot模式
- 连接带自己USB-com接口tx,rx到usb


*找到编译后hex文件\lu\Objects\lu.hex并copy到Renesas Flash软件安后目录
用type-c usb 连接线连接开发板和电脑,在设备管理器找到com口号为com5
在Renesas Flash软件安后目录打开命令窗口,每次发送命令前最好按一下复位。运行各命令。
命令rfp-cli -d RA -lp 查看可以用com口
Renesas Flash Programmer CLI V1.12
Module Version: V3.19.00.000
[Port]
COM5
COM6
COM7
命令 rfp-cli -d RA -port COM5 -ls查看可以用速度
Renesas Flash Programmer CLI V1.12
Module Version: V3.19.00.000
Connecting the tool (COM port)
Tool: COM5
Interface: 2 wire UART
Connecting the target device
Disconnecting the tool[Speed]
9600
115200
命令 rfp-cli -d RA -port COM5 -sig查看目标信息
Renesas Flash Programmer CLI V1.12
Module Version: V3.19.00.000
Connecting the tool (COM port)
Tool: COM5
Interface: 2 wire UART
Connecting the target device
Speed: 115,200 bps
Connected to R7FA4E2B93CFM
Signature:
Device: R7FA4E2B93CFM
Boot Firmware Version: V7.0.0
Device Unique ID: 4E4B2D5C5B634B533539393742037771
Device Code: 05
Memory Info:
00000000 - 0000FFFF: Code Flash 1 (Block Size: 8 KB)
00010000 - 0001FFFF: Code Flash 1 (Block Size: 32 KB)
08000000 - 08000FFF: Data Flash 1 (Block Size: 64)
0100A100 - 0100A2FF: Config Area 1 (Block Size: 512)
Disconnecting the tool
Operation successful
命令rfp-cli -d RA -port COM5 -file lu.hex -p 烧录
Renesas Flash Programmer CLI V1.12
Module Version: V3.19.00.000
Load: "E:\Renesas Electronics\Programming Tools\Renesas Flash Programmer V3.19\lu.hex" (Size=47859, CRC=E2430C49)
Connecting the tool (COM port)
Tool: COM5
Interface: 2 wire UART
Connecting the target device
Speed: 115,200 bps
Connected to R7FA4E2B93CFM
Erasing the target device
[Code Flash 1] 00000000 - 00005FFF
Writing data to the target device
[Code Flash 1] 00000000 - 000040FF
[Config Area 1] 0100A100 - 0100A17F
[Config Area 1] 0100A200 - 0100A2FF
Disconnecting the tool
Operation successful

命令rfp-cli -d RA -port COM5 -rv 0 10 读取目标地址 数量数据
Renesas Flash Programmer CLI V1.12
Module Version: V3.19.00.000
Connecting the tool (COM port)
Tool: COM5
Interface: 2 wire UART
Connecting the target device
Speed: 115,200 bps
Connected to R7FA4E2B93CFM
Reading data from the device
[Code Flash 1] 00000000 - 00000009
Address | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
---------+------------------------------------------------
00000000 | 40 60 00 20 91 0C 00 00 85 03
Disconnecting the tool
Operation successful
- 文件前16字节:40600020910C000085030000B3020000

烧录数据正确,成功
MODE CONFIG *
配置成flash模式,运行成功,
com显示:
l_key 3
Hello World!
S_key 1
ADC:0
?\0\0\0ADC:0
?\0\0\0ADC:0
?\0\0\0Hello World!
ADC:0
?\0\0\0ADC:0
?\0\0\0ADC:0
?\0\0\0S_key 1
ADC:0
?\0\0\0ADC:0
?\0\0\0ADC:0
?\0\0\0Hello World!
Hello World!
Hello World!
Hello World!


达到预期状态。