续前【RA-Eco-RA4E2-64PIN-V1.0开发板试用】4、Amazon FreeRTOS初探,第一个程序
和【RA-Eco-RA4E2-64PIN-V1.0开发板试用】3、第一个程序增加adc(printf输出com9)。
原来的框图:
准备新的框图:
如上图所示,硬件部分由继电器模块,RA-Eco-RA4E2-64PIN-V1.0开发板 等组成;其中:原来 OLED,button模块准备用UART (r_sci_uart)作为显示和部分设置;继电器模块,负责执行。
RA-Eco-RA4E2-64PIN-V1.0开发板负责完成和所有外设模块通信和功能逻辑的实现。
其中LED1 (P113灯)用来显示状态,闪烁表示DF—B,红色表示DF—A,灭表示DFX;ADC 的第 0 ,5个通道模拟输入;P04来通过光耦中间继电器控制加热设备;com9 负责显示和部分设置调试设备信息。
软件框架
软件模块说明,
如上图所示,该项目软件架构主要采用几个线程完成,其中:
CommandConsoleTask 线程:负责显示和部分设置,RTC,rtos状态,调试设备信息。
DF _ A、DF_B、DFX线程:负责执行继电器控制加热设备。
ADC_Mesurement_线程: ADC 的模拟输入功能。
LED1_thread线程: LED灯显示状态。
LED2_thread 线程:设备初始化及DF _ A、DF_B、DFX线程 起动。
RA Smart Configurator软件可以在瑞萨官网进行下载,下载地址:https://www.renesas.cn
| setup_fsp_v5_4_0_rasc_v2024-04.exe
安装完成后在RenesasRAsc_v eclipse目录中运行rasc.exe
配置keil项目
可以进入片配置也可以关闭在keil项目项目中.
产生目录:
打开lu.uvprojx
打开该文件配置的RA Smart Configurator
根据板图:
![]
加入3个004,113,207:
时钟图:![未标题-2 拷贝.png]
新增线程(Threads)
点击Stacks选项卡--在左侧的New Thread -- 点击新创建的Thread 属性 -- 修改Name和Symbol,下图所示的是LED1线程,LED2,CommandConsoleTask``ADC_Mesurement
的同理。
选择堆算法
接着为堆选择算法,这里一共有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算法。其实只点灯的话不选择算法也可以的。
点击LED1 -- New Stack -- RTOS -- FreeRTOS Heap4
接下来可能会报错,要开启动态内存分配。点击LED1这个线程 -- 在属性里Support Dynamic Allocation 改为 Enabled
rtos部分设置:
编写代码
保存配置文件,生成项目代码。
在FSP_Project\src会多出LED1_thread_entry.c
和LED2_thread_entry.c
等4个文件,这4个文件是留给我们写线程具体功能的。
在LED1_thread_entry.c
中的死循环中添加代码
if(lfalg &0x2)
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_13, BSP_IO_LEVEL_HIGH);
else
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_13, BSP_IO_LEVEL_LOW);
if(lfalg &0x8)
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_07, BSP_IO_LEVEL_HIGH);
else
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_07, BSP_IO_LEVEL_LOW);
vTaskDelay (400);
if(lfalg &0x1)
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_13, BSP_IO_LEVEL_HIGH);
else
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_13, BSP_IO_LEVEL_LOW);
if(lfalg &0x4)
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_07, BSP_IO_LEVEL_HIGH);
else
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_07, BSP_IO_LEVEL_LOW);
vTaskDelay (400);
在LED2_thread_entry.c
中添加代码
fsp_err_t err = FSP_SUCCESS;
err = R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
assert(FSP_SUCCESS == err);
err = R_ADC_Open(&g_adc0_ctrl, &g_adc0_cfg);
assert(FSP_SUCCESS == err);
err = R_ADC_ScanCfg(&g_adc0_ctrl, &g_adc0_channel_cfg);
assert(FSP_SUCCESS == err);
while (1)
{
df_a()
}
void adc_callback (adc_callback_args_t * p_args)
{
FSP_PARAMETER_NOT_USED(p_args);
scan_complete_flag = true;
}
void user_uart_callback (uart_callback_args_t * p_args)
{
switch (p_args->event)
{
case UART_EVENT_RX_CHAR:
{uint8_t Res=p_args->data;
if((USART_RX_STA&0x8000)==0)
{
if(USART_RX_STA&0x4000)
{
if(Res!=0x0a)USART_RX_STA=0;
else {
if ((USART_RX_STA&0X3FFF)==0)USART_RX_STA=0;
else USART_RX_STA|=0x8000;
}
}
else
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;
}
}
}
}
break;
case UART_EVENT_TX_COMPLETE:
{
uart_send_complete_flag = true;}
break;
default:
break;
}
}
int fputc(int ch, FILE *f)
{
fsp_err_t err = FSP_SUCCESS;
err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&ch, 1);
if(FSP_SUCCESS != err) __BKPT();
while(uart_send_complete_flag == false){}
uart_send_complete_flag = false;
return ch;
}
在ADC_Mesurement_entry.c`中的添加代码
#include "hal_data.h"
#include "stdio.h"
/* ADC_Sample entry function */
/* pvParameters contains TaskHandle_t */
extern volatile uint8_t lfalg ;
extern volatile uint8_t scan_complete_flag;
void ADC_Mesurement_entry(void * pvParameters)
{
fsp_err_t err = FSP_SUCCESS;
double a0,a5;
uint16_t adc_data1=0;
FSP_PARAMETER_NOT_USED(pvParameters);
while(1)
{
if(lfalg &0x10)
{
for (uint8_t i = 0; i < 5; i++)
{
(void) R_ADC_ScanStart(&g_adc0_ctrl);
scan_complete_flag = false;
while (!scan_complete_flag)
{
vTaskDelay(100);
}
err =R_ADC_Read(&g_adc0_ctrl, ADC_CHANNEL_0, &adc_data1);
assert(FSP_SUCCESS == err);
a0=(adc_data1/4095.0)*3.3;
err =R_ADC_Read(&g_adc0_ctrl, ADC_CHANNEL_5, &adc_data1);
assert(FSP_SUCCESS == err);
a5=(adc_data1/4095.0)*3.3;
R_BSP_SoftwareDelay (20, BSP_DELAY_UNITS_MILLISECONDS);
printf("a0: %f\\r\\n", a0);
printf("a5: %f\\r\\n", a5);
}
lfalg = (lfalg &0xf);
printf("adc over\\r\\n");
}
vTaskDelay(100);
}
}
在CommandConsole
_entry.c`中的添加代码
extern uint8_t USART_RX_BUF[50];
extern uint16_t USART_RX_STA ;
volatile uint8_t falg,lfalg ;
rtc_time_t get_time =
{
.tm_hour = RESET_VALUE,
.tm_isdst = RESET_VALUE,
.tm_mday = RESET_VALUE,
.tm_min = RESET_VALUE,
.tm_mon = RESET_VALUE,
.tm_sec = RESET_VALUE,
.tm_wday = RESET_VALUE,
.tm_yday = RESET_VALUE,
.tm_year = RESET_VALUE,
};
static void rtc_date_time_conversion(rtc_time_t * time, unsigned char read_buffer[])
{
time->tm_mday = (((read_buffer[0] - ASCII_ZERO) * PLACE_VALUE_TEN) + (read_buffer[1] - ASCII_ZERO));
time->tm_mon = ((((read_buffer[3] - ASCII_ZERO) * PLACE_VALUE_TEN) + (read_buffer[4] - ASCII_ZERO))) - MON_ADJUST_VALUE;
time->tm_year = (((read_buffer[6] - ASCII_ZERO) * PLACE_VALUE_THOUSAND) +
((read_buffer[7] - ASCII_ZERO )* PLACE_VALUE_HUNDRED) +
((read_buffer[8] - ASCII_ZERO) * PLACE_VALUE_TEN) + (read_buffer[9] - ASCII_ZERO)) - YEAR_ADJUST_VALUE;
time->tm_hour = (((read_buffer[11] - ASCII_ZERO) * PLACE_VALUE_TEN) + (read_buffer[12] - ASCII_ZERO));
time->tm_min = (((read_buffer[14] - ASCII_ZERO) * PLACE_VALUE_TEN) + (read_buffer[15] - ASCII_ZERO));
time->tm_sec = (((read_buffer[17] - ASCII_ZERO) * PLACE_VALUE_TEN )+ (read_buffer[18] - ASCII_ZERO));
}
void RTC_setup(void)
{
fsp_err_t err = FSP_SUCCESS;
printf ("\\r\\nSetting RTC Date and Time \\r\\n");
printf("\\r\\nEnter Date and Time in DD:MM:YYYY HH:MM:SS format.\\nSample Input: '04:11:2019 15:23:05'\\r\\n");
USART_RX_STA=0;
vTaskDelay(100);
for (uint8_t i = 0; i < 150; i++)
{
if((USART_RX_STA&0x8000)==1)
{
rtc_date_time_conversion(&get_time, &USART_RX_BUF[0]);
err = R_RTC_CalendarTimeSet(&g_rtc0_ctrl, &get_time);
return;
}
else
{vTaskDelay(100);
}
}
}
void RTC_up(void)
{
if ((USART_RX_STA&0X3FFF)==1)
{
R_RTC_CalendarTimeGet(&g_rtc0_ctrl, &get_time);
printf(" %d y %d m %d d %d h %d m %d s %d w\\r\\n",get_time.tm_year+1900,get_time.tm_mon+1,get_time.tm_mday,get_time.tm_hour,get_time.tm_min,get_time.tm_sec,get_time.tm_wday);
printf(" input 1 to setup rtc.\\r\\n");
USART_RX_STA=0;
vTaskDelay(100);
for (uint8_t i = 0; i < 150; i++)
{
if((USART_RX_STA&0x8000)==1)
{
switch (USART_RX_BUF[0])
{
case '1':
RTC_setup();
USART_RX_STA=0;
return;
break;
default:
USART_RX_STA=0;
return;
break;
}
}
else
{vTaskDelay(100);
}
}
}
else
{
switch (USART_RX_BUF[1])
{
case '1':
RTC_setup();
USART_RX_STA=0;
return;
case '2':
R_RTC_CalendarTimeGet(&g_rtc0_ctrl, &get_time);
printf(" %d y %d m %d d %d h %d m %d s %d w\\n",get_time.tm_year+1900,get_time.tm_mon+1,get_time.tm_mday,get_time.tm_hour,get_time.tm_min,get_time.tm_sec,get_time.tm_wday);
USART_RX_STA=0;
return;
default:
return;
}
}
}
void LED_up(void)
{
if ((USART_RX_STA&0X3FFF)==1)
{
printf(" input 1~6 to setup LED1.LED2\\r\\n");
USART_RX_STA=0;
vTaskDelay(100);
for (uint8_t i = 0; i < 150; i++)
{
if((USART_RX_STA&0x8000)==1)
{
switch (USART_RX_BUF[0])
{
case '1':
lfalg = (lfalg &0x1c)+3;
USART_RX_STA=0;
return;
case '2':
lfalg = (lfalg &0x1c);
USART_RX_STA=0;
return;
case '3':
lfalg = (lfalg &0x13)+12;
USART_RX_STA=0;
return;
case '4':
lfalg = (lfalg &0x13);
USART_RX_STA=0;
return;
case '5':
lfalg = (lfalg &0x1c)+2;
USART_RX_STA=0;
return;
case '6':
lfalg = (lfalg &0x13)+8;
USART_RX_STA=0;
return;
default:
USART_RX_STA=0;
return;
}
}
else
{vTaskDelay(100);
}
}
}
else
{
switch (USART_RX_BUF[1])
{
case '1':
lfalg = (lfalg &0x1c)+3;
USART_RX_STA=0;
return;
case '2':
lfalg = (lfalg &0x1c);
USART_RX_STA=0;
return;
case '3':
lfalg = (lfalg &0x13)+12;
USART_RX_STA=0;
return;
case '4':
lfalg = (lfalg &0x13);
USART_RX_STA=0;
return;
case '5':
lfalg = (lfalg &0x1c)+2;
USART_RX_STA=0;
return;
case '6':
lfalg = (lfalg &0x13)+8;
USART_RX_STA=0;
return;
default:
USART_RX_STA=0;
return;
}
}
}
void adc_up()
{
lfalg = (lfalg &0xf)+16;
USART_RX_STA=0;
return;
}
void rtos()
{
"*****************************************************************\\n \\
X: running, B: blocking, R: ready, D: delete, S: suspend\\n \\
*****************************************************************\\n \\
task_name task_state priority stack task_num\\n\\
_____________________________________________\\n"
"task_name run_count usage % \\n\\
____________________________________________\\n"
static uint8_t InfoBuffer[ MAX_OUTPUT_LENGTH ];
vTaskGetRunTimeStats(InfoBuffer);
printf("ÈÎÎñÃû\\t\\t\\tÔËÐÐʱ¼ä\\tÔËÐÐËùÕ¼°Ù·Ö±È\\r\\n");
printf("task_name run_count usage % \\r\\n");
printf("%s\\r\\n",InfoBuffer);
vTaskList(InfoBuffer);
printf("*****************************************************************\\r\\n");
printf("task_name task_state priority stack task_num\\r\\n");
printf("%s\\r\\n",InfoBuffer);
USART_RX_STA=0;
return;
}
void df_a(){
}
void CommandConsoleTask_entry(void * pvParameters)
{
FSP_PARAMETER_NOT_USED(pvParameters);
vTaskDelay(100);
while(1)
{
if((USART_RX_STA&0x8000)==1)
{
switch (USART_RX_BUF[0])
{
case '1':
RTC_up();
break;
case '2':
LED_up();
break;
case '3':
adc_up();
break;
case '4':
rtos();
break;
case '5':
df_a();
break;
case '6':
falg = 6;
break;
default:
break;
}
}
else
{vTaskDelay(100);
}
}
}
‘在hal_entry.c不需要加入任何代码,所有与os有关代码由[瑞萨]在生成项目时完成了.’
这次编译没有出错:
compiling vector_data.c...
linking...
Program Size: Code=14668 RO-data=2496 RW-data=60 ZI-data=7524
FromELF: creating hex file...
After Build - User command #1: cmd /c "start "Renesas" /w cmd /c ""E:\lst\ra0e1-20240827154516\123\ra4e2-rt\FSP_Project\rasc_launcher.bat" "E:\lst\ra0e1-20240827154516\123\ra4e2-rt\FSP_Project\rasc_version.txt" -nosplash --launcher.suppressErrors --gensmartbundle --compiler ARMv6 --devicefamily ra "E:\lst\ra0e1-20240827154516\123\ra4e2-rt\FSP_Project\configuration.xml" "E:\lst\ra0e1-20240827154516\123\ra4e2-rt\FSP_Project\Objects\FSP_Project.axf" 2> "%TEMP%\rasc_stderr.out"""
".\Objects\FSP_Project.axf" - 0 Error(s), 113 Warning(s).
Build Time Elapsed: 00:00:34
设置出HEX文件
在C:RenesaslustObjects目录下生成lst.hex文件。
开发板是支持用串口工具来下载程序的,当然在MDK的环境下用串口是无法完成这个任务的,它必需借助工具软件Renesas Flash Programmer的支持,其软件版本为 V3.14。
在安装了Renesas Flash Programmer之后,该如何进行下载呢?
其步骤如下:
1)将开发板由运行模式切换为下载模式,即改变J1上引脚的连接方式,按图所示用短接子将引脚1和引脚3连接起来。
切换工作模式
2)串口连接
串口编程所用的引脚是P109和P110,其中P110是输入端要接串口的发送端TXD,而P109
是输出端接串口的接收端RXD 。
图3引脚功能
3)运行工具软件,先创建一个工程,见图4所示。然后选取待下载的*.hex文件,并按下开发板的复位键以进入下载状态。
用上次安装Renesas Flash Programmer _Package_V31400软件,
这次烧成功。
Target device : RA
Connecting the tool
Tool : COM port (COM3), Interface : 2 wire UART
Connecting to the target device
Setting the target device
Communication speed : 115200bps
Setting the target device
Erasing the selected blocks
[Code Flash 1] 0x00000000 - 0x0003FFFF size : 256 K
[Data Flash 1] 0x40100000 - 0x40101FFF size : 8 K
Writing data to the target device
[Code Flash 1] 0x00000000 - 0x00000DD7 size : 3.5 K
[Config Area] 0x01010018 - 0x01010033 size : 28
Verifying data
[Code Flash 1] 0x00000000 - 0x00000DD7 size : 3.5 K
[Config Area] 0x01010018 - 0x01010033 size : 28
Disconnecting the tool
Operation completed.
重新设boot引脚
reset达到预期状态。