definitely not functuonal but hey its something

This commit is contained in:
Triss 2021-06-06 05:10:36 +02:00
parent f73f890276
commit 144b351d74
18 changed files with 593 additions and 37 deletions

View File

@ -7,6 +7,9 @@ set(TOP "./tinyusb")
get_filename_component(TOP "${TOP}" REALPATH)
option(USE_SYSTEMWIDE_PICOSDK "Use the systemwide Pico SDK instead of relying on the one from a deeply nested Git submodule (OFF by default)" OFF)
# OPTION: PICO_NO_FLASH: load only into RAM (useful for testing)
# OPTION: PICO_COPY_TO_RAM: place the code/rodata into RAM at startup (while still stored in flash)
# TODO: add option for FAMILY and BOARD
# Check for -DFAMILY=
if(FAMILY STREQUAL "rp2040")
@ -25,6 +28,10 @@ if(FAMILY STREQUAL "rp2040")
include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
# need uart stdio, usb is busy doing other stuff
pico_enable_stdio_uart(${PROJECT} 1)
pico_enable_stdio_usb(${PROJECT} 0)
# Example source
target_sources(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/main.c
@ -35,6 +42,8 @@ if(FAMILY STREQUAL "rp2040")
${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5/CMSIS/DAP/Firmware/Source/SWO.c
${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5/CMSIS/DAP/Firmware/Source/SW_DP.c
${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
)
# Example include
@ -50,7 +59,8 @@ if(FAMILY STREQUAL "rp2040")
target_compile_definitions(${PROJECT} PUBLIC
)
target_link_libraries(${PROJECT} pico_stdlib pico_fix_rp2040_usb_device_enumeration pico_unique_id)
target_link_libraries(${PROJECT} pico_stdlib pico_unique_id hardware_spi
pico_fix_rp2040_usb_device_enumeration)
pico_add_extra_outputs(${PROJECT})

View File

@ -8,7 +8,7 @@ INC += \
./bsp/default \
$(TOP)/hw
APP_SOURCE += $(wildcard ./*.c)
APP_SOURCE += $(wildcard ./*.c) $(wildcard ./bsp/$(BOARD)/*.c)
SRC_C += $(addprefix $(CURRENT_PATH)/, $(APP_SOURCE))
@ -17,7 +17,6 @@ SRC_C += \
./CMSIS_5/CMSIS/DAP/Firmware/Source/JTAG_DP.c \
./CMSIS_5/CMSIS/DAP/Firmware/Source/DAP_vendor.c \
./CMSIS_5/CMSIS/DAP/Firmware/Source/SWO.c \
./CMSIS_5/CMSIS/DAP/Firmware/Source/SW_DP.c \
./bsp/$(BOARD)/cdc_uart.c
./CMSIS_5/CMSIS/DAP/Firmware/Source/SW_DP.c
include ./tinyusb/examples/rules.mk

View File

@ -74,7 +74,8 @@ The pin mapping for the RP2040 is as follows:
The UART pins are for connecting to the device to be debugged, the data is
echoed back over the USB CDC interface (typically a `/dev/ttyACMx` device on
Linux).
Linux). If you want to get stdio readout on your computer, connect GP0 to GP5,
and GP1 to GP4.
In SWD mode, the pin mapping is entirely as with the standard Picoprobe setup,
as described in Chapter 5 and Appendix A of [Getting Started with Raspberry Pi
@ -94,7 +95,23 @@ ARM's CMSIS_5 code is licensed under the [Apache 2.0 license](https://opensource
## TODO
- [x] CMSIS-DAP JTAG implementation
- [ ] Flashrom/SPI support using Serprog
- [ ] UART with CTS/RTS flow control
- [ ] 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?
- [ ] Maybe add some way of reconfiguring features while the device is running.
Eg. CTS/RTS enable/disable, temperature ADC I2C address, ...
- Maybe use the Serprog USB serial interface for this, with some extension
commands not typically used for Serprog.
- [ ] AVR programming (USBavr emulation?)
- Renesas E7-{0,1,2} programming thing????
- Renesas tell us how this works pls
- Maybe steal other features from the Bus Pirate or Glasgow or so
- 1-wire? Never seen this one in the wild
- MIDI? Feels mostly gimmicky...
- PS/2? Hmmmm idk
- HD44780 LCD? See MIDI
- CAN? If I'd first be able to find a CAN device to test it with, sure

11
bsp/default/protocfg.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef PROTOCFG_H_
#define PROTOCFG_H_
/*#define DBOARD_HAS_UART*/
#define DBOARD_HAS_CMSISDAP
/*#define DBOARD_HAS_SERPROG*/
/*#define DBOARD_HAS_TINYI2C*/
#endif

View File

@ -57,6 +57,7 @@ This information includes:
#include <hardware/regs/io_bank0.h>
#include <hardware/structs/iobank0.h>
#include <hardware/gpio.h>
#include <pico/binary_info.h>
#include "picoprobe_config.h"
@ -559,6 +560,17 @@ __STATIC_INLINE void DAP_SETUP (void) {
hw_write_masked(&padsbank0_hw->io[PICOPROBE_LED], 0, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
iobank0_hw->io[PICOPROBE_LED].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
bi_decl(bi_2pins_with_names(
PROBE_PIN_JTAG_TCK, "TCK / SWCLK",
PROBE_PIN_JTAG_TMS, "TMS / SWDIO"
));
bi_decl(bi_4pins_with_names(
PROBE_PIN_JTAG_TDI , "TDI",
PROBE_PIN_JTAG_TDO , "TDO",
PROBE_PIN_JTAG_nTRST , "nTRST",
PROBE_PIN_JTAG_nRESET, "nRESET"
));
}
/** Reset Target Device with custom specific I/O pin or command sequence.

View File

@ -24,39 +24,49 @@
*/
#include <pico/stdlib.h>
#include <pico/binary_info.h>
#include "tusb.h"
#include "picoprobe_config.h"
#include "protocfg.h"
#include "protos.h"
// declare these so other CDC interfaces can use the same buffers, decreasing
// overall memory usage. however, this means the contents of these buffers
// can't be relied upon to persist between two cdc_*_task() calls
extern uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE];
extern uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE];
__attribute__((__weak__)) uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE];
__attribute__((__weak__)) uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE];
void cdc_uart_init(void) {
gpio_set_function(PICOPROBE_UART_TX, GPIO_FUNC_UART);
gpio_set_function(PICOPROBE_UART_RX, GPIO_FUNC_UART);
uart_init(PICOPROBE_UART_INTERFACE, PICOPROBE_UART_BAUDRATE);
bi_decl(bi_2pins_with_func(PICOPROBE_UART_TX, PICOPROBE_UART_RX, GPIO_FUNC_UART));
}
void cdc_task(void) {
uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE];
uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE];
void cdc_uart_task(void) {
// Consume uart fifo regardless even if not connected
uint rx_len = 0;
while(uart_is_readable(PICOPROBE_UART_INTERFACE) && (rx_len < sizeof(rx_buf))) {
while (uart_is_readable(PICOPROBE_UART_INTERFACE) && (rx_len < sizeof(rx_buf))) {
rx_buf[rx_len++] = uart_getc(PICOPROBE_UART_INTERFACE);
}
if (tud_cdc_connected()) {
if (tud_cdc_n_connected(CDC_N_UART)) {
// Do we have anything to display on the host's terminal?
if (rx_len) {
for (uint i = 0; i < rx_len; i++) {
tud_cdc_write_char(rx_buf[i]);
tud_cdc_n_write_char(CDC_N_UART, rx_buf[i]);
}
tud_cdc_write_flush();
tud_cdc_n_write_flush(CDC_N_UART);
}
if (tud_cdc_available()) {
if (tud_cdc_n_available(CDC_N_UART)) {
// Is there any data from the host for us to tx
uint tx_len = tud_cdc_read(tx_buf, sizeof(tx_buf));
uint tx_len = tud_cdc_n_read(CDC_N_UART, tx_buf, sizeof(tx_buf));
uart_write_blocking(PICOPROBE_UART_INTERFACE, tx_buf, tx_len);
}
}
@ -66,3 +76,4 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) {
picoprobe_info("New baud rate %d\n", line_coding->bit_rate);
uart_init(PICOPROBE_UART_INTERFACE, line_coding->bit_rate);
}

View File

@ -66,6 +66,13 @@
#define PROBE_PIN_JTAG_nTRST 8
#define PROBE_PIN_JTAG_nRESET 9
// SPI config
#define PROBE_SPI_DEV spi1
#define PROBE_SPI_SCLK 10
#define PROBE_SPI_MOSI 11
#define PROBE_SPI_MISO 12
#define PROBE_SPI_nCS 13
// LED config
// you can change these two as you like

15
bsp/rp2040/protocfg.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef PROTOCFG_H_
#define PROTOCFG_H_
#define DBOARD_HAS_UART
#define DBOARD_HAS_CMSISDAP
#define DBOARD_HAS_SERPROG
/*#define DBOARD_HAS_TINYI2C*/
#define HID_N_CMSISDAP 0
#define CDC_N_UART 0
#define CDC_N_SERPROG 1
#endif

65
bsp/rp2040/spi_serprog.c Normal file
View File

@ -0,0 +1,65 @@
#include <stdio.h>
#include <pico/stdlib.h>
#include <pico/binary_info.h>
#include <hardware/spi.h>
#include "protocfg.h"
#include "protos.h"
#include "serprog.h"
#include "picoprobe_config.h"
static bool cs_asserted;
void sp_spi_init(void) {
printf("spi init!\n");
cs_asserted = false;
spi_init(PROBE_SPI_DEV, 512*1000); // default to 512 kHz
gpio_init(PROBE_SPI_nCS);
gpio_put(PROBE_SPI_nCS, 1);
gpio_set_dir(PROBE_SPI_nCS, GPIO_OUT);
gpio_set_function(PROBE_SPI_MISO, GPIO_FUNC_SPI);
gpio_set_function(PROBE_SPI_MOSI, GPIO_FUNC_SPI);
gpio_set_function(PROBE_SPI_SCLK, GPIO_FUNC_SPI);
bi_decl(bi_3pins_with_func(PROBE_SPI_MISO, PROBE_SPI_MOSI, PROBE_SPI_SCLK, GPIO_FUNC_SPI));
bi_decl(bi_1pin_with_name(PROBE_SPI_nCS, "SPI #CS"));
}
uint32_t __not_in_flash_func(sp_spi_set_freq)(uint32_t freq_wanted) {
return spi_set_baudrate(PROBE_SPI_DEV, freq_wanted);
}
void __not_in_flash_func(sp_spi_cs_deselect)(void) {
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PROBE_SPI_nCS, 1);
asm volatile("nop\nnop\nnop"); // idk if this is needed
cs_asserted = false;
}
void __not_in_flash_func(sp_spi_cs_select)(void) {
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PROBE_SPI_nCS, 0);
asm volatile("nop\nnop\nnop"); // idk if this is needed
cs_asserted = true;
}
void __not_in_flash_func(sp_spi_op_begin)(void) {
if (!cs_asserted) sp_spi_cs_select();
}
void __not_in_flash_func(sp_spi_op_end)(void) {
if (cs_asserted) sp_spi_cs_deselect();
}
// TODO: use dma?
void __not_in_flash_func(sp_spi_op_write)(uint32_t write_len, const uint8_t* write_data) {
spi_write_blocking(PROBE_SPI_DEV, write_data, write_len);
}
void __not_in_flash_func(sp_spi_op_read)(uint32_t read_len, uint8_t* read_data) {
spi_read_blocking(PROBE_SPI_DEV, 0, read_data, read_len);
}

View File

@ -2,6 +2,6 @@ void cdc_uart_init(void)
{
}
void cdc_task(void)
void cdc_uart_task(void)
{
}

View File

@ -0,0 +1,11 @@
#ifndef PROTOCFG_H_
#define PROTOCFG_H_
/*#define DBOARD_HAS_UART*/
#define DBOARD_HAS_CMSISDAP
/*#define DBOARD_HAS_SERPROG*/
/*#define DBOARD_HAS_TINYI2C*/
#endif

View File

@ -0,0 +1,17 @@
#include "serprog.h"
void sp_spi_init(void) {
}
uint32_t sp_spi_set_freq(uint32_t freq_wanted) {
return 0;
}
void sp_spi_cs_deselect(void) {
}
void sp_spi_cs_select(void) {
}
void sp_spi_op_begin(void){}
void sp_spi_op_write(uint32_t write_len, uint8_t* write_data){}
void sp_spi_op_read(uint32_t read_len, const uint8_t* read_data){}
void sp_spi_op_end(void){}

241
cdc_serprog.c Normal file
View File

@ -0,0 +1,241 @@
// vim: set et:
#include <stdio.h>
#include "tusb.h"
#include "protocfg.h"
#ifdef DBOARD_HAS_SERPROG
#include "protos.h"
#include "serprog.h"
// TODO: refactor some of this stuff into another header & split off serprog
// protocol handling from the SPI stuff. one thing we should think about
// when performing this refactor is, would other boards support
// parallell, LPC, or FWH, or only SPI? if only SPI, the entire proto
// handler can just be made reusable verbatim.
// kinda refactored this already but it still has a good note for non-SPI stuff,
// so leaving it here for now
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
};
static const char serprog_pgmname[16] = {
'D','a','p','p','e','r','M','i','m','e','-','J','T','A','G',0 // TODO
};
// declare these so other CDC interfaces can use the same buffers, decreasing
// overall memory usage. however, this means the contents of these buffers
// can't be relied upon to persist between two cdc_*_task() calls
extern uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE];
extern uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE];
__attribute__((__weak__)) uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE];
__attribute__((__weak__)) uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE];
static uint32_t bufpos;
void cdc_serprog_init(void) {
bufpos = 0;
sp_spi_init();
}
static uint32_t serprog_handle_cmd(const uint8_t* buf, uint32_t nread) {
if (nread == 0) return 0;
uint32_t nresp = 0, rv = 1;
switch (buf[0]) {
case S_CMD_NOP:
printf("nop\n");
tx_buf[0] = S_ACK;
nresp = 1;
break;
case S_CMD_SYNCNOP:
printf("syncnop\n");
tx_buf[0] = S_NAK;
tx_buf[1] = S_ACK;
nresp = 2;
break;
case S_CMD_Q_IFACE:
printf("q_iface\n");
tx_buf[0] = S_ACK;
tx_buf[1] = SERPROG_IFACE_VERSION & 0xff;
tx_buf[2] = (SERPROG_IFACE_VERSION >> 8) & 0xff;
nresp = 3;
break;
case S_CMD_Q_CMDMAP:
printf("q_cmdmap\n");
tx_buf[0] = S_ACK;
memcpy(&tx_buf[1], serprog_cmdmap, sizeof serprog_cmdmap);
nresp = sizeof(serprog_cmdmap) + 1;
break;
case S_CMD_Q_PGMNAME:
printf("q_pgmname\n");
tx_buf[0] = S_ACK;
memcpy(&tx_buf[1], serprog_pgmname, sizeof serprog_pgmname);
nresp = sizeof(serprog_pgmname) + 1;
break;
case S_CMD_Q_SERBUF:
printf("q_serbuf\n");
tx_buf[0] = S_ACK;
tx_buf[1] = sizeof(rx_buf) & 0xff;
tx_buf[2] = (sizeof(rx_buf) >> 8) & 0xff;
nresp = 3;
break;
case S_CMD_Q_BUSTYPE:
printf("q_bustype\n");
tx_buf[0] = S_ACK;
tx_buf[1] = 1<<3; // SPI only
nresp = 2;
break;
case S_CMD_Q_WRNMAXLEN:
printf("q_wrnmaxlen\n");
tx_buf[0] = S_ACK;
tx_buf[1] = (sizeof(tx_buf)-1) & 0xff;
tx_buf[2] = ((sizeof(tx_buf)-1) >> 8) & 0xff;
nresp = 3;
break;
case S_CMD_Q_RDNMAXLEN:
printf("q_rdnmaxlen\n");
tx_buf[0] = S_ACK;
tx_buf[1] = (sizeof(rx_buf)-1) & 0xff;
tx_buf[2] = ((sizeof(rx_buf)-1) >> 8) & 0xff;
nresp = 3;
break;
case S_CMD_S_BUSTYPE:
printf("s_bustype\n");
if (nread < 2) return 0; // need more data
if (buf[1] == (1<<3)) {
tx_buf[0] = S_ACK;
} else {
tx_buf[0] = S_NAK;
}
nresp = 1;
rv = 2;
break;
case S_CMD_SPIOP: {
printf("spiop\n");
if (nread < 7) return 0; // need more data
uint32_t
slen = (uint32_t)buf[1] | ((uint32_t)buf[2] << 8) | ((uint32_t)buf[3]),
rlen = (uint32_t)buf[4] | ((uint32_t)buf[5] << 8) | ((uint32_t)buf[6]);
if (7 + slen > sizeof(rx_buf) || 1 + rlen > sizeof(tx_buf)) {
// TODO: stream buffers in and out here for larger xfers
tx_buf[0] = S_NAK;
nresp = 1;
} else {
if (nread < 7 + slen) return 0;
tx_buf[0] = S_ACK;
sp_spi_op_do(slen, &buf[7], rlen, &tx_buf[1]);
nresp = 7 + rlen;
rv = 7 + slen;
}
}
break;
case S_CMD_S_SPI_FREQ: {
printf("s_spi_freq\n");
if (nread < 5) return 0; // need more data
uint32_t freq = (uint32_t)buf[1] | ((uint32_t)buf[2] << 8) | ((uint32_t)buf[3] << 16) | ((uint32_t)buf[4] << 24);
uint32_t nfreq = sp_spi_set_freq(freq);
tx_buf[0] = S_ACK;
tx_buf[1] = nfreq & 0xff;
tx_buf[2] = (nfreq >> 8) & 0xff;
tx_buf[3] = (nfreq >> 16) & 0xff;
tx_buf[4] = (nfreq >> 24) & 0xff;
nresp = 5;
rv = 5;
}
break;
case S_CMD_S_PINSTATE: {
printf("s_pinstate\n");
if (nread < 2) return 0; // need more data
if (buf[1] == 0) sp_spi_cs_deselect();
else sp_spi_cs_select();
tx_buf[0] = S_ACK;
nresp = 1;
rv = 2;
}
break;
default:
printf("illcmd %d\n", buf[0]);
tx_buf[0] = S_NAK;
nresp = 1;
break;
}
if (nresp > 0) {
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, nresp);
tud_cdc_n_write_flush(CDC_N_SERPROG);
}
return rv;
}
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));
}
}
#endif /* DBOARD_HAS_SERPROG */

