本贴是Follow me第二季第3期,所有任务的相关视频、任务内容、代码等内容的汇总帖。具体如下:
一、任务介绍
本次Follow me第二季第3期的活动,主要的硬件环境就是RA的evb板子,具体型号为:EK-RA6M5开发套件。包含一个开发板,一条micro USB数据线,一条网线和一条micro USB转type A接口的数据线。
本次活动主要参考ra官方的《ra-fsp-examples-5.6.0.example.2》示例程序,完成以下四个任务:
- 入门任务:搭建环境,下载调试示例程序,Blink,按键
- 基础任务:quad-spi flash和octo-spi flash配置及读写速度测试;DAC配置生成波形正弦波形
- 进阶任务:示例程序中新增命令打印信息,输出DAC的实时数据
- 扩展任务:设计一个类似信号发生器功能的例程。通过命令或按键,设置DAC输出波形,可通过flash存储历史波形等信息。
二、具体任务
1. 入门任务
》》》【Follow me第二季第3期】 EK-RA6M5 入门任务 《《《
void button_irq10_callback(external_irq_callback_args_t *p_args)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
BaseType_t xResult = pdFAIL;
EventBits_t uxBits;
/* Void the unused args */
FSP_PARAMETER_NOT_USED(p_args);
uxBits = xEventGroupGetBitsFromISR (g_update_console_event);
if ((uxBits & (STATUS_UPDATE_INTENSE_INFO)) != (STATUS_UPDATE_INTENSE_INFO))
{
/* Cast, as compiler will assume calc is int */
g_board_status.led_intensity = (uint16_t) ((g_board_status.led_intensity + 1) % 4);
xResult = xEventGroupSetBitsFromISR(g_update_console_event, STATUS_UPDATE_INTENSE_INFO,
&xHigherPriorityTaskWoken);
/* Was the message posted successfully? */
if (pdFAIL != xResult)
{
/* If xHigherPriorityTaskWoken is now set to pdTRUE then a context
switch should be requested. The macro used is port specific and will
be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
the documentation page for the port being used. */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
}
void button_irq9_callback(external_irq_callback_args_t *p_args)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
BaseType_t xResult = pdFAIL;
EventBits_t uxBits;
/* Void the unused args */
FSP_PARAMETER_NOT_USED(p_args);
uxBits = xEventGroupGetBitsFromISR (g_update_console_event);
if ((uxBits & (STATUS_UPDATE_FREQ_INFO)) != (STATUS_UPDATE_FREQ_INFO))
{
/* Cast, as compiler will assume calc is int */
g_board_status.led_frequency = (uint16_t) ((g_board_status.led_frequency + 1) % 4);
xResult = xEventGroupSetBitsFromISR(g_update_console_event, STATUS_UPDATE_FREQ_INFO, &xHigherPriorityTaskWoken);
/* Was the message posted successfully? */
if (pdFAIL != xResult)
{
/* If xHigherPriorityTaskWoken is now set to pdTRUE then a context
switch should be requested. The macro used is port specific and will
be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
the documentation page for the port being used. */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
}
2. 基础任务
》》》【Follow me第二季第3期】基础任务 《《《
FLASH读写速度测试
DAC波形输出
2.1 OSPI写测试
static uint32_t write_dopi_ospi(uint32_t data_size)
{
fsp_err_t err;
uint32_t test_var;
/* Cast to req type */
uint8_t * p_dest = (uint8_t *)OSPI_DMA_ADDRESS;
timer_status_t status = {};
uint32_t number_of_pages;
R_GPT_Open(g_memory_performance.p_ctrl, g_memory_performance.p_cfg);
/* Cast, as compiler will assume result of calc to be int */
number_of_pages = (uint32_t)(data_size * (1024 / OSPI_TEST_PAGE_SIZE));
/* Write 32 blocks worth of data starting at Block 0
* Block size = 64K, i.e. 2 blocks = 128K of data
* check this comment....... */
for (test_var = 0; test_var < number_of_pages; test_var++ )
{
/* Performance measured around this loop will be slightly lower due to branches and test write-in-progress
* The actual throughput should be measured with direct debugger downloads (not supported by SEGGER yet)*/
R_GPT_Start(g_memory_performance.p_ctrl);
err = R_OSPI_Write(g_ospi.p_ctrl, s_page, p_dest, OSPI_TEST_PAGE_SIZE);
if (FSP_SUCCESS != err)
{
__asm("bkpt");
}
ospi_test_wait_until_wip();
p_dest += OSPI_TEST_PAGE_SIZE;
R_GPT_Stop(g_memory_performance.p_ctrl);
vTaskDelay(1U);
}
R_GPT_StatusGet(g_memory_performance.p_ctrl, &status);
R_GPT_Reset(g_memory_performance.p_ctrl);
R_GPT_Close(g_memory_performance.p_ctrl);
return (status.counter);
}
2.2 OSPI 读测试
static uint32_t read_dopi_ospi(uint32_t data_size)
{
/* Cast to req type */
uint32_t * p_src = (uint32_t *)OSPI_DMA_ADDRESS;
/* Cast to req type */
uint32_t * p_dest = (uint32_t *)s_perf_read;
/* Full bus access, transfer 4 bytes at a time */
timer_status_t status = {};
R_GPT_Open(g_memory_performance.p_ctrl, g_memory_performance.p_cfg);
#ifdef READ_PAGE_BY_PAGE
/* convert to number of mem pages */
number_of_blocks = data_size * ( 1024 / OSPI_TEST_PAGE_SIZE);
while(number_of_blocks--)
{
/* convert page size to number of 32bit reads */
data = (OSPI_TEST_PAGE_SIZE) / 4U;
/* Start timer */
R_GPT_Start(g_memory_performance.p_ctrl);
#ifdef MANUAL_READ
while (data)
{
*p_dest = *p_src;
p_dest++;
p_src++;
data--;
}
#endif
#define READ_MEMCPY
#ifdef READ_MEMCPY
memcpy ( p_dest, p_src, OSPI_TEST_PAGE_SIZE / 4);
p_src += OSPI_TEST_PAGE_SIZE / 4;
p_dest += OSPI_TEST_PAGE_SIZE / 4;
/* Stop timer */
R_GPT_Stop(g_memory_performance.p_ctrl);
vTaskDelay(1U);
#endif
}
#endif /* READ_PAGE_BY_PAGE */
#ifdef READ_AS_SINGLE_BLOCK
/* Start timer */
R_GPT_Start(g_memory_performance.p_ctrl);
R_OSPI_XipEnter(g_ospi.p_ctrl);
memcpy (p_dest, p_src, (data_size * 1024) / 4);
R_OSPI_XipExit(g_ospi.p_ctrl);
/* Stop timer */
R_GPT_Stop(g_memory_performance.p_ctrl);
#endif
R_GPT_StatusGet(g_memory_performance.p_ctrl, &status);
R_GPT_Reset(g_memory_performance.p_ctrl);
R_GPT_Close(g_memory_performance.p_ctrl);
return (status.counter);
}
2.3 QSPI写测试
static uint32_t qspi_write_test(uint32_t block_size)
{
fsp_err_t fsp_err;
uint32_t qspi_write_result = 0;
timer_status_t status = {};
fsp_err_t err = FSP_SUCCESS;
spi_flash_protocol_t current_spi_mode;
/* Convert from kB */
block_size *= 1024;
/* The comms mode is EXTENDED_SPI by default */
current_spi_mode = SPI_FLASH_PROTOCOL_EXTENDED_SPI;
/* initialise the QSPI, and change mode to that set in FSP */
err = qpi_init();
if (FSP_SUCCESS == err)
{
/* The comms mode has changed. So if recovering, this new mode required */
current_spi_mode = g_qspi_cfg.spi_protocol;
}
uint32_t page_write_count = 0;
uint8_t * p_mem_addr;
/* Cast to req type */
p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS;
while (((page_write_count * SECTOR_SIZE) < block_size)
&& ( FSP_SUCCESS == err ) )
{
/* Erase Flash for one sector */
err = R_QSPI_Erase(&g_qspi_ctrl, p_mem_addr, SECTOR_SIZE);
if (FSP_SUCCESS != err)
{
sprintf(s_print_buffer, "R_QSPI_Erase Failed\r\n");
}
else
{
err = get_flash_status();
if (FSP_SUCCESS != err)
{
sprintf(s_print_buffer, "Failed to get status for QSPI operation\r\n");
}
/* Verify the erased block data */
uint32_t count;
for (count = 0; count < SECTOR_SIZE; count++ )
{
if (DEFAULT_MEM_VAL != p_mem_addr[count])
{
/* Verification failed, perhaps the ERASE failed */
err = FSP_ERR_NOT_ERASED;
}
}
}
p_mem_addr += SECTOR_SIZE;
page_write_count++;
}
/* Start the test timer */
fsp_err = R_GPT_Start(g_memory_performance.p_ctrl);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
SYSTEM_ERROR
}
/* Cast to req type */
p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS;
page_write_count = 0;
while (((page_write_count * PAGE_WRITE_SIZE) < block_size)
&& (FSP_SUCCESS == err))
{
if (FSP_SUCCESS == err)
{
/* Write data to QSPI Flash */
/* Each block begins one character shifted along the source text. To avoid regular striping in memory */
err = R_QSPI_Write(&g_qspi_ctrl, &(sp_source[page_write_count]), p_mem_addr, PAGE_WRITE_SIZE);
if (FSP_SUCCESS != err)
{
sprintf(s_print_buffer, "R_QSPI_Write Failed\r\n");
}
else
{
err = get_flash_status();
if (FSP_SUCCESS != err)
{
sprintf(s_print_buffer, "Failed to get status for QSPI operation\r\n");
}
}
}
p_mem_addr += PAGE_WRITE_SIZE;
page_write_count++;
}
/* close QSPI module */
deinit_qspi(current_spi_mode);
fsp_err = R_GPT_Stop(g_memory_performance.p_ctrl);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
SYSTEM_ERROR
}
fsp_err = R_GPT_StatusGet(g_memory_performance.p_ctrl, &status);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
SYSTEM_ERROR
}
fsp_err = R_GPT_Reset(g_memory_performance.p_ctrl);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
SYSTEM_ERROR
}
qspi_write_result = status.counter;
return (qspi_write_result);
}
2.4 QSPI读测试
static uint32_t qspi_read_test(uint32_t block_size)
{
fsp_err_t fsp_err;
fsp_err_t err = FSP_SUCCESS;
uint32_t qspi_read_result = 0;
timer_status_t status = {};
spi_flash_protocol_t current_spi_mode;
uint8_t * p_dma_read_buffer;
uint32_t page_read_count;
uint8_t * p_mem_addr;
/* Convert from kB */
block_size *= 1024;
p_dma_read_buffer = pvPortMalloc(block_size);
if (NULL == p_dma_read_buffer)
{
HeapStats_t pxHeapStats;
vPortGetHeapStats(&pxHeapStats);
sprintf(s_print_buffer, "\r\nQSPI malloc operation Failed - Max free mem: %dbytes\r\n",
pxHeapStats.xSizeOfLargestFreeBlockInBytes);
/* Verification failed, perhaps the ERASE failed */
err = FSP_ERR_NOT_ERASED;
}
/* The comms mode of the FLASH device is EXTENDED_SPI by default */
current_spi_mode = SPI_FLASH_PROTOCOL_EXTENDED_SPI;
/* initialise the QSPI, and change mode to that set in FSP */
err = qpi_init();
if (FSP_SUCCESS == err)
{
/* The comms mode has changed. So if recovering, this new mode required */
current_spi_mode = g_qspi_cfg.spi_protocol;
}
/* Start the test timer */
fsp_err = R_GPT_Start(g_memory_performance.p_ctrl);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
SYSTEM_ERROR
}
page_read_count = 0;
/* cast to req type */
p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS;
while (((page_read_count * PAGE_WRITE_SIZE) < block_size)
&& (FSP_SUCCESS == err))
{
/* Verify the written data */
/* Each block begins one character shifted along the source text. To avoid regular striping in memory */
if ((fsp_err_t) (memcmp (p_mem_addr, &(sp_source[page_read_count]), PAGE_WRITE_SIZE)) != FSP_SUCCESS)
{
err = FSP_ERR_NOT_ERASED;
sprintf(s_print_buffer, "\r\nQSPI operation Failed -> Data read does not match with written data\r\n");
}
p_mem_addr += PAGE_WRITE_SIZE;
page_read_count++;
}
fsp_err = R_GPT_Stop(g_memory_performance.p_ctrl);
/* close QSPI module */
deinit_qspi(current_spi_mode);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
SYSTEM_ERROR
}
fsp_err = R_GPT_StatusGet(g_memory_performance.p_ctrl, &status);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
SYSTEM_ERROR
}
fsp_err = R_GPT_Reset(g_memory_performance.p_ctrl);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
SYSTEM_ERROR
}
qspi_read_result = status.counter;
vPortFree(p_dma_read_buffer);
return (qspi_read_result);
}
2.5 DAC波形输出
fsp_err_t common_init(void)
{
fsp_err_t fsp_err = FSP_SUCCESS;
fsp_err = adc_initialize ();
if (FSP_SUCCESS != fsp_err)
{
return fsp_err;
}
// DAC初始化
fsp_err = R_DAC_Open(&g_dac0_ctrl, &g_dac0_cfg);
if (FSP_SUCCESS != fsp_err)
{
return fsp_err;
}
// DAC启动
fsp_err = R_DAC_Start(&g_dac0_ctrl);
if (FSP_SUCCESS != fsp_err)
{
return fsp_err;
}
fsp_err = icu_initialize ();
if (FSP_SUCCESS != fsp_err)
{
return fsp_err;
}
fsp_err = gpt_initialize ();
#if 1
if (FSP_SUCCESS != fsp_err)
{
return fsp_err;
}
led_duty_cycle_update ();
#endif
/* Set baseline LED status */
g_board_status.led_intensity = 0;
g_board_status.led_frequency = 0;
R_GPT_PeriodSet(g_blinker.p_ctrl, g_pwm_rates[g_board_status.led_frequency]);
led_duty_cycle_update ();
s_duty = g_pwm_dcs[g_board_status.led_intensity];
/* Start the timers */
R_GPT_Start(g_blinker.p_ctrl);
R_GPT_Start(g_gpt_blue.p_ctrl);
return fsp_err;
}
void gpt_blinker_callback(timer_callback_args_t *p_args)
{
/* Void the unused params */
FSP_PARAMETER_NOT_USED(p_args);
// 计算正弦波
uint16_t dac_val = 0;
static double position = 0.0;
position += (PI / 30); // add 6° per cycle
if (position >= PI*2) // if angle bigger than 90°
position = 0.0;
dac_val = (uint16_t)((sin(position) + 1) / 2 * 4095);
// 通过DAC输出正弦波
R_DAC_Write(&g_dac0_ctrl, dac_val);
if (OFF == s_blueled_flashing)
{
s_blueled_flashing = ON;
}
else
{
s_blueled_flashing = OFF;
}
}
3. 进阶任务
》》》【Follow me第二季第3期】进阶任务《《《
test_fn dac_display_menu(void)
{
int8_t c = -1;
uint16_t wn_mcu_temp_f = 0;
uint16_t fr_mcu_temp_f = 0;
uint16_t wn_mcu_temp_c = 0;
uint16_t fr_mcu_temp_c = 0;
sprintf (s_print_buffer, "%s%s", gp_clear_screen, gp_cursor_home);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
sprintf (s_print_buffer, MODULE_NAME, g_selected_menu);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
wn_mcu_temp_f = g_board_status.temperature_f.whole_number;
fr_mcu_temp_f = g_board_status.temperature_f.mantissa;
wn_mcu_temp_c = g_board_status.temperature_c.whole_number;
fr_mcu_temp_c = g_board_status.temperature_c.mantissa;
sprintf (s_print_buffer, SUB_OPTIONS, FULL_NAME,
wn_mcu_temp_f, fr_mcu_temp_f, wn_mcu_temp_c, fr_mcu_temp_c,
g_dac_val);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
sprintf (s_print_buffer, MENU_RETURN_INFO);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
/* provide small delay so board_status should be up to date */
vTaskDelay (s_ticks_to_wait);
xEventGroupSetBits (g_update_console_event, STATUS_DAC_MONITOR);
}
4. 扩展任务
》》》【Follow me第二季第3期】扩展任务《《《
命令行菜单
test_fn dac_display_menu(void)
{
int8_t c = -1;
uint16_t wn_mcu_temp_f = 0;
uint16_t fr_mcu_temp_f = 0;
uint16_t wn_mcu_temp_c = 0;
uint16_t fr_mcu_temp_c = 0;
sprintf (s_print_buffer, "%s%s", gp_clear_screen, gp_cursor_home);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
sprintf (s_print_buffer, MODULE_NAME, g_selected_menu);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
wn_mcu_temp_f = g_board_status.temperature_f.whole_number;
fr_mcu_temp_f = g_board_status.temperature_f.mantissa;
wn_mcu_temp_c = g_board_status.temperature_c.whole_number;
fr_mcu_temp_c = g_board_status.temperature_c.mantissa;
sprintf (s_print_buffer, SUB_OPTIONS, FULL_NAME,
wn_mcu_temp_f, fr_mcu_temp_f, wn_mcu_temp_c, fr_mcu_temp_c,
g_dac_val);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
sprintf (s_print_buffer, MENU_RETURN_INFO);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
/* provide small delay so board_status should be up to date */
vTaskDelay (s_ticks_to_wait);
xEventGroupSetBits (g_update_console_event, STATUS_DAC_MONITOR);
uint32_t read_data_len = 0;
uint32_t save_len = 0;
while (CONNECTION_ABORT_CRTL != c)
{
c = input_from_console ();
if ((MENU_EXIT_CRTL == c) || (CONNECTION_ABORT_CRTL == c))
{
break;
}
else if ('s' == c)
{
g_dac_write_data_len = 0;
sprintf (s_print_buffer, "%s select: %c start save wave %s", gp_cursor_store, c, gp_cursor_restore);
print_to_console((void*)s_print_buffer);
}
else if ('t' == c)
{
int offset = sprintf (s_print_buffer, "%s select: %c stop save wave. \r\nsave data: \r\n\t", gp_cursor_store, c);
save_len = g_dac_write_data_len;
for (uint16_t i = 0; i < save_len; i++)
{
offset += sprintf (s_print_buffer + offset, "%d ", g_dac_adwrite_data_buff[i]);
}
sprintf (s_print_buffer + offset, " %s", gp_cursor_restore);
print_to_console((void*)s_print_buffer);
qspi_write(save_len * sizeof(uint16_t), g_dac_adwrite_data_buff);
}
else if ('p' == c)
{
sprintf (s_print_buffer, "%s select: %c get wave %s", gp_cursor_store, c, gp_cursor_restore);
print_to_console((void*)s_print_buffer);
qspi_read(&read_data_len, read_data_buff);
int offset = sprintf (s_print_buffer, "get %s length: %d \r\nGet data: \r\n\t", gp_cursor_store, read_data_len/2);
for (uint16_t i = 0; i < read_data_len / 2; i++)
{
offset += sprintf (s_print_buffer + offset, "%d ", read_data_buff[i]);
}
sprintf (s_print_buffer + offset, " %s", gp_cursor_restore);
print_to_console((void*)s_print_buffer);
}
}
xEventGroupClearBits (g_update_console_event, STATUS_DAC_MONITOR);
return (0);
}
缓存DAC值
void gpt_blinker_callback(timer_callback_args_t *p_args)
{
/* Void the unused params */
FSP_PARAMETER_NOT_USED(p_args);
uint16_t dac_val = 0;
static double position = 0.0;
position += (PI / 30); // add 6° per cycle
if (position >= PI*2) // if angle bigger than 90°
position = 0.0;
dac_val = (uint16_t)((sin(position) + 1) / 2 * 4095);
R_DAC_Write(&g_dac0_ctrl, dac_val);
if (OFF == s_blueled_flashing)
{
s_blueled_flashing = ON;
}
else
{
s_blueled_flashing = OFF;
}
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
BaseType_t xResult = pdFAIL;
if (g_dac_val != dac_val)
{
g_dac_val = dac_val;
/* Cast, as compiler will assume calc is int */
xResult = xEventGroupSetBitsFromISR(g_update_console_event, STATUS_DAC_OUTPUT_VAL, &xHigherPriorityTaskWoken);
/* Was the message posted successfully? */
if (pdFAIL != xResult)
{
/* If xHigherPriorityTaskWoken is now set to pdTRUE then a context
switch should be requested. The macro used is port specific and will
be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
the documentation page for the port being used. */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
g_dac_write_data_len = g_dac_write_data_len >= MAX_DAC_WRITE_BUFFER ? 0 : g_dac_write_data_len;
// save new data to buffer
g_dac_adwrite_data_buff[g_dac_write_data_len++] = g_dac_val;
}
}
SPI Flash写入
static uint32_t qspi_write(uint32_t data_size, uint8_t* data)
{
#if 0
fsp_err_t fsp_err;
uint32_t qspi_write_result = 0;
timer_status_t status = {};
fsp_err_t err = FSP_SUCCESS;
spi_flash_protocol_t current_spi_mode;
/* The comms mode is EXTENDED_SPI by default */
current_spi_mode = SPI_FLASH_PROTOCOL_EXTENDED_SPI;
/* initialise the QSPI, and change mode to that set in FSP */
err = qpi_init();
if (FSP_SUCCESS == err)
{
/* The comms mode has changed. So if recovering, this new mode required */
current_spi_mode = g_qspi_cfg.spi_protocol;
}
uint8_t * p_mem_addr;
/* Cast to req type */
p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS;
/* Erase Flash for one sector */
err = R_QSPI_Erase(&g_qspi_ctrl, p_mem_addr, SECTOR_SIZE);
if (FSP_SUCCESS != err)
{
sprintf(s_print_buffer, "R_QSPI_Erase Failed\r\n");
}
/* Cast to req type */
p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS;
/* Write data to QSPI Flash */
/* Each block begins one character shifted along the source text. To avoid regular striping in memory */
err = R_QSPI_Write(&g_qspi_ctrl, (uint8_t*)&data_size, p_mem_addr, PAGE_WRITE_SIZE);
if (FSP_SUCCESS != err)
{
sprintf(s_print_buffer, "R_QSPI_Write Failed\r\n");
}
/* close QSPI module */
deinit_qspi(current_spi_mode);
qspi_write_result = status.counter;
return (qspi_write_result);
#else
fsp_err_t fsp_err;
uint32_t qspi_write_result = 0;
timer_status_t status = {};
fsp_err_t err = FSP_SUCCESS;
spi_flash_protocol_t current_spi_mode;
if (data == NULL)
{
err = FSP_ERR_NOT_ERASED;
return err;
}
/* Convert from kB */
uint32_t block_size = (data_size / 1024 + 1)*1024;
uint8_t* p_dma_read_buffer = pvPortMalloc(block_size);
if (NULL == p_dma_read_buffer)
{
HeapStats_t pxHeapStats;
vPortGetHeapStats(&pxHeapStats);
sprintf(s_print_buffer, "\r\nQSPI malloc operation Failed - Max free mem: %dbytes\r\n",
pxHeapStats.xSizeOfLargestFreeBlockInBytes);
/* Verification failed, perhaps the ERASE failed */
err = FSP_ERR_NOT_ERASED;
}
memcpy(p_dma_read_buffer, &data_size, sizeof(data_size));
memcpy(p_dma_read_buffer + sizeof(data_size), data, data_size);
/* The comms mode is EXTENDED_SPI by default */
current_spi_mode = SPI_FLASH_PROTOCOL_EXTENDED_SPI;
/* initialise the QSPI, and change mode to that set in FSP */
err = qpi_init();
if (FSP_SUCCESS == err)
{
/* The comms mode has changed. So if recovering, this new mode required */
current_spi_mode = g_qspi_cfg.spi_protocol;
}
uint32_t page_write_count = 0;
uint8_t * p_mem_addr;
/* Cast to req type */
p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS;
while (((page_write_count * SECTOR_SIZE) < block_size)
&& ( FSP_SUCCESS == err ) )
{
/* Erase Flash for one sector */
err = R_QSPI_Erase(&g_qspi_ctrl, p_mem_addr, SECTOR_SIZE);
if (FSP_SUCCESS != err)
{
sprintf(s_print_buffer, "R_QSPI_Erase Failed\r\n");
}
else
{
err = get_flash_status();
if (FSP_SUCCESS != err)
{
sprintf(s_print_buffer, "Failed to get status for QSPI operation\r\n");
}
/* Verify the erased block data */
uint32_t count;
for (count = 0; count < SECTOR_SIZE; count++ )
{
if (DEFAULT_MEM_VAL != p_mem_addr[count])
{
/* Verification failed, perhaps the ERASE failed */
err = FSP_ERR_NOT_ERASED;
}
}
}
p_mem_addr += SECTOR_SIZE;
page_write_count++;
}
/* Cast to req type */
p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS;
page_write_count = 0;
while (((page_write_count * PAGE_WRITE_SIZE) < block_size)
&& (FSP_SUCCESS == err))
{
if (FSP_SUCCESS == err)
{
/* Write data to QSPI Flash */
/* Each block begins one character shifted along the source text. To avoid regular striping in memory */
// err = R_QSPI_Write(&g_qspi_ctrl, &(qspi_source[page_write_count]), p_mem_addr, PAGE_WRITE_SIZE);
err = R_QSPI_Write(&g_qspi_ctrl, &(p_dma_read_buffer[page_write_count]), p_mem_addr, PAGE_WRITE_SIZE);
if (FSP_SUCCESS != err)
{
sprintf(s_print_buffer, "R_QSPI_Write Failed\r\n");
}
else
{
err = get_flash_status();
if (FSP_SUCCESS != err)
{
sprintf(s_print_buffer, "Failed to get status for QSPI operation\r\n");
}
}
}
p_mem_addr += PAGE_WRITE_SIZE;
page_write_count++;
}
/* close QSPI module */
deinit_qspi(current_spi_mode);
qspi_write_result = status.counter;
vPortFree(p_dma_read_buffer);
return (qspi_write_result);
#endif
}
SPI Flash读取
static uint32_t qspi_read(uint32_t* data_size, uint8_t* data)
{
#if 0
fsp_err_t fsp_err;
fsp_err_t err = FSP_SUCCESS;
uint32_t qspi_read_result = 0;
timer_status_t status = {};
spi_flash_protocol_t current_spi_mode;
uint8_t * p_mem_addr;
/* The comms mode of the FLASH device is EXTENDED_SPI by default */
current_spi_mode = SPI_FLASH_PROTOCOL_EXTENDED_SPI;
/* initialise the QSPI, and change mode to that set in FSP */
err = qpi_init();
if (FSP_SUCCESS == err)
{
/* The comms mode has changed. So if recovering, this new mode required */
current_spi_mode = g_qspi_cfg.spi_protocol;
}
/* cast to req type */
p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS;
memcpy(data_size, p_mem_addr, 1);
sprintf(s_print_buffer, "save length: %d", *data_size);
print_to_console((void*)s_print_buffer);
/* close QSPI module */
deinit_qspi(current_spi_mode);
qspi_read_result = status.counter;
return (qspi_read_result);
#else
fsp_err_t fsp_err;
fsp_err_t err = FSP_SUCCESS;
uint32_t qspi_read_result = 0;
timer_status_t status = {};
spi_flash_protocol_t current_spi_mode;
uint8_t * p_dma_read_buffer;
uint32_t page_read_count;
uint8_t * p_mem_addr;
/* Convert from kB */
uint32_t block_size = 2*1024;
p_dma_read_buffer = pvPortMalloc(block_size);
if (NULL == p_dma_read_buffer)
{
HeapStats_t pxHeapStats;
vPortGetHeapStats(&pxHeapStats);
sprintf(s_print_buffer, "\r\nQSPI malloc operation Failed - Max free mem: %dbytes\r\n",
pxHeapStats.xSizeOfLargestFreeBlockInBytes);
/* Verification failed, perhaps the ERASE failed */
err = FSP_ERR_NOT_ERASED;
}
/* The comms mode of the FLASH device is EXTENDED_SPI by default */
current_spi_mode = SPI_FLASH_PROTOCOL_EXTENDED_SPI;
/* initialise the QSPI, and change mode to that set in FSP */
err = qpi_init();
if (FSP_SUCCESS == err)
{
/* The comms mode has changed. So if recovering, this new mode required */
current_spi_mode = g_qspi_cfg.spi_protocol;
}
page_read_count = 0;
/* cast to req type */
p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS;
*data_size = *((uint32_t*)p_mem_addr);
memcpy(data, p_mem_addr + 4, *data_size);
while (((page_read_count * PAGE_WRITE_SIZE) < block_size)
&& (FSP_SUCCESS == err))
{
/* Verify the written data */
/* Each block begins one character shifted along the source text. To avoid regular striping in memory */
if ((fsp_err_t) (memcmp (p_mem_addr, &(qspi_source[page_read_count]), PAGE_WRITE_SIZE)) != FSP_SUCCESS)
{
err = FSP_ERR_NOT_ERASED;
sprintf(s_print_buffer, "\r\nQSPI operation Failed -> Data read does not match with written data\r\n");
}
p_mem_addr += PAGE_WRITE_SIZE;
page_read_count++;
}
qspi_read_result = status.counter;
vPortFree(p_dma_read_buffer);
return (qspi_read_result);
#endif
}
三、任务视频
》》》视频链接《《《
四、任务代码
》》》示例代码链接《《《
五、活动心得
很高兴能够参加本次的活动,最近工作比较忙,拖到最后完成了各个任务。这个开发板资源还是非常的丰富,然后SDK的demo也比较完善,很多值得学习的地方。后续再项目应用中也尝试使用RA系列的芯片。同时也会更过关注这个RA低功耗一些相关的MCU上面。
|