fixed USB problem

This commit is contained in:
Edward Emelianov 2024-08-26 20:47:04 +03:00
parent 3e86556206
commit 9166996bff
20 changed files with 326 additions and 240 deletions

View File

@ -390,6 +390,8 @@ Dump command codes. Returns all list of CAN bus command codes.
### dumpconf ### dumpconf
Dump current configuration. Returns a lot of information both common (like CAN bus speed, ID and so on) and Dump current configuration. Returns a lot of information both common (like CAN bus speed, ID and so on) and
for each motor driver. You can call independeng getters for each of this parameter. for each motor driver. You can call independeng getters for each of this parameter.
### dumpmotN
Dump configuration of Nth motor only.
### dumpmotflags ### dumpmotflags
Dump motor flags' bits (for `motflagsN`) and reaction to limit switches (`eswreact`) values: Dump motor flags' bits (for `motflagsN`) and reaction to limit switches (`eswreact`) values:

View File

@ -20,8 +20,8 @@
#include <stdint.h> #include <stdint.h>
// amount of filter banks in STM32F0 // amount of filter banks in STM32F
#define STM32F0FBANKNO 28 #define STM32FBANKNO 28
// flood period in milliseconds // flood period in milliseconds
#define FLOOD_PERIOD_MS 5 #define FLOOD_PERIOD_MS 5

View File

@ -200,6 +200,33 @@ int erase_storage(int npage){
return ret; return ret;
} }
int fn_dumpmot(uint32_t _U_ hash, char _U_ *args){ // "dumpmot" (1224122507)
if(!args || !*args) return RET_WRONGCMD;
uint32_t i;
const char *eq = getnum(args, &i);
if(eq == args || i > STP_STATE_AMOUNT) return RET_WRONGCMD;
char cur = '0' + i;
#define PROPNAME(nm) do{newline(); USB_sendstr(nm); USB_putbyte(cur); USB_putbyte('=');}while(0)
USB_sendstr("microsteps"); USB_putbyte(cur); USB_putbyte('=');
printu(the_conf.microsteps[i]);
PROPNAME("accel");
printu(the_conf.accel[i]);
PROPNAME("maxspeed");
printu(the_conf.maxspd[i]);
PROPNAME("minspeed");
printu(the_conf.minspd[i]);
PROPNAME("maxsteps");
printu(the_conf.maxsteps[i]);
PROPNAME("motcurrent");
printu(the_conf.motcurrent[i]);
PROPNAME("motflags");
printuhex(*((uint8_t*)&the_conf.motflags[i]));
PROPNAME("eswreact");
printu(the_conf.ESW_reaction[i]);
#undef PROPNAME
newline();
return RET_GOOD;
}
int fn_dumpconf(uint32_t _U_ hash, char _U_ *args){ // "dumpconf" (3271513185) int fn_dumpconf(uint32_t _U_ hash, char _U_ *args){ // "dumpconf" (3271513185)
#ifdef EBUG #ifdef EBUG
@ -212,28 +239,12 @@ int fn_dumpconf(uint32_t _U_ hash, char _U_ *args){ // "dumpconf" (3271513185)
USB_sendstr("\nuserconf_sz="); printu(the_conf.userconf_sz); USB_sendstr("\nuserconf_sz="); printu(the_conf.userconf_sz);
USB_sendstr("\ncanspeed="); printu(the_conf.CANspeed); USB_sendstr("\ncanspeed="); printu(the_conf.CANspeed);
USB_sendstr("\ncanid="); printu(the_conf.CANID); USB_sendstr("\ncanid="); printu(the_conf.CANID);
newline();
char x[2] = {0};
// motors' data // motors' data
for(int i = 0; i < MOTORSNO; ++i){ for(int i = 0; i < MOTORSNO; ++i){
char cur = '0' + i; x[0] = '0' + i;
#define PROPNAME(nm) do{newline(); USB_sendstr(nm); USB_putbyte(cur); USB_putbyte('=');}while(0) fn_dumpmot(0, x);
PROPNAME("microsteps");
printu(the_conf.microsteps[i]);
PROPNAME("accel");
printu(the_conf.accel[i]);
PROPNAME("maxspeed");
printu(the_conf.maxspd[i]);
PROPNAME("minspeed");
printu(the_conf.minspd[i]);
PROPNAME("maxsteps");
printu(the_conf.maxsteps[i]);
PROPNAME("motcurrent");
printu(the_conf.motcurrent[i]);
PROPNAME("motflags");
printuhex(*((uint8_t*)&the_conf.motflags[i]));
PROPNAME("eswreact");
printu(the_conf.ESW_reaction[i]);
#undef PROPNAME
} }
newline();
return RET_GOOD; return RET_GOOD;
} }

View File

