add ringbuffer to USB F303 (still can't do more than 3.2Mbaud)

This commit is contained in:
Edward Emelianov 2022-02-15 21:14:41 +03:00
parent 5f246c16bf
commit 6c4b2773a8
10 changed files with 188 additions and 69 deletions

View File

@ -22,6 +22,8 @@
#include <stm32f3.h>
extern volatile uint32_t Tms;
void hw_setup();
#endif // __HARDWARE_H__

View File

@ -23,6 +23,9 @@
#define USBBUFSZ 127
const char *test = "123456789A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789I123456789J123456789K123456789L123456789M123456789N123456789O123456789P123456789Q123456789R123456789S123456789T123456789U123456789V123456789W123456789X123456789Y\n"
"123456789A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789I123456789J123456789K123456789L123456789M123456789N123456789O123456789P123456789Q123456789R123456789S123456789T123456789U123456789V123456789W123456789X123456789Y\n";
volatile uint32_t Tms = 0;
void sys_tick_handler(void){
@ -89,5 +92,13 @@ int main(void){
const char *ans = parse_cmd(txt);
if(ans) USB_send(ans);
}
if(Tlast){
usart_send("Tlast="); usart_send(u2str(Tlast)); usart_putchar('\n');
Tlast = 0;
}
if(starttest){
--starttest;
USB_send(test);
}
}
}

Binary file not shown.

View File