33
main.c
View File

@ -27,27 +27,50 @@
#include <stdio.h>
#include <string.h>
#include "bsp/board.h"
#include "bsp/board.h" /* a tinyusb header */
#include "tusb.h"
#include "DAP_config.h" /* ARM code *assumes* this is included prior to DAP.h */
#include "DAP.h"
void cdc_uart_init(void);
void cdc_task(void);
#include "protocfg.h"
#include "protos.h"
#ifdef PICO_BOARD
#include <pico/binary_info.h>
#endif
int main(void)
{
// TODO: split this out in a bsp-specific file
#ifdef PICO_BOARD
// use hardcoded values from TinyUSB board.h
bi_decl(bi_2pins_with_func(0, 1, GPIO_FUNC_UART));
#endif
board_init();
#ifdef DBOARD_HAS_UART
cdc_uart_init();
#endif
#ifdef DBOARD_HAS_SERPROG
cdc_serprog_init();
#endif
#ifdef DBOARD_HAS_CMSISDAP
DAP_Setup();
#endif
tusb_init();
while (1)
{
tud_task(); // tinyusb device task
cdc_task();
#ifdef DBOARD_HAS_UART
cdc_uart_task();
#endif
#ifdef DBOARD_HAS_SERPROG
cdc_serprog_task();
#endif
sleep_ms(100);
}
return 0;
@ -80,7 +103,9 @@ void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uin
(void) report_id;
(void) report_type;
#ifdef DBOARD_HAS_CMSISDAP
DAP_ProcessCommand(RxDataBuffer, TxDataBuffer);
#endif
tud_hid_report(0, TxDataBuffer, response_size);
}

18
protos.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef PROTOS_H_
#define PROTOS_H_
#include "protocfg.h"
#ifdef DBOARD_HAS_UART
void cdc_uart_init(void);
void cdc_uart_task(void);
#endif
#ifdef DBOARD_HAS_SERPROG
void cdc_serprog_init(void);
void cdc_serprog_task(void);
#endif
#endif

55
serprog.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef SERPROG_H_
#define SERPROG_H_
enum serprog_cmd {
S_CMD_NOP = 0x00,
S_CMD_Q_IFACE = 0x01,
S_CMD_Q_CMDMAP = 0x02,
S_CMD_Q_PGMNAME = 0x03,
S_CMD_Q_SERBUF = 0x04,
S_CMD_Q_BUSTYPE = 0x05,
S_CMD_Q_CHIPSIZE = 0x06,
S_CMD_Q_OPBUF = 0x07,
S_CMD_Q_WRNMAXLEN = 0x08,
S_CMD_R_BYTE = 0x09,
S_CMD_R_NBYTES = 0x0a,
S_CMD_O_INIT = 0x0b,
S_CMD_O_WRITEB = 0x0c,
S_CMD_O_WRITEN = 0x0d,
S_CMD_O_DELAY = 0x0e,
S_CMD_O_EXEC = 0x0f,
S_CMD_SYNCNOP = 0x10,
S_CMD_Q_RDNMAXLEN = 0x11,
S_CMD_S_BUSTYPE = 0x12,
S_CMD_SPIOP = 0x13,
S_CMD_S_SPI_FREQ = 0x14,
S_CMD_S_PINSTATE = 0x15,
};
enum serprog_response {
S_ACK = 0x06,
S_NAK = 0x15
};
#define SERPROG_IFACE_VERSION 0x0001
void sp_spi_init(void);
uint32_t/*freq_applied*/ sp_spi_set_freq(uint32_t freq_wanted);
void sp_spi_cs_deselect(void);
void sp_spi_cs_select(void);
void sp_spi_op_begin(void);
void sp_spi_op_write(uint32_t write_len, const uint8_t* write_data);
void sp_spi_op_read(uint32_t read_len, uint8_t* read_data);
void sp_spi_op_end(void);
static inline void sp_spi_op_do(uint32_t write_len, const uint8_t* write_data,
uint32_t read_len, uint8_t* read_data) {
sp_spi_op_begin();
sp_spi_op_write(write_len, write_data);
sp_spi_op_write(read_len, read_data);
sp_spi_op_end();
}
#endif