@ -56,6 +56,8 @@ int fn_dumpconf(uint32_t _U_ hash, char _U_ *args) WAL; // "dumpconf" (327151318
int fn_dumperr(uint32_t _U_ hash, char _U_ *args) WAL; // "dumperr" (1223989764) int fn_dumperr(uint32_t _U_ hash, char _U_ *args) WAL; // "dumperr" (1223989764)
int fn_dumpmot(uint32_t _U_ hash, char _U_ *args) WAL; // "dumpmot" (1224122507)
int fn_dumpmotflags(uint32_t _U_ hash, char _U_ *args) WAL; // "dumpmotflags" (36159640) int fn_dumpmotflags(uint32_t _U_ hash, char _U_ *args) WAL; // "dumpmotflags" (36159640)
int fn_dumpstates(uint32_t _U_ hash, char _U_ *args) WAL; // "dumpstates" (4235564367) int fn_dumpstates(uint32_t _U_ hash, char _U_ *args) WAL; // "dumpstates" (4235564367)
@ -216,6 +218,9 @@ int parsecmd(const char *str){
case CMD_DUMPERR: case CMD_DUMPERR:
return fn_dumperr(h, args); return fn_dumperr(h, args);
break; break;
case CMD_DUMPMOT:
return fn_dumpmot(h, args);
break;
case CMD_DUMPMOTFLAGS: case CMD_DUMPMOTFLAGS:
return fn_dumpmotflags(h, args); return fn_dumpmotflags(h, args);
break; break;

View File

@ -38,6 +38,7 @@ extern char lastcmd[];
#define CMD_DUMPCMD (1223955823) #define CMD_DUMPCMD (1223955823)
#define CMD_DUMPCONF (3271513185) #define CMD_DUMPCONF (3271513185)
#define CMD_DUMPERR (1223989764) #define CMD_DUMPERR (1223989764)
#define CMD_DUMPMOT (1224122507)
#define CMD_DUMPMOTFLAGS (36159640) #define CMD_DUMPMOTFLAGS (36159640)
#define CMD_DUMPSTATES (4235564367) #define CMD_DUMPSTATES (4235564367)
#define CMD_EMSTOP (2965919005) #define CMD_EMSTOP (2965919005)

View File

@ -20,6 +20,7 @@
"dumperr - dump error codes\n" "dumperr - dump error codes\n"
"dumpcmd - dump command codes\n" "dumpcmd - dump command codes\n"
"dumpconf - dump current configuration\n" "dumpconf - dump current configuration\n"
"dumpmotN - dump Nth motor configuration\n"
"dumpmotflags - dump motor flags' bits\n" "dumpmotflags - dump motor flags' bits\n"
"dumpstates - dump motors' state codes\n" "dumpstates - dump motors' state codes\n"
"emstop[N] - emergency stop motor N or all\n" "emstop[N] - emergency stop motor N or all\n"

Binary file not shown.

View File

@ -20,6 +20,7 @@ drvtype
dumperr dumperr
dumpcmd dumpcmd
dumpconf dumpconf
dumpmot
dumpmotflags dumpmotflags
dumpstates dumpstates
emstop emstop

View File

@ -45,11 +45,11 @@ int main(void){
hw_setup(); // GPIO, ADC, timers, watchdog etc. hw_setup(); // GPIO, ADC, timers, watchdog etc.
USBPU_OFF(); // make a reconnection USBPU_OFF(); // make a reconnection
flashstorage_init(); flashstorage_init();
init_steppers();
USB_setup(); USB_setup();
CAN_setup(the_conf.CANspeed); CAN_setup(the_conf.CANspeed);
adc_setup(); adc_setup();
pdnuart_setup(); pdnuart_setup();
init_steppers();
USBPU_ON(); USBPU_ON();
uint32_t ctr = 0; uint32_t ctr = 0;
CAN_message *can_mesg; CAN_message *can_mesg;
@ -60,10 +60,9 @@ int main(void){
LED_blink(); LED_blink();
} }
CAN_proc(); CAN_proc();
USB_proc(); // TODO: remove deprecated trash code!
process_steppers(); process_steppers();
if(CAN_get_status() == CAN_FIFO_OVERRUN){ if(CAN_get_status() == CAN_FIFO_OVERRUN){
USB_sendstr("CAN bus fifo overrun occured!\n"); USB_sendstr("CAN_FIFO_OVERRUN\n");
} }
while((can_mesg = CAN_messagebuf_pop())){ while((can_mesg = CAN_messagebuf_pop())){
if(can_mesg && isgood(can_mesg->ID)){ if(can_mesg && isgood(can_mesg->ID)){
@ -82,8 +81,13 @@ int main(void){
} }
} }
int l = USB_receivestr(inbuff, MAXSTRLEN); int l = USB_receivestr(inbuff, MAXSTRLEN);
if(l < 0) USB_sendstr("ERROR: USB buffer overflow or string was too long\n"); if(l < 0) USB_sendstr("USB_BUF_OVERFLOW\n");
else if(l){ else if(l){
#ifdef EBUG
USB_sendstr("USB GOT:\n");
USB_sendstr(inbuff);
USB_sendstr("\n--------\n");
#endif
const char *ans = cmd_parser(inbuff); const char *ans = cmd_parser(inbuff);
if(ans) USB_sendstr(ans); if(ans) USB_sendstr(ans);
} }

View File

@ -205,7 +205,7 @@ static void add_filter(const char *str){
USB_sendstr("No bank# given"); USB_sendstr("No bank# given");
return; return;
} }
if(N > STM32F0FBANKNO-1){ if(N > STM32FBANKNO-1){
USB_sendstr("bank# > 27"); USB_sendstr("bank# > 27");
return; return;
} }

View File

@ -18,19 +18,21 @@
#include "ringbuffer.h" #include "ringbuffer.h"
// stored data length static int datalen(ringbuffer *b){
int RB_datalen(ringbuffer *b){
if(b->tail >= b->head) return (b->tail - b->head); if(b->tail >= b->head) return (b->tail - b->head);
else return (b->length - b->head + b->tail); else return (b->length - b->head + b->tail);
} }
/** // stored data length
* @brief RB_hasbyte - check if buffer has given byte stored int RB_datalen(ringbuffer *b){
* @param b - buffer if(b->busy) return -1;
* @param byte - byte to find b->busy = 1;
* @return index if found, -1 if none int l = datalen(b);
*/ b->busy = 0;
int RB_hasbyte(ringbuffer *b, uint8_t byte){ return l;
}
static int hasbyte(ringbuffer *b, uint8_t byte){
if(b->head == b->tail) return -1; // no data in buffer if(b->head == b->tail) return -1; // no data in buffer
int startidx = b->head; int startidx = b->head;
if(b->head > b->tail){ // if(b->head > b->tail){ //
@ -43,6 +45,20 @@ int RB_hasbyte(ringbuffer *b, uint8_t byte){
return -1; return -1;
} }
/**
* @brief RB_hasbyte - check if buffer has given byte stored
* @param b - buffer
* @param byte - byte to find
* @return index if found, -1 if none or busy
*/
int RB_hasbyte(ringbuffer *b, uint8_t byte){
if(b->busy) return -1;
b->busy = 1;
int ret = hasbyte(b, byte);
b->busy = 0;
return ret;
}
// poor memcpy // poor memcpy
static void mcpy(uint8_t *targ, const uint8_t *src, int l){ static void mcpy(uint8_t *targ, const uint8_t *src, int l){
while(l--) *targ++ = *src++; while(l--) *targ++ = *src++;
@ -54,15 +70,8 @@ TRUE_INLINE void incr(ringbuffer *b, volatile int *what, int n){
if(*what >= b->length) *what -= b->length; if(*what >= b->length) *what -= b->length;
} }
/** static int read(ringbuffer *b, uint8_t *s, int len){
* @brief RB_read - read data from ringbuffer int l = datalen(b);
* @param b - buffer
* @param s - array to write data
* @param len - max len of `s`
* @return bytes read
*/
int RB_read(ringbuffer *b, uint8_t *s, int len){
int l = RB_datalen(b);
if(!l) return 0; if(!l) return 0;
if(l > len) l = len; if(l > len) l = len;
int _1st = b->length - b->head; int _1st = b->length - b->head;
@ -78,33 +87,49 @@ int RB_read(ringbuffer *b, uint8_t *s, int len){
return _1st; return _1st;
} }
/**
* @brief RB_read - read data from ringbuffer
* @param b - buffer
* @param s - array to write data
* @param len - max len of `s`
* @return bytes read or -1 if busy
*/
int RB_read(ringbuffer *b, uint8_t *s, int len){
if(b->busy) return -1;
b->busy = 1;
int r = read(b, s, len);
b->busy = 0;
return r;
}
static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){
int idx = hasbyte(b, byte);
if(idx < 0) return 0;
int partlen = idx + 1 - b->head;
// now calculate length of new data portion
if(idx < b->head) partlen += b->length;
if(partlen > len) return -read(b, s, len);
return read(b, s, partlen);
}
/** /**
* @brief RB_readto fill array `s` with data until byte `byte` (with it) * @brief RB_readto fill array `s` with data until byte `byte` (with it)
* @param b - ringbuffer * @param b - ringbuffer
* @param byte - check byte * @param byte - check byte
* @param s - buffer to write data * @param s - buffer to write data
* @param len - length of `s` * @param len - length of `s`
* @return amount of bytes written (negative, if len<data in buffer) * @return amount of bytes written (negative, if len<data in buffer or buffer is busy)
*/ */
int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){
int idx = RB_hasbyte(b, byte); if(b->busy) return -1;
if(idx < 0) return 0; b->busy = 1;
int partlen = idx + 1 - b->head; int n = readto(b, byte, s, len);
// now calculate length of new data portion b->busy = 0;
if(idx < b->head) partlen += b->length; return n;
if(partlen > len) return -RB_read(b, s, len);
return RB_read(b, s, partlen);
} }
/** static int write(ringbuffer *b, const uint8_t *str, int l){
* @brief RB_write - write some data to ringbuffer int r = b->length - 1 - datalen(b); // rest length
* @param b - buffer
* @param str - data
* @param l - length
* @return amount of bytes written
*/
int RB_write(ringbuffer *b, const uint8_t *str, int l){
int r = b->length - 1 - RB_datalen(b); // rest length
if(l > r) l = r; if(l > r) l = r;
if(!l) return 0; if(!l) return 0;
int _1st = b->length - b->tail; int _1st = b->length - b->tail;
@ -117,8 +142,27 @@ int RB_write(ringbuffer *b, const uint8_t *str, int l){
return l; return l;
} }
/**
* @brief RB_write - write some data to ringbuffer
* @param b - buffer
* @param str - data
* @param l - length
* @return amount of bytes written or -1 if busy
*/
int RB_write(ringbuffer *b, const uint8_t *str, int l){
if(b->busy) return -1;
b->busy = 1;
int w = write(b, str, l);
b->busy = 0;
return w;
}
// just delete all information in buffer `b` // just delete all information in buffer `b`
void RB_clearbuf(ringbuffer *b){ int RB_clearbuf(ringbuffer *b){
if(b->busy) return -1;
b->busy = 1;
b->head = 0; b->head = 0;
b->tail = 0; b->tail = 0;
b->busy = 0;
return 1;
} }

