mirror of
https://github.com/eddyem/stm32samples.git
synced 2026-03-20 08:40:57 +03:00
usbcan_gpio: both USB interfaces works; start adding GPIO functions
This commit is contained in:
@@ -10,3 +10,6 @@ DEFINES := -DUSB2_16
|
|||||||
|
|
||||||
include ../makefile.f0
|
include ../makefile.f0
|
||||||
include ../../makefile.stm32
|
include ../../makefile.stm32
|
||||||
|
|
||||||
|
$(OBJDIR)/gpioproto.o: gpioproto.c $(VERSION_FILE)
|
||||||
|
$(OBJDIR)/canproto.o: canproto.c $(VERSION_FILE)
|
||||||
|
|||||||
@@ -104,7 +104,9 @@ static const char *cmd_parser(char *buf){
|
|||||||
case 'i':
|
case 'i':
|
||||||
return setiface(buf);
|
return setiface(buf);
|
||||||
default:
|
default:
|
||||||
return buf-1; // echo wrong data
|
// echo wrong data with terminating '\n'
|
||||||
|
SENDn(buf-1);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// "short" commands
|
// "short" commands
|
||||||
@@ -138,8 +140,9 @@ static const char *cmd_parser(char *buf){
|
|||||||
void GPIO_process(){
|
void GPIO_process(){
|
||||||
char inbuff[MAXSTRLEN];
|
char inbuff[MAXSTRLEN];
|
||||||
int l = RECV(inbuff, MAXSTRLEN);
|
int l = RECV(inbuff, MAXSTRLEN);
|
||||||
|
if(l == 0) return;
|
||||||
if(l < 0) SEND("ERROR: USB buffer overflow or string was too long\n");
|
if(l < 0) SEND("ERROR: USB buffer overflow or string was too long\n");
|
||||||
else if(l){
|
else{
|
||||||
const char *ans = cmd_parser(inbuff);
|
const char *ans = cmd_parser(inbuff);
|
||||||
if(ans) SEND(ans);
|
if(ans) SEND(ans);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
#include <stm32f0.h>
|
#include <stm32f0.h>
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
|
|
||||||
|
#define CHK(b) do{if(!b) return -1;}while(0)
|
||||||
|
|
||||||
static int datalen(ringbuffer *b){
|
static int 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);
|
||||||
@@ -26,7 +28,9 @@ static int datalen(ringbuffer *b){
|
|||||||
|
|
||||||
// stored data length
|
// stored data length
|
||||||
int RB_datalen(ringbuffer *b){
|
int RB_datalen(ringbuffer *b){
|
||||||
if(!b || b->busy) return -1;
|
CHK(b);
|
||||||
|
if(0 == datalen(b)) return 0; // don't block for empty RO operations
|
||||||
|
if(b->busy) return -1;
|
||||||
b->busy = 1;
|
b->busy = 1;
|
||||||
int l = datalen(b);
|
int l = datalen(b);
|
||||||
b->busy = 0;
|
b->busy = 0;
|
||||||
@@ -34,7 +38,7 @@ int RB_datalen(ringbuffer *b){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int hasbyte(ringbuffer *b, uint8_t byte){
|
static int hasbyte(ringbuffer *b, uint8_t byte){
|
||||||
if(!b || 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){ //
|
||||||
for(int found = b->head; found < b->length; ++found)
|
for(int found = b->head; found < b->length; ++found)
|
||||||
@@ -53,7 +57,8 @@ static int hasbyte(ringbuffer *b, uint8_t byte){
|
|||||||
* @return index if found, -1 if none or busy
|
* @return index if found, -1 if none or busy
|
||||||
*/
|
*/
|
||||||
int RB_hasbyte(ringbuffer *b, uint8_t byte){
|
int RB_hasbyte(ringbuffer *b, uint8_t byte){
|
||||||
if(!b || b->busy) return -1;
|
CHK(b);
|
||||||
|
if(b->busy) return -1;
|
||||||
b->busy = 1;
|
b->busy = 1;
|
||||||
int ret = hasbyte(b, byte);
|
int ret = hasbyte(b, byte);
|
||||||
b->busy = 0;
|
b->busy = 0;
|
||||||
@@ -91,7 +96,10 @@ static int read(ringbuffer *b, uint8_t *s, int len){
|
|||||||
* @return bytes read or -1 if busy
|
* @return bytes read or -1 if busy
|
||||||
*/
|
*/
|
||||||
int RB_read(ringbuffer *b, uint8_t *s, int len){
|
int RB_read(ringbuffer *b, uint8_t *s, int len){
|
||||||
if(!b || b->busy || !s || len < 1) return -1;
|
CHK(b);
|
||||||
|
if(!s || len < 1) return -1;
|
||||||
|
if(0 == datalen(b)) return 0;
|
||||||
|
if(b->busy) return -1;
|
||||||
b->busy = 1;
|
b->busy = 1;
|
||||||
int r = read(b, s, len);
|
int r = read(b, s, len);
|
||||||
b->busy = 0;
|
b->busy = 0;
|
||||||
@@ -124,7 +132,10 @@ static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){
|
|||||||
* @return amount of bytes written (negative, if len<data in buffer or buffer is busy)
|
* @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){
|
||||||
if(!b || b->busy) return -1;
|
CHK(b);
|
||||||
|
if(!s || len < 1) return -1;
|
||||||
|
if(0 == datalen(b)) return 0;
|
||||||
|
if(b->busy) return -1;
|
||||||
b->busy = 1;
|
b->busy = 1;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if(s && len > 0){
|
if(s && len > 0){
|
||||||
@@ -137,7 +148,9 @@ int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){
|
|||||||
}
|
}
|
||||||
|
|
||||||
int RB_datalento(ringbuffer *b, uint8_t byte){
|
int RB_datalento(ringbuffer *b, uint8_t byte){
|
||||||
if(!b || b->busy) return -1;
|
CHK(b);
|
||||||
|
if(0 == datalen(b)) return 0;
|
||||||
|
if(b->busy) return -1;
|
||||||
b->busy = 1;
|
b->busy = 1;
|
||||||
int n = lento(b, byte);
|
int n = lento(b, byte);
|
||||||
b->busy = 0;
|
b->busy = 0;
|
||||||
@@ -167,7 +180,10 @@ static int write(ringbuffer *b, const uint8_t *str, int l){
|
|||||||
* @return amount of bytes written or -1 if busy
|
* @return amount of bytes written or -1 if busy
|
||||||
*/
|
*/
|
||||||
int RB_write(ringbuffer *b, const uint8_t *str, int l){
|
int RB_write(ringbuffer *b, const uint8_t *str, int l){
|
||||||
if(!b || b->busy || !str || l < 1) return -1;
|
CHK(b);
|
||||||
|
if(!str || l < 1) return -1;
|
||||||
|
if(b->length - datalen(b) < 2) return 0;
|
||||||
|
if(b->busy) return -1;
|
||||||
b->busy = 1;
|
b->busy = 1;
|
||||||
int w = write(b, str, l);
|
int w = write(b, str, l);
|
||||||
b->busy = 0;
|
b->busy = 0;
|
||||||
@@ -176,10 +192,12 @@ int RB_write(ringbuffer *b, const uint8_t *str, int l){
|
|||||||
|
|
||||||
// just delete all information in buffer `b`
|
// just delete all information in buffer `b`
|
||||||
int RB_clearbuf(ringbuffer *b){
|
int RB_clearbuf(ringbuffer *b){
|
||||||
if(!b || b->busy) return -1;
|
CHK(b);
|
||||||
|
if(b->busy) return -1;
|
||||||
b->busy = 1;
|
b->busy = 1;
|
||||||
b->head = 0;
|
b->head = 0;
|
||||||
b->tail = 0;
|
b->tail = 0;
|
||||||
|
bzero(b->data, b->length);
|
||||||
b->busy = 0;
|
b->busy = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,13 +119,15 @@ static void rxtx_handler(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear IN/OUT buffers on connection
|
static void clearRbuf(uint8_t ifno){
|
||||||
static void clearbufs(uint8_t ifno){
|
|
||||||
uint32_t T0 = Tms;
|
uint32_t T0 = Tms;
|
||||||
while(Tms - T0 < 10){ // wait no more than 10ms
|
while(Tms - T0 < 10){ // wait no more than 10ms
|
||||||
if(1 == RB_clearbuf((ringbuffer*)&rbin[ifno])) break;
|
if(1 == RB_clearbuf((ringbuffer*)&rbin[ifno])) break;
|
||||||
}
|
}
|
||||||
T0 = Tms;
|
}
|
||||||
|
|
||||||
|
static void clearTbuf(uint8_t ifno){
|
||||||
|
uint32_t T0 = Tms;
|
||||||
while(Tms - T0 < 10){
|
while(Tms - T0 < 10){
|
||||||
if(1 == RB_clearbuf((ringbuffer*)&rbout[ifno])) break;
|
if(1 == RB_clearbuf((ringbuffer*)&rbout[ifno])) break;
|
||||||
}
|
}
|
||||||
@@ -144,7 +146,8 @@ void clstate_handler(uint8_t ifno, uint16_t val){
|
|||||||
CDCready[ifno] = val; // CONTROL_DTR | CONTROL_RTS -> interface connected; 0 -> disconnected
|
CDCready[ifno] = val; // CONTROL_DTR | CONTROL_RTS -> interface connected; 0 -> disconnected
|
||||||
lastdsz[ifno] = -1;
|
lastdsz[ifno] = -1;
|
||||||
if(val){
|
if(val){
|
||||||
clearbufs(ifno);
|
clearRbuf(ifno);
|
||||||
|
clearTbuf(ifno);
|
||||||
EP_reset(EPNO(ifno));
|
EP_reset(EPNO(ifno));
|
||||||
// usart_start(ifno);
|
// usart_start(ifno);
|
||||||
}//else usart_stop(ifno); // turn of USART (if it is @ this interface)
|
}//else usart_stop(ifno); // turn of USART (if it is @ this interface)
|
||||||
@@ -306,7 +309,7 @@ int USB_receive(uint8_t ifno, uint8_t *buf, int len){
|
|||||||
if(!CDCready[ifno]) return 0;
|
if(!CDCready[ifno]) return 0;
|
||||||
chkin(ifno); // rxtx_handler could leave last message unwritten if buffer was busy
|
chkin(ifno); // rxtx_handler could leave last message unwritten if buffer was busy
|
||||||
if(bufovrfl[ifno]){
|
if(bufovrfl[ifno]){
|
||||||
while(1 != RB_clearbuf((ringbuffer*)&rbin[ifno])); // run watchdog in case of problems
|
clearRbuf(ifno);
|
||||||
bufovrfl[ifno] = 0;
|
bufovrfl[ifno] = 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -325,7 +328,7 @@ int USB_receivestr(uint8_t ifno, char *buf, int len){
|
|||||||
if(!CDCready[ifno]) return 0;
|
if(!CDCready[ifno]) return 0;
|
||||||
chkin(ifno); // rxtx_handler could leave last message unwritten if buffer was busy
|
chkin(ifno); // rxtx_handler could leave last message unwritten if buffer was busy
|
||||||
if(bufovrfl[ifno]){
|
if(bufovrfl[ifno]){
|
||||||
while(1 != RB_clearbuf((ringbuffer*)&rbin[ifno]));
|
clearRbuf(ifno);
|
||||||
bufovrfl[ifno] = 0;
|
bufovrfl[ifno] = 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -333,7 +336,7 @@ int USB_receivestr(uint8_t ifno, char *buf, int len){
|
|||||||
if(l < 1){
|
if(l < 1){
|
||||||
if((rbin[ifno].length <= RB_datalen((ringbuffer*)&rbin[ifno]) + 1) ||
|
if((rbin[ifno].length <= RB_datalen((ringbuffer*)&rbin[ifno]) + 1) ||
|
||||||
(RB_datalento((ringbuffer*)&rbin[ifno], '\n') > len - 1)){ // buffer is full but no '\n' found or string too long
|
(RB_datalento((ringbuffer*)&rbin[ifno], '\n') > len - 1)){ // buffer is full but no '\n' found or string too long
|
||||||
while(1 != RB_clearbuf((ringbuffer*)&rbin[ifno]));
|
clearRbuf(ifno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -301,10 +301,14 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f
|
|||||||
}
|
}
|
||||||
|
|
||||||
// refresh EP after interface reconnected
|
// refresh EP after interface reconnected
|
||||||
void EP_reset(uint8_t number){
|
void EP_reset(uint8_t epno){
|
||||||
if(number >= STM32ENDPOINTS) return;
|
if(epno >= STM32ENDPOINTS) return;
|
||||||
USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX;
|
// keep DTOGs (don't write 1 to them), clear CTR (write 0 to them)
|
||||||
USB_BTABLE->EP[number].USB_COUNT_TX = 0;
|
// and set STAT to VALID (write 1 where was 0)
|
||||||
|
uint16_t epstatus = KEEP_DTOG(USB->EPnR[epno]);
|
||||||
|
USB->EPnR[epno] = (epstatus & ~(USB_EPnR_CTR_TX|USB_EPnR_CTR_RX)) ^
|
||||||
|
(USB_EPnR_STAT_RX | USB_EPnR_STAT_TX);
|
||||||
|
USB_BTABLE->EP[epno].USB_COUNT_TX = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// standard IRQ handler
|
// standard IRQ handler
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f
|
|||||||
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size);
|
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size);
|
||||||
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size);
|
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size);
|
||||||
int EP_Read(uint8_t number, uint8_t *buf);
|
int EP_Read(uint8_t number, uint8_t *buf);
|
||||||
void EP_reset(uint8_t number);
|
void EP_reset(uint8_t epno);
|
||||||
|
|
||||||
// could be [re]defined in usb_dev.c
|
// could be [re]defined in usb_dev.c
|
||||||
extern void usb_class_request(config_pack_t *packet, uint8_t *data, uint16_t datalen);
|
extern void usb_class_request(config_pack_t *packet, uint8_t *data, uint16_t datalen);
|
||||||
|
|||||||
Binary file not shown.
@@ -1,2 +1,2 @@
|
|||||||
#define BUILD_NUMBER "81"
|
#define BUILD_NUMBER "85"
|
||||||
#define BUILD_DATE "2026-03-07"
|
#define BUILD_DATE "2026-03-07"
|
||||||
|
|||||||
1
F3:F303/InterfaceBoard/TODO
Normal file
1
F3:F303/InterfaceBoard/TODO
Normal file
@@ -0,0 +1 @@
|
|||||||
|
add fixes to ringbuffer and make EP_reset @ each reconnection (like in F0/usbcan_gpio).
|
||||||
Reference in New Issue
Block a user