From 377c31cdc8f1f3c71fe85645a4aae8b8333cd936 Mon Sep 17 00:00:00 2001 From: zhangzheng <1358745329@qq.com> Date: Tue, 11 Mar 2025 19:29:59 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9B=86=E6=88=90ymodem(=E6=9A=82=E6=9C=AAcesh?= =?UTF-8?q?i)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 2 +- mkrtos_knl/knl/thread_knl.c | 4 - mkrtos_user/server/init/src/test/mutex_test.c | 5 +- mkrtos_user/user/app/CMakeLists.txt | 1 + mkrtos_user/user/app/Ymodem/CMakeLists.txt | 64 ++ mkrtos_user/user/app/Ymodem/armv7_8m/link.lds | 124 +++ mkrtos_user/user/app/Ymodem/heap_stack.c | 19 + mkrtos_user/user/app/Ymodem/main.c | 8 + .../user/app/Ymodem/porting/ymodem_export.c | 265 +++++++ .../user/app/Ymodem/porting/ymodem_export.h | 56 ++ mkrtos_user/user/app/Ymodem/readme.md | 37 + mkrtos_user/user/app/Ymodem/source/common.h | 8 + mkrtos_user/user/app/Ymodem/source/ymodem.c | 726 ++++++++++++++++++ mkrtos_user/user/app/Ymodem/source/ymodem.h | 78 ++ .../user/app/Ymodem/source/ymodem_menu.c | 186 +++++ .../user/app/Ymodem/source/ymodem_menu.h | 43 ++ .../user/app/Ymodem/source/ymodem_util.c | 264 +++++++ .../user/app/Ymodem/source/ymodem_util.h | 67 ++ 18 files changed, 1951 insertions(+), 6 deletions(-) create mode 100644 mkrtos_user/user/app/Ymodem/CMakeLists.txt create mode 100644 mkrtos_user/user/app/Ymodem/armv7_8m/link.lds create mode 100644 mkrtos_user/user/app/Ymodem/heap_stack.c create mode 100644 mkrtos_user/user/app/Ymodem/main.c create mode 100644 mkrtos_user/user/app/Ymodem/porting/ymodem_export.c create mode 100644 mkrtos_user/user/app/Ymodem/porting/ymodem_export.h create mode 100644 mkrtos_user/user/app/Ymodem/readme.md create mode 100644 mkrtos_user/user/app/Ymodem/source/common.h create mode 100644 mkrtos_user/user/app/Ymodem/source/ymodem.c create mode 100644 mkrtos_user/user/app/Ymodem/source/ymodem.h create mode 100644 mkrtos_user/user/app/Ymodem/source/ymodem_menu.c create mode 100644 mkrtos_user/user/app/Ymodem/source/ymodem_menu.h create mode 100644 mkrtos_user/user/app/Ymodem/source/ymodem_util.c create mode 100644 mkrtos_user/user/app/Ymodem/source/ymodem_util.h diff --git a/TODO.md b/TODO.md index ef28a9a33..82576228b 100644 --- a/TODO.md +++ b/TODO.md @@ -15,7 +15,7 @@ * [x] TTY驱动支持 * [x] 内核二值信号量支持优先级反转(优先级继承协议)。 * [ ] FPU完整支持,fastipc FPU支持 -* [ ] 文件系统&网络协议栈完善自动删除支持(文件描述符自动管理库) +* [ ] 文件系统 & 网络协议栈完善自动删除支持(文件描述符自动管理库) * [ ] 线程占用率统计 * [ ] procfs支持 * [ ] 新进程中env支持 diff --git a/mkrtos_knl/knl/thread_knl.c b/mkrtos_knl/knl/thread_knl.c index b1a86254d..d1a9c2556 100755 --- a/mkrtos_knl/knl/thread_knl.c +++ b/mkrtos_knl/knl/thread_knl.c @@ -291,10 +291,6 @@ bool_t task_knl_kill(thread_t *kill_thread, bool_t is_knl) { // 还原栈和usp TODO: arch相关的 thread_user_pf_restore(kill_thread, (void *)arch_get_user_sp()); - // umword_t *cur_pf = (umword_t *)(arch_get_user_sp()) - 8; - // cur_pf[5] = (umword_t)(thread_get_bind_task(kill_thread)->mm_space.mm_block); - // register volatile umword_t r9 asm("r9"); - // r9 = (umword_t)(thread_get_bind_task(kill_thread)->mm_space.mm_block); mpu_switch_to_task(thread_get_bind_task(kill_thread)); ref_counter_dec_and_release(&task->ref_cn, &task->kobj); reset_ram = TRUE; diff --git a/mkrtos_user/server/init/src/test/mutex_test.c b/mkrtos_user/server/init/src/test/mutex_test.c index f82062870..360c2013f 100644 --- a/mkrtos_user/server/init/src/test/mutex_test.c +++ b/mkrtos_user/server/init/src/test/mutex_test.c @@ -18,7 +18,7 @@ static u_mutex_t mutex_lock; static int test_cn; static __attribute__((optimize(0))) void hard_sleep(void) { - int i = 99999999; + volatile int i = 999999999; while(i--); } static void *thread_th1(void *arg) @@ -52,6 +52,9 @@ static void *thread_th3(void *arg) u_mutex_unlock(&mutex_lock); return NULL; } +/** + * 测试优先级继承是否生效 + */ static void u_mutex_test(CuTest *tc) { obj_handler_t mutex_hd; diff --git a/mkrtos_user/user/app/CMakeLists.txt b/mkrtos_user/user/app/CMakeLists.txt index 6bef59d15..707d9aff1 100644 --- a/mkrtos_user/user/app/CMakeLists.txt +++ b/mkrtos_user/user/app/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory(tinycc-arm-thumb) add_subdirectory(test) add_subdirectory(test2) add_subdirectory(vi) +add_subdirectory(Ymodem) add_subdirectory(binutils-2.33.1) # add_subdirectory(share_lib_test) # add_subdirectory(share_lib_test2) diff --git a/mkrtos_user/user/app/Ymodem/CMakeLists.txt b/mkrtos_user/user/app/Ymodem/CMakeLists.txt new file mode 100644 index 000000000..8fdd9fd26 --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/CMakeLists.txt @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 3.13) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ") +file( + GLOB deps + *.c + source/*.c + porting/*.c +) + +add_executable( + ym.elf + ${deps} + ${START_SRC} +) +target_link_libraries( + ym.elf + PUBLIC + -Bstatic + ${LIBC_NAME} + --whole-archive + ${START_LIB} + libc_be + sys + sys_util + sys_svr + --no-whole-archive + ${GCC_LIB_PATH}/libgcc.a +) +target_include_directories( + ym.elf + PUBLIC + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys/inc + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys_svr/inc + + ${CMAKE_CURRENT_SOURCE_DIR}/ + ${CMAKE_CURRENT_SOURCE_DIR}/source + ${CMAKE_CURRENT_SOURCE_DIR}/porting +) +add_dependencies( + ym.elf + ${START_LIB} + sys + sys_util +) +set_target_properties( + ym.elf PROPERTIES LINK_FLAGS + "-T ${CMAKE_CURRENT_LIST_DIR}/${ARCH_NAME}/link.lds ${CORTEX_M_LINK_FLAGS} --gc-section -no-dynamic-linker " + #--no-warn-rwx-segments +) +add_custom_target( + ym_dump ALL + COMMAND + ${CMAKE_OBJCOPY} -O binary -S ym.elf ym.bin + COMMAND + ${CMAKE_SIZE} ym.elf + COMMAND + ${CMAKE_COMMAND} -E copy ym.bin ${CMAKE_SOURCE_DIR}/build/output/cpio/ym + COMMAND + cp ym.elf ${CMAKE_SOURCE_DIR}/build/output/ym.elf +) + +add_dependencies(ym_dump ym.elf) + \ No newline at end of file diff --git a/mkrtos_user/user/app/Ymodem/armv7_8m/link.lds b/mkrtos_user/user/app/Ymodem/armv7_8m/link.lds new file mode 100644 index 000000000..34fdd0c60 --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/armv7_8m/link.lds @@ -0,0 +1,124 @@ +ENTRY(_start_) + +SECTIONS +{ + .text : { + . = ALIGN(4); + __text_start__ = .; + KEEP(*(.first)) + *(.text) + *(.text.*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(SORT(.rodata.*)) + *(.rodata) + + KEEP(*(.eh_frame*)) + + . = ALIGN(4); + __rel_start__ = .; + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + __rel_end__ = .; + } + .ARM.exidx : { + . = ALIGN(4); + __exdix_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + /* This is used by the startup in order to initialize the .data secion */ + __exdix_end = .; + } + + .permissions_table : { + . = ALIGN(4); + __permissions_table_start__ = .; + KEEP(*(.permissions_table)) + __permissions_table_end__ = .; + } + + + PROVIDE(__ram_size__ = __bss_end__ - __data_start__); + .data : { + . = ALIGN(4); + __data_start__ = .; + __got_start__ = .; + *(.got) + __got_end__ = .; + . = ALIGN(4); + *(.data) + *(.data.*) + + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + . = ALIGN(4); + _shell_command_start = .; + KEEP(*(shellCommand)) + _shell_command_end = .; + + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + } + + PROVIDE(__heap_size__ = __heap_end__ - __heap_start__); + PROVIDE(__stack_size__ = __stack_end__ - __stack_start__); + .bss : { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + __bss_start__ = .; + *(.bss) + *(COMMON) + + . = ALIGN(4); + __heap_start__ = .; + KEEP(*(.bss.heap)) + __heap_end__ = .; + + . = ALIGN(4); + __stack_start__ = .; + KEEP(*(.bss.stack)) + __stack_end__ = .; + + *(.bss.*) + /* This is used by the startup in order to initialize the .bss secion */ + . = ALIGN(4); + __bss_end__ = .; + } + _end = .; +} diff --git a/mkrtos_user/user/app/Ymodem/heap_stack.c b/mkrtos_user/user/app/Ymodem/heap_stack.c new file mode 100644 index 000000000..58f523331 --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/heap_stack.c @@ -0,0 +1,19 @@ +#include + +#define HEAP_SIZE (512) +#define STACK_SIZE (1024 * 3) + +#if defined(__CC_ARM) +#define HEAP_ATTR SECTION("HEAP") __attribute__((zero_init)) +#define STACK_ATTR SECTION("STACK") __attribute__((zero_init)) +#elif defined(__GNUC__) +#define HEAP_ATTR __attribute__((__section__(".bss.heap"))) +#define STACK_ATTR __attribute__((__section__(".bss.stack"))) +#elif defined(__IAR_SYSTEMS_ICC__) +#define HEAP_ATTR +#define STACK_ATTR +#endif + +__attribute__((used)) HEAP_ATTR static char _____heap_____[HEAP_SIZE]; +__attribute__((used)) STACK_ATTR static char _____stack_____[STACK_SIZE]; +__attribute__((used)) umword_t _____mm_bitmap_____[ROUND(HEAP_SIZE, MK_PAGE_SIZE) / (sizeof(umword_t) * 8) + 1]; diff --git a/mkrtos_user/user/app/Ymodem/main.c b/mkrtos_user/user/app/Ymodem/main.c new file mode 100644 index 000000000..aaddf31ee --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/main.c @@ -0,0 +1,8 @@ + +#include "ymodem_export.h" + +int main(int argv, char *argc[]) +{ + Ymodem_Main_Entrance(); + return 0; +} \ No newline at end of file diff --git a/mkrtos_user/user/app/Ymodem/porting/ymodem_export.c b/mkrtos_user/user/app/Ymodem/porting/ymodem_export.c new file mode 100644 index 000000000..60ad2ca0f --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/porting/ymodem_export.c @@ -0,0 +1,265 @@ +/** + ****************************************************************************** + * @file STM32F0xx_IAP/src/common.c + * @author MCD Application Team + * @version V1.0.0 + * @date 29-May-2012 + * @brief Main program body + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +// #include "ymodem_port.h" +// #include "ff.h" +#include +#include +#include +#include +#include +#include +#include +/** @addtogroup STM32F0xx_IAP + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************** + * Porting APIs + ********************************************************************************/ +typedef enum { + TRANS_FILE = 0, + IAP_IMAGE = 1, +} YMODEM_ACTION_E; + +typedef struct { + int ymodem_tty_fd; + YMODEM_ACTION_E ymodem_action; + uint32_t ymodem_receive_supported_maxsize; + uint32_t ymodem_transmit_size; + + bool_t ymodem_file_inited; + uint32_t ymodem_file_total_size; + uint32_t ymodem_file_handled_size; + int ymodem_file_handle; + // uint8_t ymodem_file_tmppath[128]; +} YMODEM_DATA_T; + +static YMODEM_DATA_T s_ymodem_data; +static void tty_init(void) +{ + struct termios old_settings; + struct termios new_settings; + tcgetattr(STDIN_FILENO, &old_settings); + new_settings = old_settings; + new_settings.c_lflag &= ~(ICANON | ECHO); // 禁用规范模式和回显 + new_settings.c_cc[VMIN] = 1; // 读取的最小字符数 + new_settings.c_cc[VTIME] = 0; // 读取的超时时间(以10ms为单位) + tcsetattr(STDIN_FILENO, TCSANOW, &new_settings); +} +void ymodem_init(void) +{ + tty_init(); + memset(&s_ymodem_data, 0, sizeof(YMODEM_DATA_T)); + s_ymodem_data.ymodem_tty_fd = STDIN_FILENO; + + s_ymodem_data.ymodem_action = TRANS_FILE; + + switch (s_ymodem_data.ymodem_action) { + case TRANS_FILE: + s_ymodem_data.ymodem_receive_supported_maxsize = 1024 * 1024 * 5; + s_ymodem_data.ymodem_transmit_size = 0; + break; +#if 0 + case IAP_IMAGE: +#warning "MUST implement GOT transmit SIZE!" + s_ymodem_data.ymodem_receive_supported_maxsize = 1024 * 1024 * 5; + s_ymodem_data.ymodem_transmit_size = 0; + break; +#endif + default: + // Not supported + break; + } +} +uint32_t ymodem_get_receive_maxsize(void) +{ + return s_ymodem_data.ymodem_receive_supported_maxsize; +} + +uint32_t ymodem_get_transmit_size(void) +{ + return s_ymodem_data.ymodem_transmit_size; +} +#include +// 0 - success ; -1 - fail +int ymodem_recv_start_cb(const char *filename, const uint32_t filesize) +{ + // FRESULT fres; + int ret; + + switch (s_ymodem_data.ymodem_action) { + case TRANS_FILE: + ret = open(filename, O_RDWR | O_CREAT, 0777); + if (ret < 0) { + //logd("Ymodem Start: create file(%s) fail(%d)...\n", filename, ret); + return -1; + } else { + //logd("Ymodem Start: create file(%s) ok(%d)...\n", filename, ret); + + s_ymodem_data.ymodem_file_inited = TRUE; + s_ymodem_data.ymodem_file_total_size = filesize; + s_ymodem_data.ymodem_file_handled_size = 0; + s_ymodem_data.ymodem_file_handle = ret; + return 0; + } + // break; + + case IAP_IMAGE: + /* erase user application area */ + // FLASH_If_Erase(APPLICATION_ADDRESS); + + break; + + default: + // Not supported + break; + } + return -1; +} + +int ymodem_recv_processing_cb(const uint8_t *buffer, const uint32_t buff_size) +{ + int ret; + uint32_t to_write_size = 0; + uint32_t writted_size = 0; + + switch (s_ymodem_data.ymodem_action) { + case TRANS_FILE: + to_write_size = s_ymodem_data.ymodem_file_total_size - s_ymodem_data.ymodem_file_handled_size; + to_write_size = (buff_size > to_write_size) ? to_write_size : buff_size; + + ret = write(s_ymodem_data.ymodem_file_handle, buffer, to_write_size); + if (ret != to_write_size) { + //loge("Ymodem process: write file(%d - %d) fail(%d)...\n", to_write_size, writted_size, ret); + return -1; + } else { + s_ymodem_data.ymodem_file_handled_size += to_write_size; + // logi("Ymodem process: write file(%d/%d) ok(%d)...\n", s_ymodem_data.ymodem_file_handled_size, + // s_ymodem_data.ymodem_file_total_size, ret); + return 0; + } + // break; + + case IAP_IMAGE: + // if (FLASH_If_Write(&flashdestination, (uint32_t*) ramsource, (uint16_t) packet_length/4) == 0) + break; + + default: + // Not supported + break; + } + return -1; +} + +int ymodem_recv_end_cb(void) +{ + int fres; + // FILINFO fno; + + switch (s_ymodem_data.ymodem_action) { + case TRANS_FILE: + if (TRUE != s_ymodem_data.ymodem_file_inited) + return -1; + + fres = close(s_ymodem_data.ymodem_file_handle); + //logd("Ymodem End: close file res(%d)...\n", fres); +#if 0 + fres = stat((const TCHAR *)s_ymodem_data.ymodem_file_tmppath, &fno); + if (fres != RES_OK) { + logw("Get File Status Fail(%d)...\n", fres); + } else { + logi("Get File Status ok(%d), file size(%d) Bytes...\n", fres, fno.fsize); + } +#endif + s_ymodem_data.ymodem_file_handle = -1; + s_ymodem_data.ymodem_file_total_size = 0; + s_ymodem_data.ymodem_file_handled_size = 0; + s_ymodem_data.ymodem_file_inited = FALSE; + return 0; + // break; + + case IAP_IMAGE: + /* erase user application area */ + // FLASH_If_Erase(APPLICATION_ADDRESS); + + break; + + default: + // Not supported + break; + } + return -1; +} +/** + * @brief Test to see if a key has been pressed on the HyperTerminal + * @param key: The key pressed + * @retval 1: Correct + * 0: Error + */ +uint32_t SerialKeyPressed(uint8_t *key) +{ + int ret; + + ret = read(STDIN_FILENO, key, 1); + if (ret < 0) { + return 0; + } + return 1; +} +// fail - 0xff; success -other value +uint8_t SerialReadByte(void) +{ + int ret; + uint8_t byte; + + ret = read(STDIN_FILENO, &byte, 1); + if (ret < 0) { + return 0xff; + } + return byte; +} + +/** + * @brief Print a character on the HyperTerminal + * @param c: The character to be printed + * @retval None + */ +void SerialPutChar(uint8_t c) +{ + write(STDIN_FILENO, &c, 1); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/mkrtos_user/user/app/Ymodem/porting/ymodem_export.h b/mkrtos_user/user/app/Ymodem/porting/ymodem_export.h new file mode 100644 index 000000000..b57d5875c --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/porting/ymodem_export.h @@ -0,0 +1,56 @@ +/** + ****************************************************************************** + * @file STM32F0xx_IAP/inc/common.h + * @author MCD Application Team + * @version V1.0.0 + * @date 29-May-2012 + * @brief Header for main.c module + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +#ifndef __YMODEM_EXPORT_H__ +#define __YMODEM_EXPORT_H__ + +/******************************************************************************** + * The Public APIs * + ********************************************************************************/ +void Ymodem_Main_Entrance(void); + + + +/******************************************************************************** + * The Porting APIs Must Be Implemented * + ********************************************************************************/ +extern unsigned int SerialKeyPressed(unsigned char *key); +extern void SerialPutChar(unsigned char c); +extern unsigned char SerialReadByte(void); + +extern void ymodem_init(void); +extern unsigned int ymodem_get_receive_maxsize(void); +extern unsigned int ymodem_get_transmit_size(void); + +//0 - success ; -1 - fail +extern int ymodem_recv_start_cb(const char * filename, const unsigned int filesize); +extern int ymodem_recv_processing_cb(const unsigned char * buffer, const unsigned int buff_size); +extern int ymodem_recv_end_cb(void); + +#endif /* __YMODEM_EXPORT_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/mkrtos_user/user/app/Ymodem/readme.md b/mkrtos_user/user/app/Ymodem/readme.md new file mode 100644 index 000000000..f97eb9f1b --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/readme.md @@ -0,0 +1,37 @@ +#### About Source Code: + + - source : source code Of Ymodem Protocol Implemention + +```c +source -- + |_____ common.h : compile system header files needed to include + | + |_____ ymodem.c : protocol implemention + |_____ ymodem.h : header file of protocol implemention + | + |_____ ymodem_util.c/.h : Tool Functions + | + |_____ ymodem_menu.c/.h : man - machine interaction menu + +porting -- + | + |_____ ymodem_export.h : All porting APIs should be Implemented by USER for different System or For different Usuage + |_____ ymodem_export.c : a demo implemention for porting APIs, For reference only, compile error exist + +``` + + - porting : Porting file. porting APIs declare in ymodem_export.h, and ymodem_export.c is one implemention for Keil5/STM32. and compile errors exist + - keil : keil(v5) project, for STM32 + +--- + + +#### And Attention: + + - the origin source code is from Project\STM32F0xx_IAP Demo Project in ST.com + + - And you may read the blog-article to known more about Ymodem: [Ymodem Procotol Porting](https://nixlong.github.io/2017/08/14/svm/Ymodem%E5%8D%8F%E8%AE%AE%E7%A7%BB%E6%A4%8D/#more) + +--- + +By nix.long@126.com \ No newline at end of file diff --git a/mkrtos_user/user/app/Ymodem/source/common.h b/mkrtos_user/user/app/Ymodem/source/common.h new file mode 100644 index 000000000..e1706d1f1 --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/source/common.h @@ -0,0 +1,8 @@ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +/*System Include Files depended*/ +#include "stdint.h" +#include "string.h" + +#endif /*__COMMON_H__*/ diff --git a/mkrtos_user/user/app/Ymodem/source/ymodem.c b/mkrtos_user/user/app/Ymodem/source/ymodem.c new file mode 100644 index 000000000..e4c67e58d --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/source/ymodem.c @@ -0,0 +1,726 @@ +/** + ****************************************************************************** + * @file STM32F0xx_IAP/src/ymodem.c + * @author MCD Application Team + * @version V1.0.0 + * @date 29-May-2012 + * @brief Main program body + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +//#include "common.h" +#include "ymodem.h" +#include "ymodem_util.h" +#include "ymodem_export.h" + + +/** @addtogroup STM32F0xx_IAP + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +extern uint8_t FileName[]; + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief Receive byte from sender + * @param c: Character + * @param timeout: Timeout + * @retval 0: Byte received + * -1: Timeout + */ +static int32_t Receive_Byte (uint8_t *c, uint32_t timeout) +{ + while (timeout-- > 0) + { + if (SerialKeyPressed(c) == 1) + { + return 0; + } + } + return -1; +} + +/** + * @brief Send a byte + * @param c: Character + * @retval 0: Byte sent + */ +static uint32_t Send_Byte (uint8_t c) +{ + SerialPutChar(c); + return 0; +} + +/** + * @brief Update CRC16 for input byte + * @param CRC input value + * @param input byte + * @retval Updated CRC value + */ +uint16_t UpdateCRC16(uint16_t crcIn, uint8_t byte) +{ + uint32_t crc = crcIn; + uint32_t in = byte|0x100; + + do + { + crc <<= 1; + in <<= 1; + + if(in&0x100) + { + ++crc; + } + + if(crc&0x10000) + { + crc ^= 0x1021; + } + } while(!(in&0x10000)); + + return (crc&0xffffu); +} + +/** + * @brief Cal CRC16 for YModem Packet + * @param data + * @param length + * @retval CRC value + */ +uint16_t Cal_CRC16(const uint8_t* data, uint32_t size) +{ + uint32_t crc = 0; + const uint8_t* dataEnd = data+size; + + while(data0: packet length + * @retval 0: normally return + * -1: timeout or packet error + * 1: abort by user + */ +static int32_t Receive_Packet (uint8_t *data, int32_t *length, uint32_t timeout) +{ + uint16_t i, packet_size, computedcrc; + uint8_t c; + *length = 0; + if (Receive_Byte(&c, timeout) != 0) + { + return -1; + } + switch (c) + { + case SOH: + packet_size = PACKET_SIZE; + break; + case STX: + packet_size = PACKET_1K_SIZE; + break; + case EOT: + return 0; + case CA: + if ((Receive_Byte(&c, timeout) == 0) && (c == CA)) + { + *length = -1; + return 0; + } + else + { + return -1; + } + case ABORT1: + case ABORT2: + return 1; + default: + return -1; + } + *data = c; + for (i = 1; i < (packet_size + PACKET_OVERHEAD); i ++) + { + if (Receive_Byte(data + i, timeout) != 0) + { + return -1; + } + } + if (data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff)) + { + return -1; + } + + /* Compute the CRC */ + computedcrc = Cal_CRC16(&data[PACKET_HEADER], (uint32_t)packet_size); + /* Check that received CRC match the already computed CRC value + data[packet_size+3]<<8) | data[packet_size+4] contains the received CRC + computedcrc contains the computed CRC value */ + if (computedcrc != (uint16_t)((data[packet_size+3]<<8) | data[packet_size+4])) + { + /* CRC error */ + return -1; + } + + *length = packet_size; + return 0; +} + +/** + * @brief Receive a file using the ymodem protocol + * @param buf: Address of the first byte + * @retval The size of the file + */ +int32_t Ymodem_Receive (uint8_t *buf) +{ + uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr; + int32_t i, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0; + uint32_t flashdestination, ramsource; + + uint32_t YMODEM_MAX_SIZE = ymodem_get_receive_maxsize(); + + flashdestination = flashdestination; + ramsource = ramsource; +#if 0 + /* Initialize flashdestination variable */ + flashdestination = APPLICATION_ADDRESS; +#endif + + for (session_done = 0, errors = 0, session_begin = 0; ;) + { + for (packets_received = 0, file_done = 0, buf_ptr = buf; ;) + { + switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT)) + { + case 0: + errors = 0; + switch (packet_length) + { + /* Abort by sender */ + case - 1: + Send_Byte(ACK); + return 0; + + /* End of transmission */ + case 0: + Send_Byte(ACK); + file_done = 1; + break; + + /* Normal packet */ + default: + if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff)) + { + Send_Byte(NAK); + } + else + { + if (packets_received == 0) + { + /* Filename packet */ + if (packet_data[PACKET_HEADER] != 0) + { + /* Filename packet has valid data */ + for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);) + { + FileName[i++] = *file_ptr++; + } + FileName[i++] = '\0'; + for (i = 0, file_ptr ++; (*file_ptr != ' ') && (i < (FILE_SIZE_LENGTH - 1));) + { + file_size[i++] = *file_ptr++; + } + file_size[i++] = '\0'; + Str2Int(file_size, &size); + + /* Test the size of the image to be sent */ + /* Image size is greater than Flash size */ + if (size > (YMODEM_MAX_SIZE + 1)) + { + /* End session */ + Send_Byte(CA); + Send_Byte(CA); + return -1; + } + #if 0 + /* erase user application area */ + FLASH_If_Erase(APPLICATION_ADDRESS); + #else + //start fail + if(-1 == ymodem_recv_start_cb((char*)FileName, size)){ + /* End session */ + Send_Byte(CA); + Send_Byte(CA); + return -1; + } + #endif + Send_Byte(ACK); + Send_Byte(CRC16); + } + /* Filename packet is empty, end session */ + else + { + Send_Byte(ACK); + file_done = 1; + session_done = 1; + break; + } + } + /* Data packet */ + else + { + memcpy((uint8_t*)buf_ptr, (uint8_t*)packet_data + PACKET_HEADER, packet_length); + ramsource = (uint32_t)buf; + + /* Write received data in Flash */ + #if 0 + if (FLASH_If_Write(&flashdestination, (uint32_t*) ramsource, (uint16_t) packet_length/4) == 0) + #else + if(0 == ymodem_recv_processing_cb((const uint8_t *)buf, packet_length)) + #endif + { + Send_Byte(ACK); + } + else /* An error occurred while writing to Flash memory */ + { + /* End session */ + Send_Byte(CA); + Send_Byte(CA); + return -2; + } + } + packets_received ++; + session_begin = 1; + } + } + break; + + case 1: + Send_Byte(CA); + Send_Byte(CA); + return -3; + + default: + if (session_begin > 0) + { + errors ++; + } + if (errors > MAX_ERRORS) + { + Send_Byte(CA); + Send_Byte(CA); + return 0; + } + Send_Byte(CRC16); + break; + } + if (file_done != 0) + { + break; + } + } + if (session_done != 0) + { + break; + } + } + return (int32_t)size; +} + +/** + * @brief check response using the ymodem protocol + * @param buf: Address of the first byte + * @retval The size of the file + */ +int32_t Ymodem_CheckResponse(uint8_t c) +{ + return 0; +} + +/** + * @brief Prepare the first block + * @param timeout + * @retval None + */ +void Ymodem_PrepareIntialPacket(uint8_t *data, const uint8_t* fileName, uint32_t *length) +{ + uint16_t i, j; + uint8_t file_ptr[10]; + + /* Make first three packet */ + data[0] = SOH; + data[1] = 0x00; + data[2] = 0xff; + + /* Filename packet has valid data */ + for (i = 0; (fileName[i] != '\0') && (i < FILE_NAME_LENGTH);i++) + { + data[i + PACKET_HEADER] = fileName[i]; + } + + data[i + PACKET_HEADER] = 0x00; + + Int2Str (file_ptr, *length); + for (j =0, i = i + PACKET_HEADER + 1; file_ptr[j] != '\0' ; ) + { + data[i++] = file_ptr[j++]; + } + + for (j = i; j < PACKET_SIZE + PACKET_HEADER; j++) + { + data[j] = 0; + } +} + +/** + * @brief Prepare the data packet + * @param timeout + * @retval None + */ +void Ymodem_PreparePacket(uint8_t *SourceBuf, uint8_t *data, uint8_t pktNo, uint32_t sizeBlk) +{ + uint16_t i, size, packetSize; + uint8_t* file_ptr; + + /* Make first three packet */ + packetSize = sizeBlk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE; + size = sizeBlk < packetSize ? sizeBlk :packetSize; + if (packetSize == PACKET_1K_SIZE) + { + data[0] = STX; + } + else + { + data[0] = SOH; + } + data[1] = pktNo; + data[2] = (~pktNo); + file_ptr = SourceBuf; + + /* Filename packet has valid data */ + for (i = PACKET_HEADER; i < size + PACKET_HEADER;i++) + { + data[i] = *file_ptr++; + } + if ( size <= packetSize) + { + for (i = size + PACKET_HEADER; i < packetSize + PACKET_HEADER; i++) + { + data[i] = 0x1A; /* EOF (0x1A) or 0x00 */ + } + } +} + +/** + * @brief Transmit a data packet using the ymodem protocol + * @param data + * @param length + * @retval None + */ +void Ymodem_SendPacket(uint8_t *data, uint16_t length) +{ + uint16_t i; + i = 0; + while (i < length) + { + Send_Byte(data[i]); + i++; + } +} + +/** + * @brief Transmit a file using the ymodem protocol + * @param buf: Address of the first byte + * @retval The size of the file + */ +uint8_t Ymodem_Transmit (uint8_t *buf, const uint8_t* sendFileName, uint32_t sizeFile) +{ + uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD]; + uint8_t FileName[FILE_NAME_LENGTH]; + uint8_t *buf_ptr, tempCheckSum ; + uint16_t tempCRC, blkNumber; + uint8_t receivedC[2], CRC16_F = 0, i; + uint32_t errors = 0, ackReceived = 0, size = 0, pktSize; + + uint32_t YMODEM_TRANSMIT_SIZE = ymodem_get_transmit_size(); + + for (i = 0; i < (FILE_NAME_LENGTH - 1); i++) + { + FileName[i] = sendFileName[i]; + } + CRC16_F = 1; + + /* Prepare first block */ + Ymodem_PrepareIntialPacket(&packet_data[0], FileName, &sizeFile); + + do + { + /* Send Packet */ + Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER); + + /* Send CRC or Check Sum based on CRC16_F */ + if (CRC16_F) + { + tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE); + Send_Byte(tempCRC >> 8); + Send_Byte(tempCRC & 0xFF); + } + else + { + tempCheckSum = CalChecksum (&packet_data[3], PACKET_SIZE); + Send_Byte(tempCheckSum); + } + + /* Wait for Ack and 'C' */ + if (Receive_Byte(&receivedC[0], 1000000) == 0) + { + if (receivedC[0] == ACK) + { + /* Packet transfered correctly */ + ackReceived = 1; + } + } + else + { + errors++; + } + }while (!ackReceived && (errors < 0x0A)); + + if (errors >= 0x0A) + { + return errors; + } + buf_ptr = buf; + size = sizeFile; + blkNumber = 0x01; + + /* Here 1024 bytes package is used to send the packets */ + while (size) + { + /* Prepare next packet */ + Ymodem_PreparePacket(buf_ptr, &packet_data[0], blkNumber, size); + ackReceived = 0; + receivedC[0]= 0; + errors = 0; + do + { + /* Send next packet */ + if (size >= PACKET_1K_SIZE) + { + pktSize = PACKET_1K_SIZE; + + } + else + { + pktSize = PACKET_SIZE; + } + Ymodem_SendPacket(packet_data, pktSize + PACKET_HEADER); + /* Send CRC or Check Sum based on CRC16_F */ + if (CRC16_F) + { + tempCRC = Cal_CRC16(&packet_data[3], pktSize); + Send_Byte(tempCRC >> 8); + Send_Byte(tempCRC & 0xFF); + } + else + { + tempCheckSum = CalChecksum (&packet_data[3], pktSize); + Send_Byte(tempCheckSum); + } + + /* Wait for Ack */ + if (Receive_Byte(&receivedC[0], 1000000) == 0) + { + + if (receivedC[0] == ACK) + { + ackReceived = 1; + if (size > pktSize) + { + buf_ptr += pktSize; + size -= pktSize; + if (blkNumber == (YMODEM_TRANSMIT_SIZE/1024)) + { + return 0xFF; /* error */ + } + else + { + blkNumber++; + } + } + else + { + buf_ptr += pktSize; + size = 0; + } + } + } + else + { + errors++; + } + }while(!ackReceived && (errors < 0x0A)); + + /* Resend packet if NAK for a count of 10 else end of commuincation */ + if (errors >= 0x0A) + { + return errors; + } + + } + ackReceived = 0; + receivedC[0] = 0x00; + receivedC[1] = 0x00; + errors = 0; + do + { + Send_Byte(EOT); + /* Send (EOT); */ + /* Wait for Ack */ + receivedC[0] = SerialReadByte(); + if (receivedC[0] == ACK) + { + ackReceived = 1; + } + else + { + errors++; + } + + }while (!ackReceived && (errors < 0x0A)); + + if (errors >= 0x0A) + { + return errors; + } + + /* Last packet preparation */ + ackReceived = 0; + receivedC[0] = 0x00; + receivedC[1] = 0x00; + errors = 0; + + packet_data[0] = SOH; + packet_data[1] = 0; + packet_data [2] = 0xFF; + + for (i = PACKET_HEADER; i < (PACKET_SIZE + PACKET_HEADER); i++) + { + packet_data [i] = 0x00; + } + + do + { + /* Send Packet */ + Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER); + + /* Send CRC or Check Sum based on CRC16_F */ + tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE); + Send_Byte(tempCRC >> 8); + Send_Byte(tempCRC & 0xFF); + + /* Wait for Ack and 'C' */ + if (Receive_Byte(&receivedC[1], 1000000) == 0) + { + if (receivedC[1] == ACK) + { + /* Packet transfered correctly */ + ackReceived = 1; + } + } + else + { + errors++; + } + }while (!ackReceived && (errors < 0x0A)); + + /* Resend packet if NAK for a count of 10 else end of commuincation */ + if (errors >= 0x0A) + { + return errors; + } + receivedC[0] = 0x00; + do + { + Send_Byte(EOT); + /* Send (EOT); */ + /* Wait for Ack */ + if ((Receive_Byte(&receivedC[0], 1000000) == 0) && receivedC[0] == ACK) + { + ackReceived = 1; + } + + else + { + errors++; + } + /* Clear Overrun flag of the USART2 */ + //USART_ClearFlag(EVAL_COM1, USART_FLAG_ORE); + }while (!ackReceived && (errors < 0x0A)); + + if (errors >= 0x0A) + { + return errors; + } + return 0; /* file trasmitted successfully */ +} + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/mkrtos_user/user/app/Ymodem/source/ymodem.h b/mkrtos_user/user/app/Ymodem/source/ymodem.h new file mode 100644 index 000000000..03fe2f467 --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/source/ymodem.h @@ -0,0 +1,78 @@ +/** + ****************************************************************************** + * @file STM32F0xx_IAP/inc/ymodem.h + * @author MCD Application Team + * @version V1.0.0 + * @date 29-May-2012 + * @brief Header for main.c module + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef _YMODEM_H_ +#define _YMODEM_H_ + +#include "common.h" + +/* Includes ------------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +#define PACKET_SEQNO_INDEX (1) +#define PACKET_SEQNO_COMP_INDEX (2) + +#define PACKET_HEADER (3) +#define PACKET_TRAILER (2) +#define PACKET_OVERHEAD (PACKET_HEADER + PACKET_TRAILER) +#define PACKET_SIZE (128) +#define PACKET_1K_SIZE (1024) + +#define FILE_NAME_LENGTH (256) +#define FILE_SIZE_LENGTH (16) + +#define SOH (0x01) /* start of 128-byte data packet */ +#define STX (0x02) /* start of 1024-byte data packet */ +#define EOT (0x04) /* end of transmission */ +#define ACK (0x06) /* acknowledge */ +#define NAK (0x15) /* negative acknowledge */ +#define CA (0x18) /* two of these in succession aborts transfer */ +#define CRC16 (0x43) /* 'C' == 0x43, request 16-bit CRC */ + +#define ABORT1 (0x41) /* 'A' == 0x41, abort by user */ +#define ABORT2 (0x61) /* 'a' == 0x61, abort by user */ + +#define NAK_TIMEOUT (5000) +#define MAX_ERRORS (5) + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +int32_t Ymodem_Receive (uint8_t *); +uint8_t Ymodem_Transmit (uint8_t *,const uint8_t* , uint32_t ); +uint16_t UpdateCRC16(uint16_t crcIn, uint8_t byte); +uint16_t Cal_CRC16(const uint8_t* data, uint32_t size); +uint8_t CalChecksum(const uint8_t* data, uint32_t size); +int32_t Ymodem_CheckResponse(uint8_t c); +void Ymodem_PrepareIntialPacket(uint8_t *data, const uint8_t* fileName, uint32_t *length); +void Ymodem_PreparePacket(uint8_t *SourceBuf, uint8_t *data, uint8_t pktNo, uint32_t sizeBlk); +void Ymodem_SendPacket(uint8_t *data, uint16_t length); + +#endif /* _YMODEM_H_ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/mkrtos_user/user/app/Ymodem/source/ymodem_menu.c b/mkrtos_user/user/app/Ymodem/source/ymodem_menu.c new file mode 100644 index 000000000..33da118d4 --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/source/ymodem_menu.c @@ -0,0 +1,186 @@ +/** + ****************************************************************************** + * @file STM32F0xx_IAP/src/menu.c + * @author MCD Application Team + * @version V1.0.0 + * @date 29-May-2012 + * @brief Main program body + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "ymodem.h" +#include "ymodem_menu.h" +#include "ymodem_util.h" +#include "ymodem_export.h" + +/** @addtogroup STM32F0xx_IAP + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +uint32_t JumpAddress; +extern uint32_t UserMemoryMask; +uint32_t FlashProtection = 0; +uint8_t tab_1024[1024] = {0}; +uint8_t FileName[FILE_NAME_LENGTH]; + +/* Private function prototypes -----------------------------------------------*/ +void SerialDownload(void); +void SerialUpload(void); + + +// #warning "avoid errors" +#define APPLICATION_ADDRESS 0x08000000 +#define USER_FLASH_SIZE 1024 + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief Download a file via serial port + * @param None + * @retval None + */ +void SerialDownload(void) +{ + uint8_t Number[10] = {0}; + int32_t Size = 0; + + SerialPutString("Waiting for the file to be sent ... (press 'a' to abort)\n\r"); + Size = Ymodem_Receive(&tab_1024[0]); + ymodem_recv_end_cb(); + if (Size > 0) + { + SerialPutString("\n\n\r Download File Successfully!\n\r--------------------------------\r\n Name: "); + SerialPutString(FileName); + Int2Str(Number, Size); + SerialPutString("\n\r Size: "); + SerialPutString(Number); + SerialPutString(" Bytes\r\n"); + SerialPutString("--------------------------------\n"); + } + else if (Size == -1) + { + SerialPutString("\n\n\rThe file size is higher than the allowed space memory!\n\r"); + } + else if (Size == -2) + { + SerialPutString("\n\n\rVerification failed!\n\r"); + } + else if (Size == -3) + { + SerialPutString("\r\n\nAborted by user.\n\r"); + } + else + { + SerialPutString("\n\rFailed to receive the file!\n\r"); + } +} +#if 0 +/** + * @brief Upload a file via serial port. + * @param None + * @retval None + */ +void SerialUpload(void) +{ + uint8_t status = 0 ; + + SerialPutString("\n\n\rSelect Receive File\n\r"); + + if (GetKey() == CRC16) + { + /* Transmit the flash image through ymodem protocol */ + status = Ymodem_Transmit((uint8_t*)APPLICATION_ADDRESS, (const uint8_t*)"UploadedFlashImage.bin", USER_FLASH_SIZE); + + if (status != 0) + { + SerialPutString("\n\rError Occurred while Transmitting File\n\r"); + } + else + { + SerialPutString("\n\rFile uploaded successfully \n\r"); + } + } +} +#endif +/** + * @brief Display the Main Menu on HyperTerminal + * @param None + * @retval None + */ +void Ymodem_Main_Entrance(void) +{ + uint8_t key = 0; + + ymodem_init(); + SerialPutString("\r\n======================================================================"); + SerialPutString("\r\n= (C) COPYRIGHT 2012 STMicroelectronics ="); + SerialPutString("\r\n= ="); + SerialPutString("\r\n= MKRTOS In-Application Programming Application (Version 1.0.0) ="); + SerialPutString("\r\n= ="); + SerialPutString("\r\n= By MCD Application Team ="); + SerialPutString("\r\n======================================================================"); + SerialPutString("\r\n\r\n"); + + while (1) + { + SerialPutString("\r\n================== Ymodem Menu =========================\r\n\n"); + SerialPutString(" Download File from PC to Board ------- 1\r\n\n"); + // SerialPutString(" Upload File from Board to PC ------- 2\r\n\n"); + SerialPutString(" Exit Y-modem ------- 2\r\n\n"); + SerialPutString("==========================================================\r\n\n"); + + /* Receive key */ + key = GetKey(); + + if (key == 0x31) + { + /* Download user application in the Flash */ + SerialDownload(); + } + #if 0 + else if (key == 0x32) + { + /* Upload user application from the Flash */ + SerialUpload(); + } + #endif + else if (key == 0x32) /* execute the new program */ + { + SerialPutString("Exit Y-modem ....\r\n"); + break; + } + else + { + SerialPutString("Invalid Number ! ==> The number should be either 1, 2 or 3\r"); + } + } +} + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/mkrtos_user/user/app/Ymodem/source/ymodem_menu.h b/mkrtos_user/user/app/Ymodem/source/ymodem_menu.h new file mode 100644 index 000000000..c3f2420b6 --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/source/ymodem_menu.h @@ -0,0 +1,43 @@ +/** + ****************************************************************************** + * @file STM32F0xx_IAP/inc/menu.h + * @author MCD Application Team + * @version V1.0.0 + * @date 29-May-2012 + * @brief Header for main.c module + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MENU_H +#define __MENU_H + +/* Includes ------------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + + +#endif /* __MENU_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/mkrtos_user/user/app/Ymodem/source/ymodem_util.c b/mkrtos_user/user/app/Ymodem/source/ymodem_util.c new file mode 100644 index 000000000..655231930 --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/source/ymodem_util.c @@ -0,0 +1,264 @@ +/** + ****************************************************************************** + * @file STM32F0xx_IAP/src/common.c + * @author MCD Application Team + * @version V1.0.0 + * @date 29-May-2012 + * @brief Main program body + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "ymodem_util.h" +#include "ymodem_export.h" + + + +/******************************************************************************** + * ANSI-C APIs + ********************************************************************************/ + +/** + * @brief Get a key from the HyperTerminal + * @param None + * @retval The Key Pressed + */ +uint8_t GetKey(void) +{ + uint8_t key = 0; + + /* Waiting for user input */ + while (1) + { + if (SerialKeyPressed((uint8_t*)&key)) break; + } + return key; +} + +/** + * @brief Convert an Integer to a string + * @param str: The string + * @param intnum: The intger to be converted + * @retval None + */ +void Int2Str(uint8_t* str, int32_t intnum) +{ + uint32_t i, Div = 1000000000, j = 0, Status = 0; + + for (i = 0; i < 10; i++) + { + str[j++] = (intnum / Div) + 48; + + intnum = intnum % Div; + Div /= 10; + if ((str[j-1] == '0') & (Status == 0)) + { + j = 0; + } + else + { + Status++; + } + } +} + +/** + * @brief Convert a string to an integer + * @param inputstr: The string to be converted + * @param intnum: The intger value + * @retval 1: Correct + * 0: Error + */ +uint32_t Str2Int(uint8_t *inputstr, int32_t *intnum) +{ + uint32_t i = 0, res = 0; + uint32_t val = 0; + + if (inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X')) + { + if (inputstr[2] == '\0') + { + return 0; + } + for (i = 2; i < 11; i++) + { + if (inputstr[i] == '\0') + { + *intnum = val; + /* return 1; */ + res = 1; + break; + } + if (ISVALIDHEX(inputstr[i])) + { + val = (val << 4) + CONVERTHEX(inputstr[i]); + } + else + { + /* return 0, Invalid input */ + res = 0; + break; + } + } + /* over 8 digit hex --invalid */ + if (i >= 11) + { + res = 0; + } + } + else /* max 10-digit decimal input */ + { + for (i = 0;i < 11;i++) + { + if (inputstr[i] == '\0') + { + *intnum = val; + /* return 1 */ + res = 1; + break; + } + else if ((inputstr[i] == 'k' || inputstr[i] == 'K') && (i > 0)) + { + val = val << 10; + *intnum = val; + res = 1; + break; + } + else if ((inputstr[i] == 'm' || inputstr[i] == 'M') && (i > 0)) + { + val = val << 20; + *intnum = val; + res = 1; + break; + } + else if (ISVALIDDEC(inputstr[i])) + { + val = val * 10 + CONVERTDEC(inputstr[i]); + } + else + { + /* return 0, Invalid input */ + res = 0; + break; + } + } + /* Over 10 digit decimal --invalid */ + if (i >= 11) + { + res = 0; + } + } + + return res; +} + +/** + * @brief Get an integer from the HyperTerminal + * @param num: The inetger + * @retval 1: Correct + * 0: Error + */ +uint32_t GetIntegerInput(int32_t * num) +{ + uint8_t inputstr[16]; + + while (1) + { + GetInputString(inputstr); + if (inputstr[0] == '\0') continue; + if ((inputstr[0] == 'a' || inputstr[0] == 'A') && inputstr[1] == '\0') + { + SerialPutString("User Cancelled \r\n"); + return 0; + } + + if (Str2Int(inputstr, num) == 0) + { + SerialPutString("Error, Input again: \r\n"); + } + else + { + return 1; + } + } +} + + +/** + * @brief Print a string on the HyperTerminal + * @param s: The string to be printed + * @retval None + */ +void Serial_PutString(uint8_t *s) +{ + while (*s != '\0') + { + SerialPutChar(*s); + s++; + } +} + +/** + * @brief Get Input string from the HyperTerminal + * @param buffP: The input string + * @retval None + */ +void GetInputString (uint8_t * buffP) +{ + uint32_t bytes_read = 0; + uint8_t c = 0; + do + { + c = GetKey(); + if (c == '\r') + break; + if (c == '\b') /* Backspace */ + { + if (bytes_read > 0) + { + SerialPutString("\b \b"); + bytes_read --; + } + continue; + } + if (bytes_read >= CMD_STRING_SIZE ) + { + SerialPutString("Command string size overflow\r\n"); + bytes_read = 0; + continue; + } + if (c >= 0x20 && c <= 0x7E) + { + buffP[bytes_read++] = c; + SerialPutChar(c); + } + } + while (1); + SerialPutString(("\n\r")); + buffP[bytes_read] = '\0'; +} + + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/mkrtos_user/user/app/Ymodem/source/ymodem_util.h b/mkrtos_user/user/app/Ymodem/source/ymodem_util.h new file mode 100644 index 000000000..1e9b5b4c4 --- /dev/null +++ b/mkrtos_user/user/app/Ymodem/source/ymodem_util.h @@ -0,0 +1,67 @@ +/** + ****************************************************************************** + * @file STM32F0xx_IAP/inc/common.h + * @author MCD Application Team + * @version V1.0.0 + * @date 29-May-2012 + * @brief Header for main.c module + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __YMODEM_UTIL_H__ +#define __YMODEM_UTIL_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "common.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Constants used by Serial Command Line Mode */ +#define CMD_STRING_SIZE 128 + +/* Exported macro ------------------------------------------------------------*/ +/* Common routines */ +#define IS_AF(c) ((c >= 'A') && (c <= 'F')) +#define IS_af(c) ((c >= 'a') && (c <= 'f')) +#define IS_09(c) ((c >= '0') && (c <= '9')) +#define ISVALIDHEX(c) IS_AF(c) || IS_af(c) || IS_09(c) +#define ISVALIDDEC(c) IS_09(c) +#define CONVERTDEC(c) (c - '0') + +#define CONVERTHEX_alpha(c) (IS_AF(c) ? (c - 'A'+10) : (c - 'a'+10)) +#define CONVERTHEX(c) (IS_09(c) ? (c - '0') : CONVERTHEX_alpha(c)) + +#define SerialPutString(x) Serial_PutString((uint8_t*)(x)) + +/* Exported functions ------------------------------------------------------- */ +void Int2Str(uint8_t* str,int32_t intnum); +uint32_t Str2Int(uint8_t *inputstr,int32_t *intnum); +uint32_t GetIntegerInput(int32_t * num); +uint8_t GetKey(void); +void SerialPutChar(uint8_t c); +void Serial_PutString(uint8_t *s); +void GetInputString(uint8_t * buffP); + + + +#endif /* __YMODEM_UTIL_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/