From 425391a3a864572aa71b8dde0d0f4ad0aa3ea03b Mon Sep 17 00:00:00 2001 From: sys64738 Date: Sat, 19 Jun 2021 23:17:14 +0200 Subject: [PATCH] fun experiment ig --- CMakeLists.txt | 6 ++- bsp/rp2040/protocfg.h | 5 +- dmctl.py | 12 ++++- src/cdc_dynexec.c | 113 ++++++++++++++++++++++++++++++++++++++++++ src/dynexec.S | 43 ++++++++++++++++ src/main.c | 17 +++++++ src/protos.h | 3 ++ src/tusb_config.h | 1 + src/usb_descriptors.c | 16 ++++-- 9 files changed, 207 insertions(+), 9 deletions(-) create mode 100644 src/cdc_dynexec.c create mode 100644 src/dynexec.S diff --git a/CMakeLists.txt b/CMakeLists.txt index c2dc03e..2ed18e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,8 +33,8 @@ if(FAMILY STREQUAL "rp2040") family_initialize_project(PROJECT ${CMAKE_CURRENT_LIST_DIR}) # calls pico_sdk_init() #pico_sdk_init() - #pico_set_program_name(${PROJECT} "${PROJECT}") - #pico_set_program_version(${PROJECT} "0.1") + #pico_set_program_name(PROJECT "${PROJECT}") + #pico_set_program_version(PROJECT "0.1") add_executable(${PROJECT}) @@ -64,6 +64,8 @@ target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/tempsensor.c ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/unique.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_serprog.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_dynexec.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/dynexec.S ${CMAKE_CURRENT_SOURCE_DIR}/src/vnd_i2ctinyusb.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/rtconf.c diff --git a/bsp/rp2040/protocfg.h b/bsp/rp2040/protocfg.h index 459c312..791a6c7 100644 --- a/bsp/rp2040/protocfg.h +++ b/bsp/rp2040/protocfg.h @@ -19,6 +19,7 @@ enum { #ifdef USE_USBCDC_FOR_STDIO CDC_N_STDIO, #endif + CDC_N_DYNEXEC CDC_N__NITF }; @@ -28,9 +29,9 @@ enum { #define CFG_TUD_HID 1 #ifdef USE_USBCDC_FOR_STDIO -#define CFG_TUD_CDC 3 +#define CFG_TUD_CDC 4 #else -#define CFG_TUD_CDC 2 +#define CFG_TUD_CDC 3 #endif #define CFG_TUD_VENDOR 0 diff --git a/dmctl.py b/dmctl.py index 6f85ce2..1dd91d1 100755 --- a/dmctl.py +++ b/dmctl.py @@ -143,6 +143,14 @@ def main(): #do_xfer(1, 1, "/dev/ttyACM1") #do_xfer(1, 0, "/dev/ttyACM1") -if __name__ == '__main__': - main() +#if __name__ == '__main__': +# main() +with serial.Serial('/dev/ttyACM2', 115200, timeout=1) as ser: + regs = [x+0x18 for x in range(8)] + ops = [0x1889] # adds r1, r2 + olen = len(ops) + + ser.write(struct.pack(' +#include +#include + +#include "tusb.h" + +#include "protocfg.h" + +#include "protos.h" +#include "util.h" + +extern uint32_t dynexec_regs[8]; +uint32_t dynexec_regs[8]; +extern uint32_t dynexec_codesize; +uint32_t dynexec_codesize; +extern void* dynexec_code; +void* dynexec_code; + +static uint32_t codecap; +static uint16_t codestatic[32]; + +static uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE]; +static uint32_t rxavail, rxpos; + +extern void dynexec_exec(void); + +void cdc_dynexec_init(void) { + dynexec_codesize = 0; + memset(dynexec_regs, 0, sizeof dynexec_regs); + + codecap = 32; + dynexec_code = codestatic; +} + +static uint8_t read_byte(void) { + while (rxavail <= 0) { + if (!tud_cdc_n_connected(CDC_N_DYNEXEC) || !tud_cdc_n_available(CDC_N_DYNEXEC)) { + thread_yield(); + continue; + } + + rxpos = 0; + rxavail = tud_cdc_n_read(CDC_N_DYNEXEC, rx_buf, sizeof rx_buf); + + if (rxavail == 0) thread_yield(); + } + + uint8_t rv = rx_buf[rxpos]; + ++rxpos; + --rxavail; + return rv; +} + +static uint16_t read_hword(void) { + uint16_t r; + r = (uint16_t)read_byte(); + r |= (uint16_t)read_byte() << 8; + return r; +} +static uint32_t read_word(void) { + uint32_t r; + r = (uint32_t)read_byte(); + r |= (uint32_t)read_byte() << 8; + r |= (uint32_t)read_byte() << 16; + r |= (uint32_t)read_byte() << 24; + return r; +} + +struct dynexec_hdr { + uint32_t regs[8]; + uint32_t codelen; +}; + +void cdc_dynexec_task(void) { + for (int i = 0; i < 8; ++i) + dynexec_regs[i] = read_word(); + dynexec_codesize = read_word() /*+ 3*/; + + for (int i = 0; i < 8; ++i) + printf("r%d = 0x%08x\n", i, dynexec_regs[i]); + printf("codesize = 0x%04x\n", dynexec_codesize); + + while (dynexec_codesize > codecap) { + codecap <<= 1; + + if (codecap == 64) { + dynexec_code = malloc(codecap*sizeof(uint16_t)); + } else { + dynexec_code = realloc(dynexec_code, codecap*sizeof(uint16_t)); + } + } + + for (uint32_t i = 0; i < dynexec_codesize; ++i) { + ((uint16_t*)dynexec_code)[2+i] = read_hword(); + } + + // all little-endian... + ((uint16_t*)dynexec_code)[0] = 0xbc80; // pop {r7} + ((uint16_t*)dynexec_code)[1] = 0xb500; // push {lr} + ((uint16_t*)dynexec_code)[2+dynexec_codesize] = 0xbd00; // pop {pc} + + for (uint32_t i = 0; i < dynexec_codesize+3; ++i) { + printf("code[%u] = %04x\n", i, ((uint16_t*)dynexec_code)[i]); + } + + printf("exec!\n"); + dynexec_exec(); + + for (int i = 0; i < 8; ++i) + printf("r%d = 0x%08x\n", i, dynexec_regs[i]); +} + diff --git a/src/dynexec.S b/src/dynexec.S new file mode 100644 index 0000000..fa03a9e --- /dev/null +++ b/src/dynexec.S @@ -0,0 +1,43 @@ +@ vim: set ft=armv5: + +.cpu cortex-m0 +.thumb + +.extern dynexec_regs +.extern dynexec_code + +.section .text.dynexec_exec, "ax", %progbits +.type dynexec_exec, %function +.thumb_func +.global dynexec_exec +dynexec_exec: + push {r0-r7,lr} + + @ load regs from saved ones + ldr r7, =dynexec_regs + ldmia r7!, {r0-r6} + ldr r7, [r7] + push {r7} + + ldr r7, =dynexec_code + ldr r7, [r7] + add r7, #1 @ bluh + blx r7 + + @ save regs in saved ones + + push {r7} + ldr r7, =dynexec_regs + stmia r7!, {r0-r6} + pop {r0} + str r0, [r7] + + pop {r0-r7,pc} + + .pool + +/*to_exec_code: + pop {r7} + push {lr} + @ TODO + pop {pc}*/ diff --git a/src/main.c b/src/main.c index 111ca6c..eadbed3 100644 --- a/src/main.c +++ b/src/main.c @@ -82,6 +82,18 @@ static void serprog_thread_fn(void) { } #endif +static cothread_t dynexecthread; +static uint8_t dynexecstack[DEFAULT_STACK_SIZE]; + +static void dynexec_thread_fn(void) { + cdc_dynexec_init(); + thread_yield(); + while (1) { + cdc_dynexec_task(); + thread_yield(); + } +} + // FIXME extern uint32_t co_active_buffer[64]; uint32_t co_active_buffer[64]; @@ -114,6 +126,8 @@ int main(void) { serprogthread = co_derive(serprogstack, sizeof serprogstack, serprog_thread_fn); co_switch(serprogthread); // will call cdc_serprog_init() on correct thread #endif + dynexecthread = co_derive(dynexecstack, sizeof dynexecstack, dynexec_thread_fn); + co_switch(dynexecthread); #ifdef DBOARD_HAS_CMSISDAP DAP_Setup(); #endif @@ -139,6 +153,9 @@ int main(void) { #ifdef DBOARD_HAS_SERPROG co_switch(serprogthread); #endif + + tud_task(); + co_switch(dynexecthread); } return 0; diff --git a/src/protos.h b/src/protos.h index 5d796dc..fa9cc40 100644 --- a/src/protos.h +++ b/src/protos.h @@ -33,5 +33,8 @@ void itu_init(void); void itu_task(void); #endif +void dynexec_init(void); +void dynexec_task(void); + #endif diff --git a/src/tusb_config.h b/src/tusb_config.h index 460bcd3..9532065 100644 --- a/src/tusb_config.h +++ b/src/tusb_config.h @@ -100,6 +100,7 @@ extern "C" { #endif //------------- CLASS -------------// + #define CFG_TUD_MSC 0 #define CFG_TUD_MIDI 0 #define CFG_TUD_NET 0 diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index fb9e4f3..ab1163e 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -57,6 +57,7 @@ enum { STRID_IF_CDC_UART, STRID_IF_CDC_SERPROG, STRID_IF_CDC_STDIO, + STRID_IF_CDC_DYNEXEC, }; //--------------------------------------------------------------------+ @@ -124,6 +125,8 @@ enum { ITF_NUM_CDC_SERPROG_COM, ITF_NUM_CDC_SERPROG_DATA, #endif + ITF_NUM_CDC_DYNEXEC_COM, + ITF_NUM_CDC_DYNEXEC_DATA, #ifdef USE_USBCDC_FOR_STDIO ITF_NUM_CDC_STDIO_COM, ITF_NUM_CDC_STDIO_DATA, @@ -154,6 +157,7 @@ enum { #ifdef USE_USBCDC_FOR_STDIO + TUD_CDC_DESC_LEN #endif + + TUD_CDC_DESC_LEN }; #define EPNUM_CDC_UART_OUT 0x02 @@ -163,9 +167,12 @@ enum { #define EPNUM_CDC_SERPROG_OUT 0x05 #define EPNUM_CDC_SERPROG_IN 0x85 #define EPNUM_CDC_SERPROG_NOTIF 0x86 -#define EPNUM_CDC_STDIO_OUT 0x07 -#define EPNUM_CDC_STDIO_IN 0x87 -#define EPNUM_CDC_STDIO_NOTIF 0x88 +#define EPNUM_CDC_DYNEXEC_OUT 0x07 +#define EPNUM_CDC_DYNEXEC_IN 0x87 +#define EPNUM_CDC_DYNEXEC_NOTIF 0x88 +#define EPNUM_CDC_STDIO_OUT 0x09 +#define EPNUM_CDC_STDIO_IN 0x89 +#define EPNUM_CDC_STDIO_NOTIF 0x8a // NOTE: if you modify this table, don't forget to keep tusb_config.h up to date as well! // TODO: maybe add some strings to all these interfaces @@ -188,6 +195,8 @@ uint8_t const desc_configuration[] = { TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_SERPROG_COM, STRID_IF_CDC_SERPROG, EPNUM_CDC_SERPROG_NOTIF, 64, EPNUM_CDC_SERPROG_OUT, EPNUM_CDC_SERPROG_IN, 64), #endif + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_DYNEXEC_COM, STRID_IF_CDC_DYNEXEC, EPNUM_CDC_DYNEXEC_NOTIF, 64, EPNUM_CDC_DYNEXEC_OUT, EPNUM_CDC_DYNEXEC_IN, 64), + #ifdef USE_USBCDC_FOR_STDIO TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_STDIO_COM, STRID_IF_CDC_STDIO, EPNUM_CDC_STDIO_NOTIF, 64, EPNUM_CDC_STDIO_OUT, EPNUM_CDC_STDIO_IN, 64), #endif @@ -218,6 +227,7 @@ char const* string_desc_arr [] = { [STRID_IF_CDC_UART] = "UART CDC interface", [STRID_IF_CDC_SERPROG] = "Serprog CDC interface", [STRID_IF_CDC_STDIO] = "stdio CDC interface (debug)", + [STRID_IF_CDC_DYNEXEC] = "Dynamic execution CDC itf", }; // Invoked when received GET STRING DESCRIPTOR request