View File

@ -65,7 +65,11 @@
#endif
// This example doesn't use an RTOS
#ifdef PICO_BOARD
#define CFG_TUSB_OS OPT_OS_PICO
#else
#define CFG_TUSB_OS OPT_OS_NONE
#endif
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
// #define CFG_TUSB_DEBUG 0
@ -94,7 +98,7 @@
#endif
//------------- CLASS -------------//
#define CFG_TUD_CDC 1
#define CFG_TUD_CDC 2
#define CFG_TUD_MSC 0
#define CFG_TUD_HID 1
#define CFG_TUD_MIDI 0

View File

@ -26,6 +26,8 @@
#include "tusb.h"
#include "unique.h"
#include "protocfg.h"
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
*
@ -52,13 +54,13 @@ tusb_desc_device_t const desc_device =
{
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
.bcdUSB = 0x0110, // FIXME: 0x0200 ?
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = 0xCafe,
.idVendor = 0xCafe, // TODO
.idProduct = USB_PID,
.bcdDevice = 0x0101,
@ -99,29 +101,65 @@ uint8_t const * tud_hid_descriptor_report_cb(void)
enum
{
ITF_NUM_HID,
ITF_NUM_CDC_COM,
ITF_NUM_CDC_DATA,
#ifdef DBOARD_HAS_CMSISDAP
ITF_NUM_HID_CMSISDAP,
#endif
#ifdef DBOARD_HAS_UART
ITF_NUM_CDC_UART_COM,
ITF_NUM_CDC_UART_DATA,
#endif
#ifdef DBOARD_HAS_SERPROG
ITF_NUM_CDC_SERPROG_COM,
ITF_NUM_CDC_SERPROG_DATA,
#endif
ITF_NUM_TOTAL
};
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN)
/*#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN)*/
#define EPNUM_HID 0x01
#define EPNUM_CDC_NOTIF 0x83
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x82
static const int CONFIG_TOTAL_LEN = TUD_CONFIG_DESC_LEN
#ifdef DBOARD_HAS_UART
+ TUD_CDC_DESC_LEN
#endif
#ifdef DBOARD_HAS_CMSISDAP
+ TUD_HID_INOUT_DESC_LEN
#endif
#ifdef DBOARD_HAS_SERPROG
+ TUD_CDC_DESC_LEN
#endif
;
#define EPNUM_CDC_UART_OUT 0x02 // 2
#define EPNUM_CDC_UART_IN 0x82 // 83
#define EPNUM_CDC_UART_NOTIF 0x83 // 1
#define EPNUM_HID_CMSISDAP 0x04 // 4,5?
#define EPNUM_CDC_SERPROG_OUT 0x05 // 7
#define EPNUM_CDC_SERPROG_IN 0x85 // 8
#define EPNUM_CDC_SERPROG_NOTIF 0x86 // 6
// NOTE: if you modify this table, don't forget to keep tusb_config.h up to date as well!
uint8_t const desc_configuration[] =
{
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 1),
#ifdef DBOARD_HAS_UART
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COM, 0, EPNUM_CDC_NOTIF, 64, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_UART_COM, 0, EPNUM_CDC_UART_NOTIF, 64, EPNUM_CDC_UART_OUT, EPNUM_CDC_UART_IN, 64),
#endif
#ifdef DBOARD_HAS_CMSISDAP
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID_CMSISDAP, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID_CMSISDAP, 0x80 | (EPNUM_HID_CMSISDAP+0), CFG_TUD_HID_EP_BUFSIZE, 1),
#endif
#ifdef DBOARD_HAS_SERPROG
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_SERPROG_COM, 0, EPNUM_CDC_SERPROG_NOTIF, 64, EPNUM_CDC_SERPROG_OUT, EPNUM_CDC_SERPROG_IN, 64),
#endif
};
// Invoked when received GET CONFIGURATION DESCRIPTOR
@ -141,8 +179,8 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
char const* string_desc_arr [] =
{
[STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409)
[STRID_MANUFACTURER] = "TinyUSB", // Manufacturer
[STRID_PRODUCT] = PRODUCT_PREFIX "CMSIS-DAP", // Product
[STRID_MANUFACTURER] = "TinyUSB", // Manufacturer // TODO
[STRID_PRODUCT] = PRODUCT_PREFIX "CMSIS-DAP", // Product // TODO
};
static uint16_t _desc_str[32];