HELLO_GCC

  • 2024-12-15
  • 发表了主题帖: 【Follow me第二季第3期】任务汇总

    本贴是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 入门任务 《《《 流程图   主要代码片段 控制蓝灯blink的定时器回调函数 void gpt_blue_callback(timer_callback_args_t * p_args) { /* Void the unused params */ FSP_PARAMETER_NOT_USED(p_args); switch (s_blueled_flashing) { case ON: { if ((s_intense++ ) < s_duty) { TURN_BLUE_ON } else { TURN_BLUE_OFF } if (s_intense >= 100) { s_intense = 0; s_duty = g_pwm_dcs[g_board_status.led_intensity]; } break; } default: { TURN_BLUE_OFF s_intense = 0; s_duty = g_pwm_dcs[g_board_status.led_intensity]; } } } 按键控制闪灯亮度的回调函数 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上面。

  • 上传了资料: 【Follow me第二季第3期】任务汇总-代码

  • 发表了主题帖: 【Follow me第二季第3期】扩展任务

    本贴主要是记录最后一个扩展任务:设计一个类似信号发生器功能的例程。可在示例程序上修改。通过命令或按键,设置DAC输出波形,可通过flash存储历史波形等信息。 主要是实现了前面任务中的DAC的正弦波输出,并且将输出的DAC值,也就是波形保存在SQPI Flash里面。掉电之后,也可以正常查看上次保存的记录。   1. 打开进阶任务的示例工程,然后再新增加的DAC输出的菜单中,增加三个指令,接受来之串口终端的输入指令: 's': 开始记录DAC波形数据,'t': 停止记录DAC波形数据,并且保存再Flash中,'p': 读取Flash中保存的DAC波形数据。     2. 使用全局变量缓存当前开始记录的波形: 3. 增加QSPI Flash的数据保存接口和数据读取接口        4. 原有功能中,可以通过按键控制DAC输出波形的频率。     5. 完成相关代码之后,编译下载到开发板。通过xshell窗口终端工具,连接到开发板debug串口。     6. 输入7,再输入s,开始记录数据,按下t,结束保存数据,并且保存到flash;再按下p,输出保存再flash的数据。       以上基本的正弦波信号发生器功能完成,并且可以保存历史的波形数据,以及波形数据的输出。  

  • 发表了主题帖: 【Follow me第二季第3期】进阶任务

    本贴主要记录进阶任务:示例程序中新增命令打印信息。主要是参考demo示例工程中的Kit imformation增加一个DAC实时输出的Value. 具体操作步骤如下: 1. 在示例工程中,找到菜单任务的总入口:main.c文件的main函数。-》》程序员都懂的。。。   2. 找到menu菜单具体输出的地方:   3. 可以找到菜单全局变量的显示和具体入口函数s_menu_items。在这个全局变量新增加注册一个命令行: {"DAC monitor", dac_display_menu}, 4. 参考kis_display_menu函数实现dac_display_menu,并且增加submenu的显示信息,具体如下:包括问题显示和Dac实时输出的数据。        5. 在DAC波形的任务中,增加了一个全局变量保存实时输出的dac value,并且增加两个event标志位,用于刷新DAC的结果和捕获当前子菜单的输入。   6. 在Dac输出地方进行全局数据更新,注意在回调函数里面需要使用带_ISR后缀的接口,否则会出现系统异常。   7. 在刷新显示任务中,收到STATUS_DAC_OUTPUT_VAL标志位event的地方,进行显示的刷新,然后再清除标志位。     8. 以上功能实现已经完成,编译之后,下载到开发板。使用xshell连接开发板的输出串口。可以看到新增加了一个命令行。   9. 输入7,进入子菜单,可以看到实时刷新的温度和DAC的输出。   以上进阶任务就完成了。

  • 发表了主题帖: 【Follow me第二季第3期】基础任务

    本贴主要是基础任务:“quad-spi flash和octo-spi flash配置及读写速度测试” 和 “DAC配置生成波形及性能测试”。 基本上按照培训的视频步骤,在【ra-fsp-examples-5.6.0.example.2】example例程里面已经实现了该功能。 具体操作步骤如下: 一、quad-spi flash和octo-spi flash配置及读写速度测试 1. 打开e2studio,按照入门的操作,找到Flash测试的串口终端入口函数:ext_display_menu  2. 在红色框选的地方就是ospi和qspi读写测试的函数    3. 编译程序然后在开发板上运行,通过xshell串口工具查看,输入测试的block size, 64kbytes,得到如下结果:     上述结果可以看到,OSPI的写入速度是QSPI的2倍左右,读取速度是6倍左右。   二、DAC配置生成波形及性能测试 1. 在demo工程中,选择configureation.xml配置文件,在Hal/Common Thread中增加一个新的Stacks  2. 选择Analog --> DAC    3. 配置新增加的DAC的属性,主要是输出引脚的选择   4. 此时可以发现配置DAC0的引脚P014有冲突,可以看到具体冲突的选择功能为ADC0       5. 将冲突的ADC0 关闭,配置文件就没有报错了。   6. 在common_init在函数入口,增加DAC的初始化和使能。     7. demo的blue led 闪烁频率控制回调函数里面,增加DAC正弦波输出的函数。   8. 编译执行,然后下载到开发板,打开示波器,将示波器的通道2接入到开发板的P014,注意共地。可以看到输出的波形。     

  • 加入了学习《【Follow me第二季第3期】EK_RA6M5汇总提交视频》,观看 【Follow me第二季第3期】EK_RA6M5汇总提交视频

  • 2024-12-14
  • 加入了学习《Follow me 第二季第3期成果视频》,观看 成果展示

  • 2024-12-12
  • 加入了学习《FollowMe 第二季:3 - EK_RA6M5 开发板入门》,观看 EK-RA6M5 开发板入门

  • 2024-12-11
  • 加入了学习《【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器》,观看 【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器

  • 加入了学习《Follow me第二季第3期演示视频》,观看 Follow me第二季第3期演示视频

  • 2024-10-28
  • 发表了主题帖: 【Follow me第二季第3期】 EK-RA6M5 入门任务

    本帖最后由 HELLO_GCC 于 2024-12-15 12:18 编辑         很幸运,获得了Digikey的Follow me活动入围通知,再次表示非常感谢!下单购买了EK-RA6M5开发套件,后面就是漫长的等待时间了,等了几天拿到开发板。                  接着就是开始搭建开发环境、熟悉开发板的相关规格和外设资料,以及基本的功能验证,具体如下。   一、开发环境搭建         1. RA的开发编译环境是多样化的,工具链可以在活动入口地址找到:https://github.com/renesas/fsp/releases/tag/v5.5.0           2. 由于以前开发做嵌入式开发使用过eclipse,并且自带图形界面工具,非常便于开发。因此,我就选择了官方的:e2s,具体下载地址为:https://github.com/renesas/fsp/releases/download/v5.5.0/setup_fsp_v5_5_0_e2s_v2024-07.exe  。                  3. 接下来就是一步一步往下进行安装e2studio,如果提示安装驱动,一并安装了。完成之后,就是熟悉的Eclipse界面了。                    4. 用套件里面的MicroUSB线,连接到开发板的Debug1口,上电,可以看到LED1闪烁了。         5. 在设备管理器里面,已经识别到开发板自带的Jlink 调试器了。            二、Demo工程调试         1. 新建Demo工程                    2. 输入项目名称,进入下一步                    3. 选择FSP版本号,开发板类型 EK-RA6M5,以及交叉编译工具链和Debug工具(由于板载了Jlink,就直接选择Jlink ARM工具)                               4. 由于是下载到开发板上的,需要选择可执行文件。这里暂时先不用RTOS操作系统。                    5. 选择默认的Blink工程,然后就创建完成了。                    6. 这下工程就创建完成了,熟悉的main函数又来了。                    先编译一下,看下有没有报错。                    在最下方看到,0 errors 0 warnings.                    7. 那就开始编译下载调试吧,点击那个绿色的小bug                                          8. 这下就进入到调试界面了,点击两三下这个下一步,就可以开始看到Blink的效果了。                       三、示例程序 1. 导入ra-fsp-examples-5.6.0.example.2文件的示例程序,具体路径如下:        2. 打开e2studio,导入工程     4. 选择demo文件夹     5. 打开配置界面   6. 选择blink的定时器配置,可以看到回调函数gpt_blinker_callback     7. 可以看到蓝色灯控制的函数逻辑的回调函数 8. 最后编译程序下载到开发板,通过按键1和按键2可以控制灯光频率和亮度,在调试监控的界面可以看到按键按下时的频率和亮度变化。    9. demo的blink,按键功能就完成了。

  • 2024-10-23
  • 加入了学习《Follow me 第二季第2期汇总的视频》,观看 Follow me 第二季第2期汇总的视频

  • 加入了学习《动手学深度学习V2》,观看 预告

最近访客

< 1/1 >

统计信息

已有5人来访过

  • 芯积分:30
  • 好友:--
  • 主题:5
  • 回复:1

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言