mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 02:35:23 +03:00
add ringbuffer to USB F303 (still can't do more than 3.2Mbaud)
This commit is contained in:
parent
5f246c16bf
commit
6c4b2773a8
@ -22,6 +22,8 @@
|
||||
|
||||
#include <stm32f3.h>
|
||||
|
||||
extern volatile uint32_t Tms;
|
||||
|
||||
void hw_setup();
|
||||
|
||||
#endif // __HARDWARE_H__
|
||||
|
||||
@ -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.
@ -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");
|
||||
|
||||
@ -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);
|
||||
|
||||
86
F303-nolib/PL2303/ringbuffer.c
Normal file
86
F303-nolib/PL2303/ringbuffer.c
Normal 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;
|
||||
}
|
||||
}
|
||||
33
F303-nolib/PL2303/ringbuffer.h
Normal file
33
F303-nolib/PL2303/ringbuffer.h
Normal 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__
|
||||
@ -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:
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user