View File

@ -25,6 +25,7 @@ typedef struct{
const int length; // its length const int length; // its length
int head; // head index int head; // head index
int tail; // tail index int tail; // tail index
volatile int busy; // == TRUE if buffer is busy now
} ringbuffer; } ringbuffer;
int RB_read(ringbuffer *b, uint8_t *s, int len); int RB_read(ringbuffer *b, uint8_t *s, int len);
@ -32,4 +33,4 @@ int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len);
int RB_hasbyte(ringbuffer *b, uint8_t byte); int RB_hasbyte(ringbuffer *b, uint8_t byte);
int RB_write(ringbuffer *b, const uint8_t *str, int l); int RB_write(ringbuffer *b, const uint8_t *str, int l);
int RB_datalen(ringbuffer *b); int RB_datalen(ringbuffer *b);
void RB_clearbuf(ringbuffer *b); int RB_clearbuf(ringbuffer *b);

View File

@ -1,6 +1,6 @@
/* /*
* This file is part of the multistepper project. * This file is part of the multistepper project.
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>. * Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,27 +19,31 @@
#include <string.h> #include <string.h>
#include "hardware.h" #include "hardware.h"
#include "ringbuffer.h"
#include "usb.h" #include "usb.h"
#include "usb_lib.h" #include "usb_lib.h"
#ifdef EBUG
#include "strfunc.h"
#endif
static volatile uint8_t usbbuff[USB_TXBUFSZ]; // temporary buffer for sending data static volatile uint8_t usbbuff[USB_TXBUFSZ]; // temporary buffer for sending data
// ring buffers for incoming and outgoing data // ring buffers for incoming and outgoing data
static uint8_t obuf[RBOUTSZ], ibuf[RBINSZ]; static uint8_t obuf[RBOUTSZ], ibuf[RBINSZ];
static volatile ringbuffer out = {.data = obuf, .length = RBOUTSZ, .head = 0, .tail = 0}; volatile ringbuffer rbout = {.data = obuf, .length = RBOUTSZ, .head = 0, .tail = 0};
static volatile ringbuffer in = {.data = ibuf, .length = RBINSZ, .head = 0, .tail = 0}; volatile ringbuffer rbin = {.data = ibuf, .length = RBINSZ, .head = 0, .tail = 0};
// transmission is succesfull // inbuf overflow when receiving
static volatile uint8_t bufisempty = 1; volatile uint8_t bufovrfl = 0;
static volatile uint8_t bufovrfl = 0; // last send data size
static volatile int lastdsz = 0;
static void send_next(){ // called from transmit EP
if(bufisempty) return; void send_next(){
static int lastdsz = 0; int buflen = RB_read((ringbuffer*)&rbout, (uint8_t*)usbbuff, USB_TXBUFSZ);
int buflen = RB_read((ringbuffer*)&out, (uint8_t*)usbbuff, USB_TXBUFSZ); if(buflen == 0){
if(!buflen){
if(lastdsz == 64) EP_Write(3, NULL, 0); // send ZLP after 64 bits packet when nothing more to send if(lastdsz == 64) EP_Write(3, NULL, 0); // send ZLP after 64 bits packet when nothing more to send
lastdsz = 0; lastdsz = 0;
bufisempty = 1; return;
}else if(buflen < 0){
EP_Write(3, NULL, 0); // send ZLP if buffer is in writting state now
return; return;
} }
EP_Write(3, (uint8_t*)usbbuff, buflen); EP_Write(3, (uint8_t*)usbbuff, buflen);
@ -48,44 +52,42 @@ static void send_next(){
// blocking send full content of ring buffer // blocking send full content of ring buffer
int USB_sendall(){ int USB_sendall(){
while(!bufisempty){ while(lastdsz > 0){
if(!usbON) return 0; if(!usbON) return FALSE;
} }
return 1; return TRUE;
} }
// put `buf` into queue to send // put `buf` into queue to send
int USB_send(const uint8_t *buf, int len){ int USB_send(const uint8_t *buf, int len){
if(!buf || !usbON || !len) return 0; if(!buf || !usbON || !len) return FALSE;
while(len){ while(len){
int a = RB_write((ringbuffer*)&out, buf, len); int a = RB_write((ringbuffer*)&rbout, buf, len);
len -= a; if(a > 0){
buf += a; len -= a;
if(bufisempty){ buf += a;
bufisempty = 0; } else if (a < 0) continue; // do nothing if buffer is in reading state
send_next(); if(lastdsz == 0) send_next(); // need to run manually - all data sent, so no IRQ on IN
}
} }
return 1; return TRUE;
} }
int USB_putbyte(uint8_t byte){ int USB_putbyte(uint8_t byte){
if(!usbON) return 0; if(!usbON) return FALSE;
while(0 == RB_write((ringbuffer*)&out, &byte, 1)){ int l = 0;
if(bufisempty){ while((l = RB_write((ringbuffer*)&rbout, &byte, 1)) != 1){
bufisempty = 0; if(l < 0) continue;
send_next();
}
} }
return 1; if(lastdsz == 0) send_next(); // need to run manually - all data sent, so no IRQ on IN
return TRUE;
} }
int USB_sendstr(const char *string){ int USB_sendstr(const char *string){
if(!string || !usbON) return 0; if(!string || !usbON) return FALSE;
int len = 0; int len = 0;
const char *b = string; const char *b = string;
while(*b++) ++len; while(*b++) ++len;
if(!len) return 0; if(!len) return FALSE;
return USB_send((const uint8_t*)string, len); return USB_send((const uint8_t*)string, len);
} }
@ -96,13 +98,14 @@ int USB_sendstr(const char *string){
* @return amount of received bytes (negative, if overfull happened) * @return amount of received bytes (negative, if overfull happened)
*/ */
int USB_receive(uint8_t *buf, int len){ int USB_receive(uint8_t *buf, int len){
int sz = RB_read((ringbuffer*)&in, buf, len); chkin();
if(bufovrfl){ if(bufovrfl){
RB_clearbuf((ringbuffer*)&in); while(1 != RB_clearbuf((ringbuffer*)&rbin));
if(!sz) sz = -1;
else sz = -sz;
bufovrfl = 0; bufovrfl = 0;
return -1;
} }
int sz = RB_read((ringbuffer*)&rbin, buf, len);
if(sz < 0) return 0; // buffer in writting state
return sz; return sz;
} }
@ -113,65 +116,25 @@ int USB_receive(uint8_t *buf, int len){
* @return strlen or negative value indicating overflow (if so, string won't be ends with 0 and buffer should be cleared) * @return strlen or negative value indicating overflow (if so, string won't be ends with 0 and buffer should be cleared)
*/ */
int USB_receivestr(char *buf, int len){ int USB_receivestr(char *buf, int len){
int l = RB_readto((ringbuffer*)&in, '\n', (uint8_t*)buf, len); chkin();
if(l == 0) return 0;
if(--l < 0 || bufovrfl) RB_clearbuf((ringbuffer*)&in);
else buf[l] = 0; // replace '\n' with strend
if(bufovrfl){ if(bufovrfl){
if(l > 0) l = -l; while(1 != RB_clearbuf((ringbuffer*)&rbin));
else l = -1;
bufovrfl = 0; bufovrfl = 0;
return -1;
} }
int l = RB_readto((ringbuffer*)&rbin, '\n', (uint8_t*)buf, len);
if(l < 1){
if(rbin.length == RB_datalen((ringbuffer*)&rbin)){ // buffer is full but no '\n' found
while(1 != RB_clearbuf((ringbuffer*)&rbin));
return -1;
}
return 0;
}
#ifdef EBUG
USB_sendstr("readto, l="); USB_sendstr(u2str(l)); newline();
#endif
if(l == 0) return 0;
buf[l-1] = 0; // replace '\n' with strend
return l; return l;
} }
// interrupt IN handler (never used?)
static void EP1_Handler(){
uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]);
if(RX_FLAG(epstatus)) epstatus = (epstatus & ~USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_RX; // set valid RX
else epstatus = epstatus & ~(USB_EPnR_STAT_TX|USB_EPnR_STAT_RX);
// clear CTR
epstatus = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX));
USB->EPnR[1] = epstatus;
}
// data IN/OUT handlers
static void transmit_Handler(){ // EP3IN
uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]);
// clear CTR keep DTOGs & STATs
USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr
send_next();
}
static void receive_Handler(){ // EP2OUT
uint8_t buf[USB_RXBUFSZ];
uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]);
uint8_t sz = EP_Read(2, (uint8_t*)buf);
if(sz){
if(RB_write((ringbuffer*)&in, buf, sz) != sz) bufovrfl = 1;
}
// keep stat_tx & set ACK rx, clear RX ctr
USB->EPnR[2] = (epstatus & ~USB_EPnR_CTR_RX) ^ USB_EPnR_STAT_RX;
}
void USB_proc(){
switch(USB_Dev.USB_Status){
case USB_STATE_CONFIGURED:
// make new BULK endpoint
// Buffer have 1024 bytes, but last 256 we use for CAN bus (30.2 of RM: USB main features)
EP_Init(1, EP_TYPE_INTERRUPT, USB_EP1BUFSZ, 0, EP1_Handler); // IN1 - transmit
EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, receive_Handler); // OUT2 - receive data
EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, transmit_Handler); // IN3 - transmit data
USB_Dev.USB_Status = USB_STATE_CONNECTED;
break;
case USB_STATE_DEFAULT:
case USB_STATE_ADDRESSED:
if(usbON){
usbON = 0;
}
break;
default: // USB_STATE_CONNECTED - send next data portion
// if(!usbON) return; // WTF?
break;
}
}

View File

@ -1,6 +1,6 @@
/* /*
* This file is part of the multistepper project. * This file is part of the multistepper project.
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>. * Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -18,11 +18,12 @@
#pragma once #pragma once
#include "ringbuffer.h"
#include "usbhw.h" #include "usbhw.h"
// sizes of ringbuffers for outgoing and incoming data // sizes of ringbuffers for outgoing and incoming data
#define RBOUTSZ (512) #define RBOUTSZ (512)
#define RBINSZ (512) #define RBINSZ (256)
#define newline() USB_putbyte('\n') #define newline() USB_putbyte('\n')
#define USND(s) do{USB_sendstr(s); USB_putbyte('\n');}while(0) #define USND(s) do{USB_sendstr(s); USB_putbyte('\n');}while(0)
@ -36,7 +37,10 @@
#define DBG(str) #define DBG(str)
#endif #endif
void USB_proc(); extern volatile ringbuffer rbout, rbin;
extern volatile uint8_t bufisempty, bufovrfl;
void send_next();
int USB_sendall(); int USB_sendall();
int USB_send(const uint8_t *buf, int len); int USB_send(const uint8_t *buf, int len);
int USB_putbyte(uint8_t byte); int USB_putbyte(uint8_t byte);

View File

@ -1,6 +1,6 @@
/* /*
* This file is part of the multistepper project. * This file is part of the multistepper project.
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>. * Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -17,14 +17,16 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include "usb.h"
#include "usb_lib.h" #include "usb_lib.h"
#include "usbhw.h"
ep_t endpoints[STM32ENDPOINTS]; ep_t endpoints[STM32ENDPOINTS];
usb_dev_t USB_Dev; static uint16_t USB_Addr = 0;
static usb_LineCoding lineCoding = {115200, 0, 0, 8}; static usb_LineCoding lineCoding = {115200, 0, 0, 8};
config_pack_t setup_packet; uint8_t ep0databuf[EP0DATABUF_SIZE], setupdatabuf[EP0DATABUF_SIZE];
uint8_t ep0databuf[EP0DATABUF_SIZE]; config_pack_t *setup_packet = (config_pack_t*) setupdatabuf;
usb_LineCoding getLineCoding(){return lineCoding;} usb_LineCoding getLineCoding(){return lineCoding;}
@ -53,9 +55,9 @@ static const uint8_t USB_DeviceDescriptor[] = {
0x23, // idProduct_H 0x23, // idProduct_H
0x00, // bcdDevice_Ver_L 0x00, // bcdDevice_Ver_L
0x03, // bcdDevice_Ver_H 0x03, // bcdDevice_Ver_H
0x01, // iManufacturer iMANUFACTURER_DESCR, // iManufacturer
0x02, // iProduct iPRODUCT_DESCR, // iProduct
0x00, // iSerialNumber iSERIAL_DESCR, // iSerialNumber
bNumConfigurations // bNumConfigurations bNumConfigurations // bNumConfigurations
}; };
@ -95,7 +97,7 @@ static const uint8_t USB_ConfigDescriptor[] = {
0xff, /* bInterfaceClass */ 0xff, /* bInterfaceClass */
0x00, /* bInterfaceSubClass */ 0x00, /* bInterfaceSubClass */
0x00, /* bInterfaceProtocol */ 0x00, /* bInterfaceProtocol */
0x00, /* iInterface: */ iINTERFACE_DESCR, /* iInterface: */
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
/*Endpoint 1 Descriptor*/ /*Endpoint 1 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */ 0x07, /* bLength: Endpoint Descriptor size */
@ -125,11 +127,19 @@ static const uint8_t USB_ConfigDescriptor[] = {
0x00, /* bInterval: ignore for Bulk transfer */ 0x00, /* bInterval: ignore for Bulk transfer */
}; };
_USB_LANG_ID_(USB_StringLangDescriptor, LANG_US); _USB_LANG_ID_(LD, LANG_US);
// these descriptors are not used in PL2303 emulator! _USB_STRING_(SD, u"0.0.1");
_USB_STRING_(USB_StringSerialDescriptor, u"0"); _USB_STRING_(MD, u"Prolific Technology Inc.");
_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc."); _USB_STRING_(PD, u"USB-Serial Controller");
_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller"); _USB_STRING_(ID, u"multistepper");
static void const *StringDescriptor[iDESCR_AMOUNT] = {
[iLANGUAGE_DESCR] = &LD,
[iMANUFACTURER_DESCR] = &MD,
[iPRODUCT_DESCR] = &PD,
[iSERIAL_DESCR] = &SD,
[iINTERFACE_DESCR] = &ID
};
/* /*
* default handlers * default handlers
@ -171,7 +181,7 @@ void WEAK vendor_handler(config_pack_t *packet){
} }
static void wr0(const uint8_t *buf, uint16_t size){ static void wr0(const uint8_t *buf, uint16_t size){
if(setup_packet.wLength < size) size = setup_packet.wLength; // shortened request if(setup_packet->wLength < size) size = setup_packet->wLength; // shortened request
if(size < endpoints[0].txbufsz){ if(size < endpoints[0].txbufsz){
EP_WriteIRQ(0, buf, size); EP_WriteIRQ(0, buf, size);
return; return;
@ -199,24 +209,18 @@ static void wr0(const uint8_t *buf, uint16_t size){
} }
static inline void get_descriptor(){ static inline void get_descriptor(){
switch(setup_packet.wValue){ uint8_t descrtype = setup_packet->wValue >> 8,
descridx = setup_packet->wValue & 0xff;
switch(descrtype){
case DEVICE_DESCRIPTOR: case DEVICE_DESCRIPTOR:
wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor)); wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor));
break; break;
case CONFIGURATION_DESCRIPTOR: case CONFIGURATION_DESCRIPTOR:
wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor)); wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor));
break; break;
case STRING_LANG_DESCRIPTOR: case STRING_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE); if(descridx < iDESCR_AMOUNT) wr0((const uint8_t *)StringDescriptor[descridx], *((uint8_t*)StringDescriptor[descridx]));
break; else EP_WriteIRQ(0, (uint8_t*)0, 0);
case STRING_MAN_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength);
break;
case STRING_PROD_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength);
break;
case STRING_SN_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength);
break; break;
case DEVICE_QUALIFIER_DESCRIPTOR: case DEVICE_QUALIFIER_DESCRIPTOR:
wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]); wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]);
@ -229,7 +233,7 @@ static inline void get_descriptor(){
static uint16_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) static uint16_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured)
static inline void std_d2h_req(){ static inline void std_d2h_req(){
uint16_t status = 0; // bus powered uint16_t status = 0; // bus powered
switch(setup_packet.bRequest){ switch(setup_packet->bRequest){
case GET_DESCRIPTOR: case GET_DESCRIPTOR:
get_descriptor(); get_descriptor();
break; break;
@ -244,16 +248,61 @@ static inline void std_d2h_req(){
} }
} }
// interrupt IN handler (never used?)
static void EP1_Handler(){
uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]);
if(RX_FLAG(epstatus)) epstatus = (epstatus & ~USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_RX; // set valid RX
else epstatus = epstatus & ~(USB_EPnR_STAT_TX|USB_EPnR_STAT_RX);
// clear CTR
epstatus = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX));
USB->EPnR[1] = epstatus;
}
// data IN/OUT handlers
static void transmit_Handler(){ // EP3IN
uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]);
// clear CTR keep DTOGs & STATs
USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr
send_next();
}
static uint8_t rcvbuf[USB_RXBUFSZ];
static uint8_t volatile rcvbuflen = 0;
void chkin(){
if(bufovrfl) return;
if(!rcvbuflen) return;
int w = RB_write((ringbuffer*)&rbin, rcvbuf, rcvbuflen);
if(w < 0) return;
if(w != rcvbuflen) bufovrfl = 1;
rcvbuflen = 0;
uint16_t status = KEEP_DTOG(USB->EPnR[2]); // don't change DTOG
USB->EPnR[2] = status ^ USB_EPnR_STAT_RX;
}
// receiver reads data from local buffer and only then ACK'ed
static void receive_Handler(){ // EP2OUT
uint16_t status = KEEP_DTOG_STAT(USB->EPnR[2]); // don't change DTOG and NACK
if(rcvbuflen){
bufovrfl = 1; // lost last data
rcvbuflen = 0;
}
rcvbuflen = EP_Read(2, (uint8_t*)rcvbuf);
USB->EPnR[2] = status & ~USB_EPnR_CTR_RX;
}
static inline void std_h2d_req(){ static inline void std_h2d_req(){
switch(setup_packet.bRequest){ switch(setup_packet->bRequest){
case SET_ADDRESS: case SET_ADDRESS:
// new address will be assigned later - after acknowlegement or request to host // new address will be assigned later - after acknowlegement or request to host
USB_Dev.USB_Addr = setup_packet.wValue; USB_Addr = setup_packet->wValue;
break; break;
case SET_CONFIGURATION: case SET_CONFIGURATION:
// Now device configured // Now device configured
USB_Dev.USB_Status = USB_STATE_CONFIGURED; configuration = setup_packet->wValue;
configuration = setup_packet.wValue; EP_Init(1, EP_TYPE_INTERRUPT, USB_EP1BUFSZ, 0, EP1_Handler); // IN1 - transmit
EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, receive_Handler); // OUT2 - receive data
EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, transmit_Handler); // IN3 - transmit data
break; break;
default: default:
break; break;
@ -271,8 +320,8 @@ bmRequestType: 76543210
*/ */
void EP0_Handler(){ void EP0_Handler(){
uint16_t epstatus = USB->EPnR[0]; // EP0R on input -> return this value after modifications uint16_t epstatus = USB->EPnR[0]; // EP0R on input -> return this value after modifications
uint8_t reqtype = setup_packet.bmRequestType & 0x7f; uint8_t reqtype = setup_packet->bmRequestType & 0x7f;
uint8_t dev2host = (setup_packet.bmRequestType & 0x80) ? 1 : 0; uint8_t dev2host = (setup_packet->bmRequestType & 0x80) ? 1 : 0;
int rxflag = RX_FLAG(epstatus); int rxflag = RX_FLAG(epstatus);
if(rxflag && SETUP_FLAG(epstatus)){ if(rxflag && SETUP_FLAG(epstatus)){
switch(reqtype){ switch(reqtype){
@ -285,15 +334,15 @@ void EP0_Handler(){
} }
break; break;
case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request
if(setup_packet.bRequest == CLEAR_FEATURE){ if(setup_packet->bRequest == CLEAR_FEATURE){
EP_WriteIRQ(0, (uint8_t *)0, 0); EP_WriteIRQ(0, (uint8_t *)0, 0);
} }
break; break;
case VENDOR_REQUEST_TYPE: case VENDOR_REQUEST_TYPE:
vendor_handler(&setup_packet); vendor_handler(setup_packet);
break; break;
case CONTROL_REQUEST_TYPE: case CONTROL_REQUEST_TYPE:
switch(setup_packet.bRequest){ switch(setup_packet->bRequest){
case GET_LINE_CODING: case GET_LINE_CODING:
EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding));
break; break;
@ -301,7 +350,7 @@ void EP0_Handler(){
break; break;
case SET_CONTROL_LINE_STATE: case SET_CONTROL_LINE_STATE:
usbON = 1; usbON = 1;
clstate_handler(setup_packet.wValue); clstate_handler(setup_packet->wValue);
break; break;
case SEND_BREAK: case SEND_BREAK:
usbON = 0; usbON = 0;
@ -310,23 +359,22 @@ void EP0_Handler(){
default: default:
break; break;
} }
if(setup_packet.bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement if(setup_packet->bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement
break; break;
default: default:
EP_WriteIRQ(0, (uint8_t *)0, 0); EP_WriteIRQ(0, (uint8_t *)0, 0);
} }
}else if(rxflag){ // got data over EP0 or host acknowlegement }else if(rxflag){ // got data over EP0 or host acknowlegement
if(endpoints[0].rx_cnt){ if(endpoints[0].rx_cnt){
if(setup_packet.bRequest == SET_LINE_CODING){ if(setup_packet->bRequest == SET_LINE_CODING){
linecoding_handler((usb_LineCoding*)ep0databuf); linecoding_handler((usb_LineCoding*)ep0databuf);
} }
} }
} else if(TX_FLAG(epstatus)){ // package transmitted } else if(TX_FLAG(epstatus)){ // package transmitted
// now we can change address after enumeration // now we can change address after enumeration
if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){ if ((USB->DADDR & USB_DADDR_ADD) != USB_Addr){
USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr; USB->DADDR = USB_DADDR_EF | USB_Addr;
// change state to ADRESSED usbON = 0;
USB_Dev.USB_Status = USB_STATE_ADDRESSED;
} }
} }
epstatus = KEEP_DTOG(USB->EPnR[0]); epstatus = KEEP_DTOG(USB->EPnR[0]);

View File

@ -1,6 +1,6 @@
/* /*
* This file is part of the multistepper project. * This file is part of the multistepper project.
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>. * Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -60,14 +60,21 @@
#define CONTROL_DTR 0x01 #define CONTROL_DTR 0x01
#define CONTROL_RTS 0x02 #define CONTROL_RTS 0x02
// wValue // string descriptors
#define DEVICE_DESCRIPTOR 0x100 enum{
#define CONFIGURATION_DESCRIPTOR 0x200 iLANGUAGE_DESCR,
#define STRING_LANG_DESCRIPTOR 0x300 iMANUFACTURER_DESCR,
#define STRING_MAN_DESCRIPTOR 0x301 iPRODUCT_DESCR,
#define STRING_PROD_DESCRIPTOR 0x302 iSERIAL_DESCR,
#define STRING_SN_DESCRIPTOR 0x303 iINTERFACE_DESCR,
#define DEVICE_QUALIFIER_DESCRIPTOR 0x600 iDESCR_AMOUNT
};
// Types of descriptors
#define DEVICE_DESCRIPTOR 0x01
#define CONFIGURATION_DESCRIPTOR 0x02
#define STRING_DESCRIPTOR 0x03
#define DEVICE_QUALIFIER_DESCRIPTOR 0x06
#define RX_FLAG(epstat) (epstat & USB_EPnR_CTR_RX) #define RX_FLAG(epstat) (epstat & USB_EPnR_CTR_RX)
#define TX_FLAG(epstat) (epstat & USB_EPnR_CTR_TX) #define TX_FLAG(epstat) (epstat & USB_EPnR_CTR_TX)
@ -77,14 +84,6 @@
#define KEEP_DTOG_STAT(EPnR) (EPnR & ~(USB_EPnR_STAT_RX|USB_EPnR_STAT_TX|USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX)) #define KEEP_DTOG_STAT(EPnR) (EPnR & ~(USB_EPnR_STAT_RX|USB_EPnR_STAT_TX|USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX))
#define KEEP_DTOG(EPnR) (EPnR & ~(USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX)) #define KEEP_DTOG(EPnR) (EPnR & ~(USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX))
// USB state: uninitialized, addressed, ready for use
typedef enum{
USB_STATE_DEFAULT,
USB_STATE_ADDRESSED,
USB_STATE_CONFIGURED,
USB_STATE_CONNECTED
} USB_state;
// EP types // EP types
#define EP_TYPE_BULK 0x00 #define EP_TYPE_BULK 0x00
#define EP_TYPE_CONTROL 0x01 #define EP_TYPE_CONTROL 0x01
@ -93,6 +92,16 @@ typedef enum{
#define LANG_US (uint16_t)0x0409 #define LANG_US (uint16_t)0x0409
#if 0
typedef struct{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t *bString;
} string_descriptor_t;
#define _USB_STRING_(name, str) string_descriptor_t name = {(sizeof(str) + 2), STRING_DESCRIPTOR, str}
#endif
#define _USB_STRING_(name, str) \ #define _USB_STRING_(name, str) \
static const struct name \ static const struct name \
{ \ { \
@ -113,7 +122,6 @@ static const struct name \
\ \
} \ } \
name = {0x04, 0x03, lng_id} name = {0x04, 0x03, lng_id}
#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4)
// EP0 configuration packet // EP0 configuration packet
typedef struct { typedef struct {
@ -133,12 +141,6 @@ typedef struct{
unsigned rx_cnt : 10; // received data counter unsigned rx_cnt : 10; // received data counter
} ep_t; } ep_t;
// USB status & its address
typedef struct {
uint8_t USB_Status;
uint16_t USB_Addr;
}usb_dev_t;
typedef struct { typedef struct {
uint32_t dwDTERate; uint32_t dwDTERate;
uint8_t bCharFormat; uint8_t bCharFormat;
@ -163,10 +165,9 @@ typedef struct {
} __attribute__ ((packed)) usb_cdc_notification; } __attribute__ ((packed)) usb_cdc_notification;
extern ep_t endpoints[]; extern ep_t endpoints[];
extern usb_dev_t USB_Dev;
extern volatile uint8_t usbON; extern volatile uint8_t usbON;
extern config_pack_t setup_packet; extern config_pack_t *setup_packet;
extern uint8_t ep0databuf[]; extern uint8_t ep0databuf[], setupdatabuf[];
void EP0_Handler(); void EP0_Handler();
@ -179,3 +180,4 @@ void linecoding_handler(usb_LineCoding *lc);
void clstate_handler(uint16_t val); void clstate_handler(uint16_t val);
void break_handler(); void break_handler();
void vendor_handler(config_pack_t *packet); void vendor_handler(config_pack_t *packet);
void chkin();

View File

@ -1,6 +1,6 @@
/* /*
* This file is part of the multistepper project. * This file is part of the multistepper project.
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>. * Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -50,10 +50,10 @@ static uint16_t lastaddr = LASTADDR_DEFAULT;
int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)(ep_t ep)){ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)(ep_t ep)){
if(number >= STM32ENDPOINTS) return 4; // out of configured amount if(number >= STM32ENDPOINTS) return 4; // out of configured amount
if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large
if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE) return 2; // out of btable if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE/ACCESSZ) return 2; // out of btable
USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA); USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA);
USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1; USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1;
if(rxsz & 1 || rxsz > 512) return 3; // wrong rx buffer size if(rxsz & 1 || rxsz > USB_BTABLE_SIZE) return 3; // wrong rx buffer size
uint16_t countrx = 0; uint16_t countrx = 0;
if(rxsz < 64) countrx = rxsz / 2; if(rxsz < 64) countrx = rxsz / 2;
else{ else{
@ -84,7 +84,6 @@ void usb_lp_isr(){
lastaddr = LASTADDR_DEFAULT; lastaddr = LASTADDR_DEFAULT;
// clear address, leave only enable bit // clear address, leave only enable bit
USB->DADDR = USB_DADDR_EF; USB->DADDR = USB_DADDR_EF;
USB_Dev.USB_Status = USB_STATE_DEFAULT;
if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler)){ if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler)){
return; return;
} }
@ -101,10 +100,10 @@ void usb_lp_isr(){
if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit) if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit)
if(n == 0){ // control endpoint if(n == 0){ // control endpoint
if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack
EP_Read(0, (uint8_t*)&setup_packet); EP_Read(0, setupdatabuf);
// interrupt handler will be called later // interrupt handler will be called later
}else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf
EP_Read(0, (uint8_t*)&ep0databuf); EP_Read(0, ep0databuf);
} }
} }
} }

View File

@ -1,6 +1,6 @@
/* /*
* This file is part of the multistepper project. * This file is part of the multistepper project.
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>. * Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@ -1,2 +1,2 @@
#define BUILD_NUMBER "119" #define BUILD_NUMBER "160"
#define BUILD_DATE "2024-08-16" #define BUILD_DATE "2024-08-26"