runtime configuration stuff
This commit is contained in:
parent
74355f5eef
commit
acb592ba88
|
@ -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
|
||||
|
|
16
README.md
16
README.md
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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")
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue