Skip to content

Commit

Permalink
fw: Minimal CDC implementation of new framing protocol
Browse files Browse the repository at this point in the history
Throwing away mode and length from incoming data. Adding mode and
length to outgoing data.

Splitting responses into frames small enough for the USB<->UART
transceiver to handle.
  • Loading branch information
agren committed Sep 23, 2024
1 parent f9feb2e commit a442672
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 13 deletions.
9 changes: 7 additions & 2 deletions hw/application_fpga/fw/tk1/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,12 +412,16 @@ int main(void)
/*@+mustfreeonly@*/
ctx.use_uss = FALSE;

uint8_t mode = 0;
uint8_t mode_bytes_left = 0;

scramble_ram();

for (;;) {
switch (state) {
case FW_STATE_INITIAL:
if (readcommand(&hdr, cmd, state) == -1) {
if (readcommand(&hdr, cmd, state, &mode,
&mode_bytes_left) == -1) {
state = FW_STATE_FAIL;
break;
}
Expand All @@ -426,7 +430,8 @@ int main(void)
break;

case FW_STATE_LOADING:
if (readcommand(&hdr, cmd, state) == -1) {
if (readcommand(&hdr, cmd, state, &mode,
&mode_bytes_left) == -1) {
state = FW_STATE_FAIL;
break;
}
Expand Down
53 changes: 44 additions & 9 deletions hw/application_fpga/fw/tk1/proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ static uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status,
enum cmdlen len);
static int parseframe(uint8_t b, struct frame_header *hdr);
static void write(uint8_t *buf, size_t nbytes);
static int read(uint8_t *buf, size_t bufsize, size_t nbytes);
static int read(uint8_t *buf, size_t bufsize, size_t nbytes, uint8_t *mode,
uint8_t *mode_bytes_left);
static int bytelen(enum cmdlen cmdlen);

static uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status,
Expand All @@ -31,12 +32,13 @@ static uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status,
return (id << 5) | (endpoint << 3) | (status << 2) | len;
}

int readcommand(struct frame_header *hdr, uint8_t *cmd, int state)
int readcommand(struct frame_header *hdr, uint8_t *cmd, int state,
uint8_t *mode, uint8_t *mode_bytes_left)
{
uint8_t in = 0;

set_led((state == FW_STATE_LOADING) ? LED_BLACK : LED_WHITE);
in = readbyte();
in = readbyte(mode, mode_bytes_left);

if (parseframe(in, hdr) == -1) {
htif_puts("Couldn't parse header\n");
Expand All @@ -45,7 +47,7 @@ int readcommand(struct frame_header *hdr, uint8_t *cmd, int state)

(void)memset(cmd, 0, CMDLEN_MAXBYTES);
// Now we know the size of the cmd frame, read it all
if (read(cmd, CMDLEN_MAXBYTES, hdr->len) != 0) {
if (read(cmd, CMDLEN_MAXBYTES, hdr->len, mode, mode_bytes_left) != 0) {
htif_puts("read: buffer overrun\n");
return -1;
}
Expand Down Expand Up @@ -115,14 +117,30 @@ void fwreply(struct frame_header hdr, enum fwcmd rspcode, uint8_t *buf)

nbytes = bytelen(len);

// Mode Protocol Header
writebyte(MODE_CDC);
writebyte(2);

// Frame Protocol Header
writebyte(genhdr(hdr.id, hdr.endpoint, 0x0, len));

// FW protocol header
writebyte(rspcode);
nbytes--;

write(buf, nbytes);
while (nbytes > 0) {
// Limit transers to 64 bytes (2 byte header + 62 byte data) to
// fit in a single USB frame.
size_t tx_count = nbytes > 62 ? 62 : nbytes;
// Mode Protocol Header
writebyte(MODE_CDC);
writebyte(tx_count & 0xff);

// Data
write(buf, tx_count);
nbytes -= tx_count;
buf += tx_count;
}
}

void writebyte(uint8_t b)
Expand All @@ -142,23 +160,40 @@ static void write(uint8_t *buf, size_t nbytes)
}
}

uint8_t readbyte(void)
uint8_t readbyte_(void)
{
for (;;) {
if (*can_rx) {
return *rx;
uint32_t b = *rx;
return b;
}
}
}

uint8_t readbyte(uint8_t *mode, uint8_t *mode_bytes_left)
{
if (*mode_bytes_left == 0) {
*mode = readbyte_();
if (*mode != MODE_CDC) {
htif_puts("We only support MODE_CDC\n");
} else {
*mode_bytes_left = readbyte_();
}
}
uint8_t b = readbyte_();
*mode_bytes_left -= 1;
return b;
}

static int read(uint8_t *buf, size_t bufsize, size_t nbytes)
static int read(uint8_t *buf, size_t bufsize, size_t nbytes, uint8_t *mode,
uint8_t *mode_bytes_left)
{
if (nbytes > bufsize) {
return -1;
}

for (int n = 0; n < nbytes; n++) {
buf[n] = readbyte();
buf[n] = readbyte(mode, mode_bytes_left);
}

return 0;
Expand Down
9 changes: 7 additions & 2 deletions hw/application_fpga/fw/tk1/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
#ifndef PROTO_H
#define PROTO_H

enum mode {
MODE_CDC = 0x40,
MODE_HID = 0x80,
};

enum endpoints {
DST_HW_IFPGA,
DST_HW_AFPGA,
Expand Down Expand Up @@ -52,7 +57,7 @@ struct frame_header {

/*@ -exportlocal @*/
void writebyte(uint8_t b);
uint8_t readbyte(void);
uint8_t readbyte(uint8_t *mode, uint8_t *mode_bytes_left);
void fwreply(struct frame_header hdr, enum fwcmd rspcode, uint8_t *buf);
int readcommand(struct frame_header *hdr, uint8_t *cmd, int state);
int readcommand(struct frame_header *hdr, uint8_t *cmd, int state, uint8_t *mode, uint8_t *mode_bytes_left);
#endif

0 comments on commit a442672

Please sign in to comment.