续前【RA4E2开发板评测】1、开发板开箱与环境搭建,rfp-cli.exe命令行烧录
背景 :大多数操作系统似乎能同时执行多个程序。这称为多任务处理。随着应用程序变得越来越复杂,[单片机]裸机开发已经无法满足对于复杂程序的需求。于是具有多任务调度和实时响应特性及各种认证的微软开源ThreadX便越来越受工程师们青睐。
ThreadX由美国的微软拥有者和维护者,ThreadX 是一个高效、紧凑的实时操作系统,专为嵌入式系统设计。它具有以下特性:
小巧且高效:ThreadX 内核非常小,可以用于资源有限的设备。
实时性:提供严格的时间限制,可以保证任务在规定时间内完成。
优先级调度:支持优先级调度,可以根据任务的重要性来调度执行。
简洁的 API:ThreadX 提供了简单易用的接口,方便开发者进行任务管理和调度。
ThreadX 常用于嵌入式设备,如 IoT 设备、医疗设备、消费电子产品等。ThreadX凭借62亿设备采用量及多项行业安全认证,成为小型RTOS标杆。其内核、文件系统、网络协议栈、USB协议栈和GUIX在各领域展现卓越性能。,是目前市场占有率较高的 RTOS。
[瑞萨]RA系列[MCU]兼容[ThreadX]系统,开发环境rasc完美支持ThreadX可简化工程配置,无需手动移植[ThreadX]系统。开发者只需要考虑进程和资源,相当容易使用。
以下介绍如何用瑞萨rasc创建RA4E2开发板的ThreadX工程。
本次实验要使用| Azure RTOS ThreadX | v6.4.0 嵌入式实时操作系统,之前实验都是在裸机上跑的,但当我们要多线程操作时并简化开发时,就需要用到RTOS(Real-Time Operating System)。
通常我们裸机开发要做软件延时用的是FSP库R_BSP_SoftwareDelay函数,它是阻塞式运行的。而在FreeRTOS实时操作系统开发里面使用到tx_thread_sleep函数,它是对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引脚。
ThreadX 部分配置
准备使用按键任务,ADC任务和printf输出任务
点击Stacks选项卡--在左侧的New Thread -- 点击新创建的Thread 属性 -- 修改Name、Symbol以及Priority等,按键切换任务的symbol是Key_Switch_Task,Name是KeySwitch,Stack Size为256,优先级2。展开内存分配可以

在线程配置上方是ThreadX 配置,有设置自定义的 tx_user.h 文件路径等等,暂时采用默认。
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 声明访问这个变量。这种方式虽然简单直接,但存在一些问题:
- 全局变量数量多,容易混乱,维护困难;
- 没有访问控制,可能被任意地方修改;
- 多个模块同时访问时容易出现竞态条件;
- 不适用于多任务并发的系统。
在ThreadX中,队列是一个线程安全的、先进先出(FIFO)缓冲结构,用于任务之间或者任务与中断之间安全传递数据。你可以把它理解为一个 任务之间传纸条的小信箱 ,一方放入数据,另一方接收数据,而且不会因为同时访问而出错。
在Threads下方有一个Object区域,点击New Object-- Queue

创建一个队列,修改symbol为queue_adcValue,Message Size (Words) 1,queue Size填16``。 在Threads下方有一个Object区域,点击New Object-- semaphore`
创建一个信号量,symbol为semphr_keyChanged,Symbol semphr_keyChanged,Initial count 0

完成后点击生成代码即可

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)
{ uint8_t key_state;
while(1)
{
key_state=key_read();
switch (key_state)
{
case 0:
break;
case 1:
printf("S_key 1 \r\n");
tx_semaphore_ceiling_put(&semphr_keyChanged,1);
break;
case 2:
printf("D_key 2 \r\n");
break;
case 3: printf("l_key 3 \r\n");
break;
}
tx_thread_sleep(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)
{
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 (tx_semaphore_get (&semphr_keyChanged, 0) == TX_NO_INSTANCE)
{
}
else
{scan_0_3V3_flag=!scan_0_3V3_flag;
printf("!scan_0_3V3_flag;S_key 1 \r\n");
}
tx_thread_sleep(10);
if(i==100){
printf("Hello World!\r\n");
i=0;
}
if (tx_queue_receive (&queue_adcValue, &num, 0) == TX_SUCCESS )
{
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)
{
uint16_t adcValue = 0;
ADC_Init();
while(1)
{
if (scan_0_3V3_flag)
{
adcValue = Read_ADC_Voltage_Value();
tx_queue_send(&queue_adcValue, &adcValue, 0);
}
tx_thread_sleep(10);
}
}
‘在hal_entry.c不需要加入任何代码,所有与os有关代码由[瑞萨]在生成项目时完成了.’
这次编译没有出错:
compiling vector_data.c...
linking...
Program Size: Code=11836 RO-data=560 RW-data=2320 ZI-data=10944
FromELF: creating hex file...
After Build - User command #1: cmd /c ""E:\lst\ra4l1\ra4-e2-64\FSP_Project\rasc_launcher.bat" "E:\lst\ra4l1\ra4-e2-64\FSP_Project\rasc_version.txt" -nosplash --launcher.suppressErrors --gensmartbundle --compiler ARMv6 --devicefamily ra "E:\lst\ra4l1\ra4-e2-64\FSP_Project\configuration.xml" "E:\lst\ra4l1\ra4-e2-64\FSP_Project\Objects\FSP_Project.axf" 2> "%TEMP%\rasc_stderr.out""
[INFO] Output file "E:\lst\ra4l1\ra4-e2-64\FSP_Project\Objects\FSP_Project.sbd" does not exist. Proceeding with RASC invocation...
Generating Smart Bundle..
".\Objects\FSP_Project.axf" - 0 Error(s), 474 Warning(s).
Build Time Elapsed: 00:00:53
rfp-cli.exe命令行烧录部分 :
- MODE CONFIG**
配置成sci boot模式
- 连接带自己USB-com接口tx,rx到usb


*找到编译后hex文件\FSP_Project\Objects\FSP_Project.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\FSP_Project.hex" (Size=42459, CRC=68D14AFE)
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 - 00003FFF
Writing data to the target device
[Code Flash 1] 00000000 - 0000397F
[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!


与FreeRTOS相同线程相比,编程更简便,ro rw rom Size都更小。
达到预期状态。