spi stuff

This commit is contained in:
Triss 2021-07-04 16:09:45 +02:00
parent 5c17820a52
commit 0f4566d0e7
11 changed files with 310 additions and 127 deletions

View File

@ -5,7 +5,7 @@
#define DBOARD_HAS_UART
#define DBOARD_HAS_CMSISDAP
// TODO: rename to _SPI
#define DBOARD_HAS_SERPROG
#define DBOARD_HAS_SPI
#define DBOARD_HAS_I2C
#define DBOARD_HAS_TEMPSENSOR
@ -27,7 +27,7 @@ enum {
};
enum {
#if CFG_TUD_VENDOR > 0
VND_CFG = 0,
VND_N_CFG = 0,
#endif
VND_N__NITF

View File

@ -13,10 +13,15 @@
static bool cs_asserted;
static uint32_t freq;
static enum serprog_flags sflags;
void sp_spi_init(void) {
cs_asserted = false;
spi_init(PINOUT_SPI_DEV, 512 * 1000); // default to 512 kHz
freq = 512*1000; // default to 512 kHz
sflags = 0; // CPOL 0, CPHA 0, 8bit
spi_init(PINOUT_SPI_DEV, freq);
gpio_set_function(PINOUT_SPI_MISO, GPIO_FUNC_SPI);
gpio_set_function(PINOUT_SPI_MOSI, GPIO_FUNC_SPI);
@ -32,6 +37,8 @@ void sp_spi_init(void) {
}
void sp_spi_deinit(void) {
cs_asserted = false;
sflags = 0;
freq = 512*1000;
gpio_set_function(PINOUT_SPI_MISO, GPIO_FUNC_NULL);
gpio_set_function(PINOUT_SPI_MOSI, GPIO_FUNC_NULL);
@ -43,32 +50,52 @@ void sp_spi_deinit(void) {
spi_deinit(PINOUT_SPI_DEV);
}
uint32_t __not_in_flash_func(sp_spi_set_freq)(uint32_t freq_wanted) {
return spi_set_baudrate(PINOUT_SPI_DEV, freq_wanted);
freq = spi_set_baudrate(PINOUT_SPI_DEV, freq_wanted);
return freq;
}
void __not_in_flash_func(sp_spi_cs_deselect)(void) {
void __not_in_flash_func(sp_spi_set_flags)(enum serprog_flags flags) {
sflags = flags;
spi_set_format(PINOUT_SPI_DEV, (flags & S_FLG_16BIT) ? 16 : 8,
(flags & S_FLG_CPOL) ? SPI_CPOL_1 : SPI_CPOL_0,
(flags & S_FLG_CPHA) ? SPI_CPHA_1 : SPI_CPHA_0,
SPI_MSB_FIRST);
}
__attribute__((__const__))
int __not_in_flash_func(sp_spi_get_num_cs)(void) { return 1; }
void __not_in_flash_func(sp_spi_cs_deselect)(uint8_t csflags) {
(void)csflags;
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_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) {
void __not_in_flash_func(sp_spi_cs_select)(uint8_t csflags) {
(void)csflags;
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_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) {
// sp_spi_cs_select();
void __not_in_flash_func(sp_spi_op_begin)(uint8_t csflags) {
// sp_spi_cs_select(csflags);
(void)csflags;
if (!cs_asserted) {
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 0);
asm volatile("nop\nnop\nnop"); // idk if this is needed
}
}
void __not_in_flash_func(sp_spi_op_end)(void) {
// sp_spi_cs_deselect();
void __not_in_flash_func(sp_spi_op_end)(uint8_t csflags) {
// sp_spi_cs_deselect(csflags);
(void)csflags;
if (!cs_asserted) { // YES, this condition is the intended one!
asm volatile("nop\nnop\nnop"); // idk if this is needed
gpio_put(PINOUT_SPI_nCS, 1);
@ -77,10 +104,29 @@ void __not_in_flash_func(sp_spi_op_end)(void) {
}
// TODO: use dma?
void __not_in_flash_func(sp_spi_op_write)(uint32_t write_len, const uint8_t* write_data) {
spi_write_blocking(PINOUT_SPI_DEV, write_data, write_len);
// TODO: routines for non-8/16-bit xfers??
void __not_in_flash_func(sp_spi_op_write)(uint32_t write_len, const void* write_data) {
if (sflags & S_FLG_16BIT) {
spi_write16_blocking(PINOUT_SPI_DEV, (const uint16_t*)write_data, write_len >> 1);
} else {
spi_write_blocking(PINOUT_SPI_DEV, (const uint8_t*)write_data, write_len);
}
}
void __not_in_flash_func(sp_spi_op_read)(uint32_t read_len, uint8_t* read_data) {
spi_read_blocking(PINOUT_SPI_DEV, 0, read_data, read_len);
void __not_in_flash_func(sp_spi_op_read)(uint32_t read_len, void* read_data) {
if (sflags & S_FLG_16BIT) {
spi_read16_blocking(PINOUT_SPI_DEV, 0, (uint16_t*)read_data, read_len >> 1);
} else {
spi_read_blocking(PINOUT_SPI_DEV, 0, (uint8_t*)read_data, read_len);
}
}
void __not_in_flash_func(sp_spi_op_read_write)(uint32_t len, void* read_data,
const void* write_data) {
if (sflags & S_FLG_16BIT) {
spi_write16_read16_blocking(PINOUT_SPI_DEV, (const uint16_t*)write_data,
(uint16_t*)read_data, len >> 1);
} else {
spi_write_read_blocking(PINOUT_SPI_DEV, (const uint8_t*)write_data,
(uint8_t*)read_data, len);
}
}

View File

@ -55,7 +55,7 @@ static void uart_thread_fn(void) {
}
#endif
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
static cothread_t serprogthread;
static uint8_t serprogstack[THREAD_STACK_SIZE];
@ -82,7 +82,7 @@ static void enter_cb(void) {
uartthread = co_derive(uartstack, sizeof uartstack, uart_thread_fn);
thread_enter(uartthread); // will call cdc_uart_init() on correct thread
#endif
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
serprogthread = co_derive(serprogstack, sizeof serprogstack, serprog_thread_fn);
thread_enter(serprogthread); // will call cdc_serprog_init() on correct thread
#endif
@ -95,7 +95,7 @@ static void leave_cb(void) {
#ifdef DBOARD_HAS_UART
cdc_uart_deinit();
#endif
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
cdc_serprog_deinit();
#endif
}
@ -105,7 +105,7 @@ static void task_cb(void) {
tud_task();
thread_enter(uartthread);
#endif
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
tud_task();
thread_enter(serprogthread);
#endif
@ -122,7 +122,7 @@ static void handle_cmd_cb(uint8_t cmd) {
#ifdef DBOARD_HAS_CMSISDAP
resp |= mdef_feat_cmsisdap;
#endif
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
resp |= mdef_feat_spi;
#endif
#ifdef DBOARD_HAS_I2C
@ -134,7 +134,7 @@ static void handle_cmd_cb(uint8_t cmd) {
vnd_cfg_write_resp(cfg_resp_ok, 1, &resp);
break;
case mdef_cmd_spi:
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
sp_spi_bulk_cmd();
#else
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
@ -194,7 +194,7 @@ enum {
ITF_NUM_CDC_UART_COM,
ITF_NUM_CDC_UART_DATA,
#endif
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
ITF_NUM_CDC_SERPROG_COM,
ITF_NUM_CDC_SERPROG_DATA,
#endif
@ -220,7 +220,7 @@ enum {
#ifdef DBOARD_HAS_UART
+ TUD_CDC_DESC_LEN
#endif
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
+ TUD_CDC_DESC_LEN
#endif
#ifdef USE_USBCDC_FOR_STDIO
@ -265,7 +265,7 @@ static const uint8_t desc_configuration[] = {
#if CFG_TUD_VENDOR > 0
TUD_VENDOR_DESCRIPTOR(ITF_NUM_VND_CFG, STRID_IF_VND_CFG, EPNUM_VND_CFG_OUT,
EPNUM_VND_CFG_IN, 64),
EPNUM_VND_CFG_IN, CFG_TUD_VENDOR_RX_BUFSIZE),
#endif
#if defined(DBOARD_HAS_I2C) && defined(MODE_ENABLE_I2CTINYUSB)
@ -279,18 +279,18 @@ static const uint8_t desc_configuration[] = {
#endif
#ifdef DBOARD_HAS_UART
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_UART_COM, STRID_IF_CDC_UART, EPNUM_CDC_UART_NOTIF, 64,
EPNUM_CDC_UART_OUT, EPNUM_CDC_UART_IN, 64),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_UART_COM, STRID_IF_CDC_UART, EPNUM_CDC_UART_NOTIF,
CFG_TUD_CDC_RX_BUFSIZE, EPNUM_CDC_UART_OUT, EPNUM_CDC_UART_IN, CFG_TUD_CDC_RX_BUFSIZE),
#endif
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
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),
CFG_TUD_CDC_RX_BUFSIZE, EPNUM_CDC_SERPROG_OUT, EPNUM_CDC_SERPROG_IN, CFG_TUD_CDC_RX_BUFSIZE),
#endif
#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),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_STDIO_COM, STRID_IF_CDC_STDIO, EPNUM_CDC_STDIO_NOTIF,
CFG_TUD_CDC_RX_BUFSIZE, EPNUM_CDC_STDIO_OUT, EPNUM_CDC_STDIO_IN, CFG_TUD_CDC_RX_BUFSIZE),
#endif
};
static const char* string_desc_arr[] = {

View File

@ -6,7 +6,7 @@
#include "m_default/bsp-feature.h"
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
#include "info.h"
#include "util.h"
@ -20,6 +20,11 @@ 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, // 18..1f
0, // 20..27
0, // 28..2f
0, // 30..37
0x3f, // cmd 40..45
0, // rest is 0
};
// clang-format on
@ -29,10 +34,12 @@ static uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE];
static uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE];
static uint32_t rxavail, rxpos;
static uint8_t selchip;
void cdc_serprog_init(void) {
rxavail = 0;
rxpos = 0;
selchip = 1;
sp_spi_init();
}
@ -41,9 +48,15 @@ void cdc_serprog_deinit(void) {
rxavail = 0;
rxpos = 0;
selchip = 1;
}
static uint8_t read_byte(void) {
__attribute__((__const__))
uint32_t sp_spi_get_buf_limit(void) {
return sizeof(rx_buf) - 1;
}
static uint8_t read_byte_cdc(void) {
while (rxavail <= 0) {
if (!tud_cdc_n_connected(CDC_N_SERPROG) || !tud_cdc_n_available(CDC_N_SERPROG)) {
thread_yield();
@ -62,10 +75,13 @@ static uint8_t read_byte(void) {
return rv;
}
static void handle_cmd(void) {
uint32_t nresp = 0;
static uint32_t nresp = 0;
static void handle_cmd(uint8_t cmd, int ud, uint8_t (*read_byte)(void),
void (*writepkt)(int ud, const uint8_t* buf, uint32_t len),
void (*flushpkt)(int ud),
void (*writehdr)(enum cfg_resp stat, uint32_t len, const void* data)) {
nresp = 0;
uint8_t cmd = read_byte();
switch (cmd) {
case S_CMD_NOP:
tx_buf[0] = S_ACK;
@ -104,17 +120,19 @@ static void handle_cmd(void) {
nresp = 2;
break;
case S_CMD_Q_WRNMAXLEN:
nresp = sp_spi_get_buf_limit();
tx_buf[0] = S_ACK;
tx_buf[1] = (sizeof(tx_buf) - 1) & 0xff;
tx_buf[2] = ((sizeof(tx_buf) - 1) >> 8) & 0xff;
tx_buf[3] = ((sizeof(tx_buf) - 1) >> 16) & 0xff;
tx_buf[1] = nresp & 0xff;
tx_buf[2] = (nresp >> 8) & 0xff;
tx_buf[3] = (nresp >> 16) & 0xff;
nresp = 4;
break;
case S_CMD_Q_RDNMAXLEN:
nresp = sp_spi_get_buf_limit();
tx_buf[0] = S_ACK;
tx_buf[1] = (sizeof(rx_buf) - 1) & 0xff;
tx_buf[2] = ((sizeof(rx_buf) - 1) >> 8) & 0xff;
tx_buf[3] = ((sizeof(rx_buf) - 1) >> 16) & 0xff;
tx_buf[1] = nresp & 0xff;
tx_buf[2] = (nresp >> 8) & 0xff;
tx_buf[3] = (nresp >> 16) & 0xff;
nresp = 4;
break;
case S_CMD_S_BUSTYPE:
@ -126,58 +144,6 @@ static void handle_cmd(void) {
nresp = 1;
break;
case S_CMD_SPIOP: {
uint32_t slen, rlen;
// clang-format off
slen = (uint32_t)read_byte();
slen |= (uint32_t)read_byte() << 8;
slen |= (uint32_t)read_byte() << 16;
rlen = (uint32_t)read_byte();
rlen |= (uint32_t)read_byte() << 8;
rlen |= (uint32_t)read_byte() << 16;
// clang-format on
sp_spi_op_begin();
size_t this_batch;
// 1. write slen data bytes
// we're going to use the tx buf for all operations here
while (slen > 0) {
this_batch = sizeof(tx_buf);
if (this_batch > slen) this_batch = slen;
for (size_t i = 0; i < this_batch; ++i) tx_buf[i] = read_byte();
sp_spi_op_write(this_batch, tx_buf);
slen -= this_batch;
}
// 2. write data
// first, do a batch of 63, because we also need to send an ACK byte
this_batch = sizeof(tx_buf) - 1;
if (this_batch > rlen) this_batch = rlen;
sp_spi_op_read(this_batch, &tx_buf[1]);
tx_buf[0] = S_ACK;
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, this_batch + 1);
rlen -= this_batch;
// now do in batches of 64
while (rlen > 0) {
this_batch = sizeof(tx_buf);
if (this_batch > rlen) this_batch = rlen;
sp_spi_op_read(this_batch, tx_buf);
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, this_batch);
rlen -= this_batch;
}
tud_cdc_n_write_flush(CDC_N_SERPROG);
// that's it!
sp_spi_op_end();
nresp = 0; // we sent our own response manually
} break;
case S_CMD_S_SPI_FREQ: {
uint32_t freq;
// clang-format off
@ -198,19 +164,134 @@ static void handle_cmd(void) {
} break;
case S_CMD_S_PINSTATE: {
if (read_byte() == 0)
sp_spi_cs_deselect();
sp_spi_cs_deselect(selchip);
else
sp_spi_cs_select();
sp_spi_cs_select(selchip);
tx_buf[0] = S_ACK;
nresp = 1;
} break;
case S_CMD_Q_NUM_CS:
tx_buf[0] = S_ACK;
tx_buf[1] = sp_spi_get_num_cs();
nresp = 2;
break;
case S_CMD_S_SPI_FLAGS:
sp_spi_set_flags(read_byte());
tx_buf[0] = S_ACK;
nresp = 1;
break;
case S_CMD_S_SPI_CHIPN:
selchip = read_byte();
tx_buf[0] = S_ACK;
nresp = 1;
break;
case S_CMD_SPIOP: case S_CMD_SPI_READ: case S_CMD_SPI_WRITE: {
uint32_t slen, rlen;
// clang-format off
slen = (uint32_t)read_byte();
slen |= (uint32_t)read_byte() << 8;
slen |= (uint32_t)read_byte() << 16;
rlen = (uint32_t)read_byte();
rlen |= (uint32_t)read_byte() << 8;
rlen |= (uint32_t)read_byte() << 16;
// clang-format on
if (writehdr)
writehdr(cfg_resp_ok, rlen+1, NULL);
sp_spi_op_begin(selchip);
size_t this_batch;
// 1. write slen data bytes
// we're going to use the tx buf for all operations here
if (cmd == S_CMD_SPIOP || cmd == S_CMD_SPI_WRITE) {
while (slen > 0) {
this_batch = sizeof(tx_buf);
if (this_batch > slen) this_batch = slen;
for (size_t i = 0; i < this_batch; ++i) tx_buf[i] = read_byte();
sp_spi_op_write(this_batch, tx_buf);
slen -= this_batch;
}
}
// 2. read data
// first, do a batch of 63, because we also need to send an ACK byte
if (cmd == S_CMD_SPIOP || cmd == S_CMD_SPI_READ) {
this_batch = sizeof(tx_buf) - 1;
if (this_batch > rlen) this_batch = rlen;
sp_spi_op_read(this_batch, &tx_buf[1]);
tx_buf[0] = S_ACK;
writepkt(ud, tx_buf, this_batch + 1);
rlen -= this_batch;
// now do in batches of 64
while (rlen > 0) {
this_batch = sizeof(tx_buf);
if (this_batch > rlen) this_batch = rlen;
sp_spi_op_read(this_batch, tx_buf);
writepkt(ud, tx_buf, this_batch);
rlen -= this_batch;
}
flushpkt(ud);
}
// that's it!
sp_spi_op_end(selchip);
nresp = 0; // we sent our own response manually
} break;
case S_CMD_SPI_RDWR: {
uint32_t len;
// clang-format off
len = (uint32_t)read_byte();
len |= (uint32_t)read_byte() << 8;
len |= (uint32_t)read_byte() << 16;
// clang-format on
sp_spi_op_begin(selchip);
size_t this_batch;
// first, do a batch of 63, because we also need to send an ACK byte
this_batch = sizeof(tx_buf) - 1;
if (this_batch > len) this_batch = len;
for (size_t i = 0; i < this_batch; ++i) rx_buf[i] = read_byte();
sp_spi_op_read_write(this_batch, &tx_buf[1], rx_buf);
tx_buf[0] = S_ACK;
writepkt(ud, tx_buf, this_batch + 1);
len -= this_batch;
// now do in batches of 64
while (len > 0) {
this_batch = sizeof(tx_buf);
if (this_batch > len) this_batch = len;
for (size_t i = 0; i < this_batch; ++i) rx_buf[i] = read_byte();
sp_spi_op_read_write(this_batch, tx_buf, rx_buf);
writepkt(ud, tx_buf, this_batch);
len -= this_batch;
}
} break;
default:
tx_buf[0] = S_NAK;
nresp = 1;
break;
}
}
void cdc_serprog_task(void) {
uint8_t cmd = read_byte_cdc();
handle_cmd(cmd, CDC_N_SERPROG, read_byte_cdc,
tud_cdc_n_write, tud_cdc_n_write_flush, NULL);
if (nresp > 0) {
tud_cdc_n_write(CDC_N_SERPROG, tx_buf, nresp);
@ -218,12 +299,32 @@ static void handle_cmd(void) {
}
}
void cdc_serprog_task(void) { handle_cmd(); }
static void vnd_writepkt(int ud, const uint8_t* buf, uint32_t len) {
(void)ud;
for (size_t i = 0; i < len; ++i) vnd_cfg_write_byte(buf[i]);
}
static void vnd_flushpkt(int ud) {
(void)ud;
vnd_cfg_write_flush();
}
void sp_spi_bulk_cmd(void) {
// TODO
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
uint8_t cmd = read_byte_cdc();
handle_cmd(cmd, VND_N_CFG, vnd_cfg_read_byte, vnd_writepkt, vnd_flushpkt,
vnd_cfg_write_resp);
if (nresp > 0) {
enum cfg_resp stat = cfg_resp_ok;
if (nresp == 1 && tx_buf[0] == S_NAK) // invalid cmd
stat = cfg_resp_illcmd;
vnd_cfg_write_resp(stat, nresp, tx_buf);
} else {
// hanlded using the writehdr callback
}
}
#endif /* DBOARD_HAS_SERPROG */
#endif /* DBOARD_HAS_SPI */

View File

@ -27,35 +27,57 @@ enum serprog_cmd {
S_CMD_S_SPI_FREQ = 0x14,
S_CMD_S_PINSTATE = 0x15,
S_CMD_MAGIC_SETTINGS = 0x53
// TODO: upstream this to flashrom? could be useful to others maybe
S_CMD_Q_NUM_CS = 0x40,
S_CMD_S_SPI_FLAGS = 0x41,
// number of chip (well, bitflags) to use when asserting/deasserting the chip select line
S_CMD_S_SPI_CHIPN = 0x42,
S_CMD_SPI_READ = 0x43,
S_CMD_SPI_WRITE = 0x44,
// as opposed to S_CMD_SPIOP, this one is full-duplex instead of half-duplex
S_CMD_SPI_RDWR = 0x45,
};
enum serprog_response { S_ACK = 0x06, S_NAK = 0x15 };
enum serprog_flags {
S_FLG_CPOL = 1<<0, // 1: clock polarity 1, else clkpol 0
S_FLG_CPHA = 1<<1, // 1: clock phase 1, else clkpha 1
S_FLG_16BIT = 1<<2, // 1: 16-bit transfers, else 8-bit xfers
};
#define SERPROG_IFACE_VERSION 0x0001
#ifdef DBOARD_HAS_SERPROG
#ifdef DBOARD_HAS_SPI
/* functions to be implemented by the BSP */
uint32_t /*freq_applied*/ sp_spi_set_freq(uint32_t freq_wanted);
void sp_spi_set_flags(enum serprog_flags flags);
__attribute__((__const__)) int sp_spi_get_num_cs(void);
void sp_spi_init(void);
void sp_spi_deinit(void);
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);
void sp_spi_cs_deselect(uint8_t csflags);
void sp_spi_cs_select(uint8_t csflags);
static inline void sp_spi_op_do(
uint32_t write_len, const uint8_t* write_data, uint32_t read_len, uint8_t* read_data) {
void sp_spi_op_write(uint32_t write_len, const void* write_data);
void sp_spi_op_read(uint32_t read_len, void* read_data);
void sp_spi_op_read_write(uint32_t len, void* read_data, const void* write_data);
/* serprog-specific */
void sp_spi_op_begin(uint8_t csflags);
void sp_spi_op_end(uint8_t csflags);
// half-duplex
/*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();
}
}*/
/* protocol handling functions */
__attribute__((__const__)) uint32_t sp_spi_get_buf_limit(void); // rdnmaxlen, wrnmaxlen
void cdc_serprog_init(void);
void cdc_serprog_deinit(void);
void cdc_serprog_task(void);

View File

@ -105,7 +105,6 @@ int tempsense_do_read(int length, uint8_t* buf) {
int i;
for (i = 0; i < length; ++i, ++index) {
switch (reg) {
// TODO: big or little endian? seems to be big
case cap: buf[index] = 0; break;
case config:
if (index == 0)
@ -273,21 +272,25 @@ void tempsense_bulk_cmd(void) {
resp[0] = temp & 0xff;
resp[1] = (temp >> 8) & 0xff;
vnd_cfg_write_resp(cfg_resp_ok, 2, resp);
break;
case tcmd_get_lower:
temp = tempsense_dev_get_lower();
resp[0] = temp & 0xff;
resp[1] = (temp >> 8) & 0xff;
vnd_cfg_write_resp(cfg_resp_ok, 2, resp);
break;
case tcmd_get_upper:
temp = tempsense_dev_get_upper();
resp[0] = temp & 0xff;
resp[1] = (temp >> 8) & 0xff;
vnd_cfg_write_resp(cfg_resp_ok, 2, resp);
break;
case tcmd_get_crit:
temp = tempsense_dev_get_crit();
resp[0] = temp & 0xff;
resp[1] = (temp >> 8) & 0xff;
vnd_cfg_write_resp(cfg_resp_ok, 2, resp);
break;
default:
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
break;

View File

@ -259,7 +259,7 @@ void i2ctu_bulk_cmd(void) {
handle_read(&cmd);
us = cmd.len;
if (us > sizeof txbuf) us = sizeof txbuf;
vnd_cfg_write_resp(cfg_resp_ok, us, txbuf);
vnd_cfg_write_resp(cfg_resp_ok, (uint32_t)us, txbuf);
} else if (cmd.len == 0) {
handle_probe(&cmd);
txbuf[0] = status;

View File

@ -52,7 +52,7 @@ void modes_switch(uint8_t newmode);
extern int mode_current_id;
extern int mode_next_id;
extern const struct mode* mode_list[16];
extern const struct mode* const mode_list[16];
#define mode_default (mode_list[1])
#define mode_current (((mode_current_id)==-1)?NULL:(mode_list[mode_current_id]))

View File

@ -1,13 +1,15 @@
// vim: set et:
#include <assert.h>
#include "mode.h"
extern struct mode m_01_default/*, m_02_default2*/;
// clang-format off
const struct mode* mode_list[16] = {
const struct mode* const mode_list[16] = {
NULL, // dummy 0 entry
&m_01_default,
&m_01_default, // entry 1 CANNOT be NULL!
//&m_02_default2,
NULL, // terminating entry
};
@ -36,7 +38,7 @@ void modes_init(void) {
mode_current_id = &mode_default - mode_list;
mode_next_id = -1;
if (!mode_default) return; // TODO: panic here
//if (!mode_default) return;
// clang-format off
#if CFG_TUD_HID > 0

View File

@ -56,19 +56,28 @@ void vnd_cfg_write_byte(uint8_t v) {
tx_buf[txpos] = v;
++txpos;
}
void vnd_cfg_write_resp(enum cfg_resp stat, uint16_t len, const void* data) {
if (len > 0x7fff) len = 0x7fff; // aaaaaaaaaaaaaaaaa // TODO: throw some kind of error
vnd_cfg_write_byte(stat);
if (len < 0x80) {
vnd_cfg_write_byte(len);
} else {
vnd_cfg_write_byte((len & 0x7f) | 0x80);
vnd_cfg_write_byte(len >> 7);
void vnd_cfg_write_resp(enum cfg_resp stat, uint32_t len, const void* data) {
if (len > 0x3fffff) {
printf("W: truncating response length from 0x%lx to 0x3fffff\n", len);
len = 0x3fffff;
}
for (size_t i = 0; i < len; ++i) {
vnd_cfg_write_byte(((const uint8_t*)data)[i]);
vnd_cfg_write_byte(stat);
if (len < (1<<7)) {
vnd_cfg_write_byte(len);
} else if (len < (1<<14)) {
vnd_cfg_write_byte((len & 0x7f) | 0x80);
vnd_cfg_write_byte((len >> 7) & 0x7f);
} else {
vnd_cfg_write_byte((len & 0x7f) | 0x80);
vnd_cfg_write_byte(((len >> 7) & 0x7f) | 0x80);
vnd_cfg_write_byte(((len >> 14) & 0x7f));
}
if (data) {
for (size_t i = 0; i < len; ++i) {
vnd_cfg_write_byte(((const uint8_t*)data)[i]);
}
}
vnd_cfg_write_flush();

View File

@ -43,7 +43,7 @@ enum cfg_resp {
uint8_t vnd_cfg_read_byte (void);
void vnd_cfg_write_flush(void);
void vnd_cfg_write_byte(uint8_t v);
void vnd_cfg_write_resp(enum cfg_resp stat, uint16_t len, const void* data);
void vnd_cfg_write_resp(enum cfg_resp stat, uint32_t len, const void* data);
/*
* wire protocol: