diff options
author | Fredrik Thulin <fredrik@thulin.net> | 2016-05-15 10:42:23 +0200 |
---|---|---|
committer | Fredrik Thulin <fredrik@thulin.net> | 2016-05-15 10:43:03 +0200 |
commit | 9b73356f2831800d2328827998e1e5b2a1994b68 (patch) | |
tree | 194357028a78b8ef92e4914074c2b3c51df5b17b | |
parent | cc07ee6bfcf4721254145ef388196be82532fd4a (diff) |
add simple filetransfer poc
-rw-r--r-- | projects/cli-test/Makefile | 6 | ||||
-rw-r--r-- | projects/cli-test/cli-test.c | 57 | ||||
-rw-r--r-- | projects/cli-test/crc32.c | 62 | ||||
-rwxr-xr-x | projects/cli-test/filetransfer | 89 | ||||
-rw-r--r-- | stm-init.c | 2 | ||||
-rw-r--r-- | stm-uart.c | 11 | ||||
-rw-r--r-- | stm-uart.h | 5 |
7 files changed, 220 insertions, 12 deletions
diff --git a/projects/cli-test/Makefile b/projects/cli-test/Makefile index 1f1f890..d0fce70 100644 --- a/projects/cli-test/Makefile +++ b/projects/cli-test/Makefile @@ -1,11 +1,15 @@ TEST = cli-test +OBJS = crc32.o + +LIBCLI_DIR=/home/ft/work/others/libcli.arm + CFLAGS += -I$(LIBCLI_DIR) LIBS += $(LIBCLI_DIR)/libcli.a all: $(TEST:=.elf) -%.elf: %.o $(BOARD_OBJS) $(LIBS) +%.elf: %.o $(BOARD_OBJS) $(OBJS) $(LIBS) $(CC) $(CFLAGS) $^ -o $@ -T$(LDSCRIPT) -g -Wl,-Map=$*.map $(OBJCOPY) -O ihex $*.elf $*.hex $(OBJCOPY) -O binary $*.elf $*.bin diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index 2f246a5..0b54e7e 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -12,14 +12,6 @@ #define DELAY() HAL_Delay(250) -int cmd_show_cpuspeed(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - volatile uint32_t hclk; - - hclk = HAL_RCC_GetHCLKFreq(); - cli_print(cli, "HCLK: %li (%i MHz)", hclk, (int) hclk / 1000 / 1000); - return CLI_OK; -} void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf) { @@ -42,6 +34,50 @@ int uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf return (int) count; } +int cmd_show_cpuspeed(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + volatile uint32_t hclk; + + hclk = HAL_RCC_GetHCLKFreq(); + cli_print(cli, "HSE_VALUE: %li", HSE_VALUE); + cli_print(cli, "HCLK: %li (%i MHz)", hclk, (int) hclk / 1000 / 1000); + cli_print(cli, "SystemCoreClock: %li (%i MHz)", SystemCoreClock, (int) SystemCoreClock / 1000 / 1000); + return CLI_OK; +} + +extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len); + +int cmd_filetransfer(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + uint32_t filesize = 0, crc = 0, my_crc = 0, n = 4; + uint8_t buf[4]; + + cli_print(cli, "OK, write file size (4 bytes), data, CRC-32 (4 bytes)"); + + uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000); + cli_print(cli, "Filesize %li", filesize); + + while (filesize) { + if (filesize < n) { + n = filesize; + } + + uart_receive_bytes(STM_UART_MGMT, (void *) &buf, n, 1000); + filesize -= n; + my_crc = update_crc(my_crc, buf, n); + } + + uart_receive_bytes(STM_UART_MGMT, (void *) &crc, 4, 1000); + cli_print(cli, "CRC-32 %li", crc); + if (crc == my_crc) { + cli_print(cli, "CRC checksum MATCHED"); + } else { + cli_print(cli, "CRC checksum did NOT match"); + } + + return CLI_OK; +} + int embedded_cli_loop(struct cli_def *cli) { unsigned char c; @@ -109,6 +145,9 @@ main() struct cli_command cmd_show_cpuspeed_s = {(char *) "cpuspeed", cmd_show_cpuspeed, 0, (char *) "Show the speed at which the CPU currently operates", PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL}; + struct cli_command cmd_filetransfer_s = {(char *) "filetransfer", cmd_filetransfer, 0, + (char *) "Test file transfering", + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL}; char crlf[] = "\r\n"; uint8_t tx = 'A'; @@ -134,6 +173,8 @@ main() cli_register_command2(&cli, &cmd_show_s, NULL); cli_register_command2(&cli, &cmd_show_cpuspeed_s, &cmd_show_s); + cli_register_command2(&cli, &cmd_filetransfer_s, NULL); + HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_PORT, LED_GREEN, GPIO_PIN_SET); diff --git a/projects/cli-test/crc32.c b/projects/cli-test/crc32.c new file mode 100644 index 0000000..4d1a0bc --- /dev/null +++ b/projects/cli-test/crc32.c @@ -0,0 +1,62 @@ +/* Reference code from RFC1952. Not meant to be used outside test code. */ + +#include "stm32f4xx_hal.h" + + +/* Table of CRCs of all 8-bit messages. */ +unsigned long crc_table[256]; + +/* Flag: has the table been computed? Initially false. */ +int crc_table_computed = 0; + +/* Make the table for a fast CRC. */ +void make_crc_table(void) +{ + unsigned long c; + + int n, k; + for (n = 0; n < 256; n++) { + c = (unsigned long) n; + for (k = 0; k < 8; k++) { + if (c & 1) { + c = 0xedb88320L ^ (c >> 1); + } else { + c = c >> 1; + } + } + crc_table[n] = c; + } + crc_table_computed = 1; +} + +/* + Update a running crc with the bytes buf[0..len-1] and return + the updated crc. The crc should be initialized to zero. Pre- and + post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the caller. Usage example: + + unsigned long crc = 0L; + + while (read_buffer(buffer, length) != EOF) { + crc = update_crc(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ +uint32_t update_crc(uint32_t crc, uint8_t *buf, int len) +{ + unsigned long c = crc ^ 0xffffffffL; + int n; + + if (!crc_table_computed) + make_crc_table(); + for (n = 0; n < len; n++) { + c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); + } + return c ^ 0xffffffffL; +} + +/* Return the CRC of the bytes buf[0..len-1]. */ +unsigned long crc(unsigned char *buf, int len) +{ + return update_crc(0L, buf, len); +} diff --git a/projects/cli-test/filetransfer b/projects/cli-test/filetransfer new file mode 100755 index 0000000..92b117f --- /dev/null +++ b/projects/cli-test/filetransfer @@ -0,0 +1,89 @@ +#!/usr/bin/python + +import os +import sys +import time +import struct +import serial + +from binascii import crc32 + + +def _write(dst, data): + dst.write(data) + if len(data) == 4: + print("Wrote 0x{:02x}{:02x}{:02x}{:02x}".format(ord(data[0]), ord(data[1]), ord(data[2]), ord(data[3]))) + else: + print("Wrote {!r}".format(data)) + + +def _read(dst): + res = '' + while True: + x = dst.read(1) + if not x: + break + res += x + print ("Read {!r}".format(res)) + return res + + +def _execute(dst, cmd): + _write(dst, '\r') + prompt = _read(dst) + if prompt.endswith('Username: '): + _write(dst, 'ct\r') + prompt = _read(dst) + if prompt.endswith('Password: '): + _write(dst, 'ct\r') + prompt = _read(dst) + if not prompt.endswith('> '): + sys.stderr.write('Device does not seem to be ready for a file transfer (got {!r})\n'.format(prompt)) + return False + _write(dst, cmd + '\r') + response = _read(dst) + return response + +def send_file(filename, device='/dev/ttyUSB0', initiate=True): + s = os.stat(filename) + size = s.st_size + src = open(filename, 'rb') + + dst = serial.Serial(device, 115200, timeout=0.5) + + if initiate: + response = _execute(dst, 'filetransfer') + if 'OK' not in response: + sys.stderr.write('Device did not accept the filetransfer command (got {!r})\n'.format(response)) + return False + + # 1. Write size of file (4 bytes) + _write(dst, struct.pack('<I', size)) + _read(dst) + # 2. Write file contents while calculating CRC-32 + crc = 0 + while True: + data = src.read(1024) + if not data: + break + dst.write(data) + print("Wrote {!s} bytes".format(len(data))) + crc = crc32(data, crc) & 0xffffffff + # 3. Write CRC-32 (4 bytes) + _write(dst, struct.pack('<I', crc)) + _read(dst) + + src.close() + dst.close() + return True + + +if len(sys.argv) != 2: + sys.stderr.write('Syntax: {!s} filename\n'.format(sys.argv[0])) + sys.exit(1) + +if send_file(sys.argv[1]): + sys.exit(0) + +sys.exit(1) + @@ -87,7 +87,7 @@ static void MX_USART1_UART_Init(void) huart_mgmt.Init.StopBits = UART_STOPBITS_1; huart_mgmt.Init.Parity = UART_PARITY_NONE; huart_mgmt.Init.Mode = UART_MODE_TX_RX; - huart_mgmt.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart_mgmt.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS; //UART_HWCONTROL_NONE; huart_mgmt.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart_mgmt) != HAL_OK) { @@ -115,6 +115,17 @@ HAL_StatusTypeDef uart_send_bytes(enum stm_uart_port port, uint8_t *buf, size_t return HAL_ERROR; } +/* receive raw bytes */ +HAL_StatusTypeDef uart_receive_bytes(enum stm_uart_port port, uint8_t *buf, size_t len, uint32_t timeout) +{ + UART_HandleTypeDef *uart = _which_uart(port); + + if (uart) + return HAL_UART_Receive(uart, (uint8_t *) buf, (uint32_t) len, timeout); + + return HAL_ERROR; +} + /* Generalized routine to send binary, decimal, and hex integers. * This code is adapted from Chris Giese's printf.c */ @@ -37,8 +37,8 @@ #include "stm32f4xx_hal.h" -#define USART_MGMT_BAUD_RATE 9600 -#define USART_USER_BAUD_RATE 9600 +#define USART_MGMT_BAUD_RATE 115200 +#define USART_USER_BAUD_RATE 115200 enum stm_uart_port { STM_UART_USER, @@ -61,6 +61,7 @@ extern HAL_StatusTypeDef uart_send_string2(enum stm_uart_port port, const char * extern HAL_StatusTypeDef uart_send_number2(enum stm_uart_port port, uint32_t num, uint8_t digits, uint8_t radix); extern HAL_StatusTypeDef uart_send_bytes(enum stm_uart_port port, uint8_t *buf, size_t len); +extern HAL_StatusTypeDef uart_receive_bytes(enum stm_uart_port port, uint8_t *buf, size_t len, uint32_t timeout); #define uart_send_binary(num, bits) uart_send_number(num, bits, 2) #define uart_send_integer(num, digits) uart_send_number(num, digits, 10) |