runtime configuration stuff

This commit is contained in:
Triss 2021-06-12 21:35:06 +02:00
parent 74355f5eef
commit acb592ba88
6 changed files with 156 additions and 51 deletions

View File

@ -46,6 +46,7 @@ if(FAMILY STREQUAL "rp2040")
${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/cdc_uart.c
${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/spi_serprog.c
${CMAKE_CURRENT_SOURCE_DIR}/cdc_serprog.c
${CMAKE_CURRENT_SOURCE_DIR}/rtconf.c
)
# Example include

View File

@ -125,13 +125,25 @@ libco is licensed under the [ISC license](https://opensource.org/licenses/ISC)
- [x] Flashrom/SPI support using Serprog
- [ ] Parallel ROM flashing support, too, by having the device switch into a
separate mode that temporarily disables all other IO protocols
- [ ] UART with CTS/RTS flow control
- Needs configurable stuff as well, as some UART interfaces won't use this.
- [x] UART with CTS/RTS flow control
- [x] Needs configurable stuff as well, as some UART interfaces won't use this.
- [ ] Debug interface to send printf stuff directly to USB, instead of having
- to use the UART interface as a loopback thing.
- [ ] I2C support by emulating the I2C Tiny USB
- [ ] Expose RP2040-internal temperature ADC on I2C-over-USB bus?
- Does SMBus stuff need special treatment here?
- [ ] Host-side script that is an XVC (or hw_server) cable and communicates
with the device to perform the JTAG commands, because Vivado no likey
OpenOCD.
- CMSIS-DAP interface can be used directly, see CMSIS_5/CMSIS/DoxyGen/DAP/src/dap_USB_cmds.txt
- https://github.com/BerkeleyLab/XVC-FTDI-JTAG
- https://www.eevblog.com/forum/fpga/xilinx-jtag-and-tcf/
- https://git.eclipse.org/c/tcf/org.eclipse.tcf.git/plain/docs/TCF%20Linux%20Agent%20Prototype.html
- http://www.eclipse.org/tcf/
- https://debugmo.de/2012/02/xvcd-the-xilinx-virtual-cable-daemon/
- https://github.com/Xilinx/XilinxVirtualCable/
- https://github.com/derekmulcahy/xvcpi
- OpenOCD as XVC client??
- [ ] Maybe use the ADCs for something?
- [ ] AVR programming (USBavr emulation?)
- AVR ISP is hardly used anymore

View File

@ -10,6 +10,7 @@
#include "protos.h"
#include "thread.h"
#include "rtconf.h"
#include "serprog.h"
@ -26,7 +27,16 @@ static const uint8_t serprog_cmdmap[32] = {
0x3f, // cmd 00..05 not 0x06 (Q_CHIPSIZE) and 0x07 (Q_OPBUF), as this is a SPI-only device
0x01, // only cmd 08
0x1f, // cmd 10..15 supported
0, // rest is 0
0, // 18..1f
0, // 20..27
0, // 28..2f
0, // 30..37
0, // 38..3f
0, // 40..47
0, // 48..4f
(1<<3), // 50..57: enable 0x53
0, // 58..5f
0, // rest is 0
};
static const char serprog_pgmname[16] = {
'D','a','p','p','e','r','M','i','m','e','-','J','T','A','G',0 // TODO
@ -219,6 +229,16 @@ static void handle_cmd(void) {
}
break;
case S_CMD_MAGIC_SETTINGS: {
uint8_t a = read_byte();
uint8_t b = read_byte();
tx_buf[0] = S_ACK;
tx_buf[1] = rtconf_do(a, b);
nresp = 2;
}
break;
default:
//printf("ill %d\n", cmd);
tx_buf[0] = S_NAK;
@ -232,54 +252,6 @@ static void handle_cmd(void) {
}
}
//extern void cdc_uart_task();
//void cdc_serprog_task(void) {
// bool conn = tud_cdc_n_connected(CDC_N_SERPROG),
// avail = tud_cdc_n_available(CDC_N_SERPROG);
// //printf("hi conn=%c avail=%c\n", conn?'y':'n', avail?'y':'n');
// // TODO: this is, apparently, not at all how this works: in practice,
// // bytes seem to be sent one by one, so its probably better to rework
// // this, a lot
// if (conn && avail) {
// //printf("rbp=%d\n", bufpos);
// uint32_t nread = tud_cdc_n_read(CDC_N_SERPROG, &rx_buf[bufpos], sizeof(rx_buf) - bufpos);
// printf("got %d\n", nread);
// cdc_uart_task();
//
// bufpos = 0;
// do {
// //printf("hbp=%d\n", /*rx_buf[bufpos],*/ bufpos);
// cdc_uart_task();
// uint32_t dec = serprog_handle_cmd(&rx_buf[bufpos], nread);
// cdc_uart_task();
// printf("dec=%d\n", dec);
//
// cdc_uart_task();
//
// // didn't do a decrement => not enough data, wait for the next
// // task() call to read it in
// if (dec == 0) {
// // so we move the leftover data to the start of the buffer,
// // and make sure the next call will put the new data right
// // after it
// //printf("mv %d %d %d ", nread, bufpos, rx_buf[bufpos]);
// memmove(rx_buf, &rx_buf[bufpos], nread);
// //printf("%d\n", rx_buf[0]);
// bufpos = nread;
// break;
// }
//
// nread -= dec;
// bufpos += dec;
// // read everything left in the buffer => we're done here
// if (nread == 0) {
// // and we can start using the full rx buffer again
// bufpos = 0;
// break;
// }
// } while (tud_cdc_n_connected(CDC_N_SERPROG) && tud_cdc_n_available(CDC_N_SERPROG));
// }
//}
void cdc_serprog_task(void) {
handle_cmd();
//printf("d\n");

77
dmctl.py Normal file
View File

@ -0,0 +1,77 @@
#!/usr/bin/env python3
import serial, struct
from typing import *
S_ACK = b'\x06'
S_NAK = b'\x15'
S_CMD_NOP = b'\x00'
S_CMD_Q_IFACE = b'\x01'
S_CMD_Q_CMDMAP = b'\x02'
S_CMD_Q_PGMNAME = b'\x03'
S_CMD_SYNCNOP = b'\x10'
S_CMD_MAGIC_SETTINGS = b'\x53'
def do_xfer(cmd:int, arg:int, port: str, baudrate:int=115200) -> Optional[int]:
with serial.Serial(port, baudrate, timeout=1) as ser:
cmdmap = [0]*32
syncok = False
for i in range(8):
ser.write(S_CMD_SYNCNOP)
a = ser.read()
b = ser.read()
if a == S_NAK and b == S_ACK:
syncok = True
break
if not syncok:
print("sync failed")
return None
ser.write(S_CMD_NOP)
if ser.read() != S_ACK:
print("nop failed")
return None
ser.write(S_CMD_Q_IFACE)
if ser.read() != S_ACK:
print("q_iface failed")
return None
serprogver = struct.unpack('<H', ser.read(2))[0]
if serprogver != 1:
print("unknown serprog protocol version %d" % serprogver)
return None
ser.write(S_CMD_Q_CMDMAP)
if ser.read() != S_ACK:
print("q_cmdmap failed")
return None
else:
cmdmap = ser.read(32)
if (cmdmap[S_CMD_MAGIC_SETTINGS[0] >> 3] & (1<<(S_CMD_MAGIC_SETTINGS[0]&7))) == 0:
print("serprog programmer has no S_CMD_MAGIC_SETTINGS")
return None
if (cmdmap[S_CMD_Q_PGMNAME[0] >> 3] & (1<<(S_CMD_Q_PGMNAME[0]&7))) != 0:
ser.write(S_CMD_Q_PGMNAME)
if ser.read() != S_ACK:
print("q_pgmname failed")
else:
name = ser.read(16).decode('utf-8')
print("programmer is '%s'" % name)
ser.write(S_CMD_MAGIC_SETTINGS)
ser.write(bytes([cmd,arg]))
acknak = ser.read()
if acknak == S_ACK:
return ser.read()[0]
else:
print("settings command failed")
return None
do_xfer(1, 1, "/dev/ttyACM1")
do_xfer(1, 0, "/dev/ttyACM1")

22
rtconf.c Normal file
View File

@ -0,0 +1,22 @@
#include <stdint.h>
#include <stdio.h>
#include "protos.h"
#include "rtconf.h"
uint8_t rtconf_do(uint8_t a, uint8_t b) {
//printf("rtconf %02x,%02x\n", a, b);
switch ((enum rtconf_opt)a) {
#ifdef DBOARD_HAS_UART
case opt_uart_hwfc_endis:
cdc_uart_set_hwflow(b != 0);
return 0;
#endif
default:
return 0xff;
}
}

21
rtconf.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef RTCONF_H_
#define RTCONF_H_
#include <stdint.h>
#include "protocfg.h"
enum rtconf_opt {
#ifdef DBOARD_HAS_UART
// enable_disable UART flow control
// b: 0 -> disable, nonzero -> enable
// return: 0
opt_uart_hwfc_endis = 1,
#endif
};
uint8_t rtconf_do(uint8_t a, uint8_t b);
#endif