谢谢eepw的测评机会。板子到手立即上手测试,一般点灯和串口打印都是必须的,所以这次也不例外。之所以同时做flash测试和笔者最终目标有关(先卖个关子)
瑞萨的mcu一般都通过rasc这个工具配置,生成适用于cmake/mdk等工具的项目工程,然后用对应工具编译的。笔者一直
是linux下做开发的,瑞萨rasc这个工具也支持linux,这点需要给瑞萨点赞。Linux下适合使用cmake来构建。
rasc可以去瑞萨github下载appimage安装,非常顺滑此处略过不提。安装好后启动进配置界面,说实话
笔者这第一次用rasc工具呢。配置步骤中大部分很容易明白,配置关键几步如下:
第一步选芯片、板子、toolchain、工程种类
板子选Custom User Board即可,Device这里其实是选芯片,芯片丝印清晰可见是R7FA6M4AF3CFB,语言
选c语言,工程种类选cmake,toolchain选gcc。详细情形如图。
第二步选Flat Project
RA6M4是Cortex-M33加持,支持trustzone,但因笔者暂时不想开启trustzone,所以这里选Flat Project
第三步不使用RTOS
第四步配置时钟
CPK-RA6M4未板载晶振,所以这里时钟源需要选HOCO。最大能有200MHZ,HOCO经2分频, Mul为20, 正好
是200MHZ,其它默认即可
第五步点灯引脚配置
据原理图,P106引脚接了LED,所以这里把P106 enable,功能选为GPIO
第六步串口引脚配置
CPK-RA6M4虽然板载了一颗MCU做jlink调试器,但不支持cdc-acm串口,所以想用串口我们需要外接一个
usb转ttl的。CPK-RA6M4其实引出了MCU的所有针脚,咱们可以选比较方便的引脚。观察板子上丝印P101和
P410正好靠在一起,这里下拉到Connectivity:SCI,选中SCI0,配置好TXD0与RXD0分别为P101与P410
第七步串口参数配置
此步骤在stacks选项卡中配,具体参数如图所示。这里比较重要的是取一个比较好的callback函数名,
后面在代码里会用上
第八步开启flash
因flash不用配置引脚复用功能,所以只要在stacks中开启,此步骤同样在stacks选项卡中配置即可。这里比较重要的也是callback函数名。
配置完成后即可点击按钮生成项目了。项目生成完毕后,需要添加必要的代码,完成具体逻辑,笔者添加的代码如下:
串口打印相关代码:
static volatile uint8_t uart_rx_event; static volatile uint8_t uart_tx_event; void uart_callback(uart_callback_args_t *p_args) { if (UART_EVENT_RX_COMPLETE == p_args->event) uart_rx_event = 1; if (UART_EVENT_TX_COMPLETE == p_args->event) uart_tx_event = 1; } int _write(int file, char *ptr, int len) { fsp_err_t err; (void)(file); uart_tx_event = 0; err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)ptr, (uint32_t)len); if (FSP_SUCCESS != err) len = -1; while (!uart_tx_event) R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS); return len; }
flash测试代码
char msgbuf[256]; fsp_err_t flash_hp_code_flash_operations(void) { fsp_err_t err = FSP_SUCCESS; flash_result_t blank_check_result = FLASH_RESULT_BLANK; uint8_t write_buffer[BLOCK_SIZE] = {RESET_VALUE}; uint8_t read_buffer[BLOCK_SIZE] = {RESET_VALUE}; /* Set write buffer, clear read buffer */ for (uint8_t index = 0; index < BLOCK_SIZE; index++) { write_buffer[index] = index; } /* Disable interrupts to prevent vector table access while code flash is in P/E mode. */ __disable_irq(); /* Erase Block */ err = R_FLASH_HP_Erase(&g_flash0_ctrl, FLASH_HP_CF_BLOCK_8, BLOCK_NUM); __enable_irq(); /* Error Handle */ if (FSP_SUCCESS != err) { printf("\r\nErase API failed, Restart the Application"); return err; } printf("\r\nErase successful"); /* Blank Check */ __disable_irq(); err = R_FLASH_HP_BlankCheck(&g_flash0_ctrl, FLASH_HP_CF_BLOCK_8, FLASH_HP_CF_BLOCK_SIZE_8KB, &blank_check_result); __enable_irq(); /* Error Handle */ if (FSP_SUCCESS != err) { printf("\r\nBlankCheck API failed, Restart the Application"); return err; } printf("\r\nBlankCheck API Successful"); /* Validate the blank check result */ if (FLASH_RESULT_BLANK == blank_check_result) { printf("\r\nFLASH is blank "); } else if (FLASH_RESULT_NOT_BLANK == blank_check_result) { printf("\r\n Flash is not Blank, not to write the data. Restart the application"); return (fsp_err_t)FLASH_RESULT_NOT_BLANK; } /* Write code flash data*/ __disable_irq(); err = R_FLASH_HP_Write(&g_flash0_ctrl, (uint32_t) write_buffer,FLASH_HP_CF_BLOCK_8, BLOCK_SIZE); __enable_irq(); /* Error Handle */ if (FSP_SUCCESS != err) { printf("\r\nWrite API failed, Restart the Application"); return err; } printf("\r\nWriting flash data is successful\r\n"); /*Read code flash data */ memcpy(read_buffer, (uint8_t *) FLASH_HP_CF_BLOCK_8, BLOCK_SIZE); /* comparing the write_buffer and read_buffer */ if (RESET_VALUE == memcmp(read_buffer, write_buffer, BLOCK_SIZE)) { printf("\r\nRead and Write buffer is verified and successful"); /* Print the read data on the RTT terminal */ printf("\r\nRead Data : \r\n"); READ_DATA_PRINT(read_buffer); } else { printf("Read and Write buffer is verified and not successful"); return FSP_ERR_WRITE_FAILED; } /* Erase block again */ printf("\r\nErase block again"); __disable_irq(); err = R_FLASH_HP_Erase(&g_flash0_ctrl, FLASH_HP_CF_BLOCK_5, BLOCK_NUM); __enable_irq(); if(FSP_SUCCESS != err) { printf("\r\nErase API failed, Restart the Application"); return err; } printf("\r\nErase successful"); /* Enable interrupts after code flash operations are complete. */ //__enable_irq(); return err; }
hal_entry.c中测试序列:
R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg); printf("Hello EEPW!!!\r\n"); fsp_err_t err = FSP_SUCCESS; err = R_FLASH_HP_Open(&g_flash0_ctrl, &g_flash0_cfg); if (FSP_SUCCESS != err) printf("\r\n Flah_HP_Open API failed"); err = R_FLASH_HP_StartUpAreaSelect(&g_flash0_ctrl, FLASH_STARTUP_AREA_BLOCK0, true); if (err != FSP_SUCCESS) printf("\r\n Flah_HP_StartUpAreaSelect API failed"); flash_hp_code_flash_operations(); flash_hp_deinit(); while(1) { R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_06, BSP_IO_LEVEL_HIGH); R_BSP_SoftwareDelay(200, BSP_DELAY_UNITS_MILLISECONDS); R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_06, BSP_IO_LEVEL_LOW); R_BSP_SoftwareDelay(200, BSP_DELAY_UNITS_MILLISECONDS); }
先打印"Hello EEPW!!!"字样,然后即做flash的擦、读、写测试,最后循环点灯。
至此代码工作完成,可以编译啦:
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/gcc.cmake -DCMAKE_BUILD_TYPE=Release -B /tmp/build cmake --build /tmp/build -j8
在/tmp/build/目录下即有$PROJECT_NAME.srec文件生成,比如笔者PROJECT_NAME起的是ra6m4,所以文件就是ra6m4.srec
jlink烧录:
下列命令先启动jlink:
JLinkExe -device R7FA6M4AF3CFB -if SWD -autoconnect 1 -speed 20000
然后在jlink命令行中执行下列命令:
loadfile /tmp/build/ra6m4.srec
烧录完成后重启板子即可。笔者串口log如下,供参考:
Hello EEPW!!! Erase successful BlankCheck API Successful FLASH is blank Writing flash data is successful Read and Write buffer is verified and successful Read Data : 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f Erase block again Erase successful
至此我们已经实现了点灯、串口打印和flash测试,为后面的目标打下了坚实基础