@ -19,6 +19,9 @@
#include "proto.h"
#include "usart.h"
#include "usb.h"
uint8_t starttest = 50;
char *omit_spaces(const char *buf){
while(*buf){
if(*buf > ' ') break;
@ -154,6 +157,8 @@ const char* helpmsg =
"'p' - toggle USB pullup\n"
"'N' - read number (dec, 0xhex, 0oct, bbin) and show it in decimal\n"
"'R' - software reset\n"
"'T' - test usb sending a very large message\n"
"'U' - get USB status\n"
"'W' - test watchdog\n"
;
@ -168,6 +173,7 @@ static void add2buf(const char *s){
*bptr = 0;
}
extern uint8_t usbON;
const char *parse_cmd(const char *buf){
initbuf();
if(buf[1] == '\n' || !buf[1]){ // one symbol commands
@ -190,6 +196,17 @@ const char *parse_cmd(const char *buf){
usart_send("Soft reset\n");
NVIC_SystemReset();
break;
case 'T':
add2buf("STARTT=");
add2buf(u2str(Tms)); add2buf("\n");
starttest = 10;
break;
case 'U':
add2buf("USB status: ");
if(usbON) add2buf("ON");
else add2buf("OFF");
add2buf("\n");
break;
case 'W':
USB_send("Wait for reboot\n");
usart_send("Wait for reboot\n");

View File

@ -22,6 +22,8 @@
#include <stm32f3.h>
extern uint8_t starttest;
const char *parse_cmd(const char *buf);
char *omit_spaces(const char *buf);
char *getnum(const char *buf, uint32_t *N);

View File

@ -0,0 +1,86 @@
/*
* This file is part of the pl2303 project.
* Copyright 2022 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stm32f3.h>
#include "ringbuffer.h"
#include "usb.h"
#include "usb_lib.h"
// ring buffer
static char ringbuffer[RBSIZE];
// head - position of first data byte
// tail - position of last data byte + 1
// head == tail - empty! So, buffer can't store more than RBSIZE-1 bytes of data!
static volatile int head = 0, tail = 0;
static int datalen(){
if(tail >= head) return (tail - head);
else return (RBSIZE - head + tail);
}
static int restlen(){
return (RBSIZE - 1 - datalen());
}
TRUE_INLINE void incr(volatile int *what, int n){
*what += n;
if(*what >= RBSIZE) *what -= RBSIZE;
}
int RB_read(char s[BLOCKSIZE]){
int l = datalen();
if(!l) return 0;
if(l > BLOCKSIZE) l = BLOCKSIZE;
int _1st = RBSIZE - head;
if(_1st > l) _1st = l;
if(_1st > BLOCKSIZE) _1st = BLOCKSIZE;
memcpy(s, ringbuffer+head, _1st);
if(_1st < BLOCKSIZE && l > _1st){
memcpy(s+_1st, ringbuffer, l-_1st);
incr(&head, l);
return l;
}
incr(&head ,_1st);
return _1st;
}
static int addportion(const char *str, int l){
int r = restlen();
if(l > r) l = r;
if(!l) return 0;
int _1st = RBSIZE - tail;
if(_1st > l) _1st = l;
memcpy(ringbuffer+tail, str, _1st);
if(_1st < l){ // add another piece from start
memcpy(ringbuffer, str+_1st, l-_1st);
}
incr(&tail, l);
return l;
}
void RB_write(const char *str, int l){
if(!str || !*str) return;
if(!usbON) return;
while(l){
send_next();
int a = addportion(str, l);
l -= a;
str += a;
}
}

View File

@ -0,0 +1,33 @@
/*
* This file is part of the pl2303 project.
* Copyright 2022 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef RINGBUFFER_H__
#define RINGBUFFER_H__
#include "usbhw.h"
// ring buffer size in bytes
#define RBSIZE (512)
// max reading portion size
#define BLOCKSIZE (USB_TXBUFSZ)
int RB_read(char s[BLOCKSIZE]);
void RB_write(const char *str, int l);
#endif // RINGBUFFER_H__

View File

@ -16,17 +16,39 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "hardware.h"
#include "ringbuffer.h"
#include "usb.h"
#include "usb_lib.h"
static char usbbuff[USB_TXBUFSZ]; // temporary buffer for sending data
static volatile uint8_t tx_succesfull = 1;
static volatile uint8_t rxNE = 0;
static int sstrlen(const char *s){
if(!s) return 0;
int l = 0;
while(*s++) ++l;
return l;
volatile uint32_t Tlast = 0;
void send_next(){
static int lastdsz = 0;
if(!tx_succesfull) return;
int buflen = RB_read(usbbuff);
if(!buflen){
if(lastdsz) Tlast = Tms;
if(lastdsz == 64) EP_Write(3, NULL, 0); // send ZLP after 64 bits packet when nothing more to send
lastdsz = 0;
return;
}
tx_succesfull = 0;
EP_Write(3, (uint8_t*)usbbuff, buflen);
lastdsz = buflen;
}
// put `buf` into queue to send
void USB_send(const char *buf){
int len = strlen(buf);
if(!usbON || !len) return;
RB_write(buf, len); // this is a blocking procedure if there's too little free memory in buffer
}
// interrupt IN handler (never used?)
@ -45,6 +67,7 @@ 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
@ -53,67 +76,6 @@ static void receive_Handler(){ // EP2OUT
USB->EPnR[2] = (epstatus & ~(USB_EPnR_CTR_RX)); // clear RX ctr
}
static int usbwr(const char *buf, int l){
uint32_t ctra = 1000000;
while(--ctra && tx_succesfull == 0){
IWDG->KR = IWDG_REFRESH;
}
tx_succesfull = 0;
EP_Write(3, (uint8_t*)buf, l);
ctra = 1000000;
while(--ctra && tx_succesfull == 0){
IWDG->KR = IWDG_REFRESH;
}
if(tx_succesfull == 0){usbON = 0; return 1;} // usb is OFF?
return 0;
}
static char usbbuff[USB_TXBUFSZ-1]; // temporary buffer (63 - to prevent need of ZLP)
static int buflen = 0; // amount of symbols in usbbuff
// send next up to 63 bytes of data in usbbuff
static void send_next(){
if(!buflen || !tx_succesfull) return;
tx_succesfull = 0;
EP_Write(3, (uint8_t*)usbbuff, buflen);
buflen = 0;
}
// blocking sending
static void USB_send_blk(const char *buf, int len){
if(!usbON || !len) return; // USB disconnected
if(buflen){
usbwr(usbbuff, buflen);
buflen = 0;
}
int needzlp = 0;
while(len){
if(len == USB_TXBUFSZ) needzlp = 1;
int s = (len > USB_TXBUFSZ) ? USB_TXBUFSZ : len;
if(usbwr(buf, s)) return;
len -= s;
buf += s;
}
if(needzlp){
usbwr(NULL, 0);
}
}
// unblocking sending - just fill a buffer
void USB_send(const char *buf){
int len = sstrlen(buf);
if(!usbON || !len) return;
if(len > USB_TXBUFSZ-1 - buflen){
usbwr(usbbuff, buflen);
buflen = 0;
}
if(len > USB_TXBUFSZ-1){
USB_send_blk(buf, len);
return;
}
while(len--) usbbuff[buflen++] = *buf++;
}
void usb_proc(){
switch(USB_Dev.USB_Status){
case USB_STATE_CONFIGURED:

View File

@ -24,7 +24,10 @@
#define BUFFSIZE (64)
extern volatile uint32_t Tlast;
void usb_proc();
void send_next();
void USB_send(const char *buf);
int USB_receive(char *buf);

View File

@ -27,11 +27,14 @@ void USB_setup(){
// setup pullup
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
USBPU_OFF();
GPIOA->MODER = (GPIOA->MODER & (~GPIO_MODER_MODER15_Msk | GPIO_MODER_MODER11_Msk | GPIO_MODER_MODER12_Msk)) |
GPIO_MODER_MODER11_AF | GPIO_MODER_MODER12_AF | GPIO_MODER_MODER15_O;
//GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER15_Msk | GPIO_MODER_MODER11_Msk | GPIO_MODER_MODER12_Msk)) |
GPIOA->MODER = (GPIOA->MODER & (MODER_CLR(11) & MODER_CLR(12) & MODER_CLR(15))) |
(MODER_AF(11) | MODER_AF(12) | MODER_O(15));
//(GPIO_MODER_MODER11_AF | GPIO_MODER_MODER12_AF | GPIO_MODER_MODER15_O);
// USB - alternate function 14 @ pins PA11/PA12
GPIOA->AFR[1] = (GPIOA->AFR[1] & ~(GPIO_AFRH_AFRH3_Msk | GPIO_AFRH_AFRH4_Msk)) |
(14 << (3 * 4)) | (14 << (4 * 4));
//AFR1(14, 11) | AFR1(14, 12);
AFRf(14, 11) | AFRf(14, 12);
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
USB->CNTR = USB_CNTR_FRES; // Force USB Reset
for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms