fun experiment ig

This commit is contained in:
Triss 2021-06-19 23:17:14 +02:00
parent 1e61d057bb
commit 425391a3a8
9 changed files with 207 additions and 9 deletions

View File

@ -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

View File

@ -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

View File

@ -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('<IIIIIIII', *regs))
ser.write(struct.pack('<I', olen))
ser.write(struct.pack('<'+('H'*olen), *ops))

113
src/cdc_dynexec.c Normal file
View File

@ -0,0 +1,113 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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]);
}

43
src/dynexec.S Normal file
View File

@ -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}*/

View File

@ -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;

View File

@ -33,5 +33,8 @@ void itu_init(void);
void itu_task(void);
#endif
void dynexec_init(void);
void dynexec_task(void);
#endif

View File

@ -100,6 +100,7 @@ extern "C" {
#endif
//------------- CLASS -------------//
#define CFG_TUD_MSC 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_NET 0

View File

@ -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