mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 18:55:13 +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>
|
#include <stm32f3.h>
|
||||||
|
|
||||||
|
extern volatile uint32_t Tms;
|
||||||
|
|
||||||
void hw_setup();
|
void hw_setup();
|
||||||
|
|
||||||
#endif // __HARDWARE_H__
|
#endif // __HARDWARE_H__
|
||||||
|
|||||||
@ -23,6 +23,9 @@
|
|||||||
|
|
||||||
#define USBBUFSZ 127
|
#define USBBUFSZ 127
|
||||||
|
|
||||||
|
const char *test = "123456789A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789I123456789J123456789K123456789L123456789M123456789N123456789O123456789P123456789Q123456789R123456789S123456789T123456789U123456789V123456789W123456789X123456789Y\n"
|
||||||
|
"123456789A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789I123456789J123456789K123456789L123456789M123456789N123456789O123456789P123456789Q123456789R123456789S123456789T123456789U123456789V123456789W123456789X123456789Y\n";
|
||||||
|
|
||||||
volatile uint32_t Tms = 0;
|
volatile uint32_t Tms = 0;
|
||||||
|
|
||||||
void sys_tick_handler(void){
|
void sys_tick_handler(void){
|
||||||
@ -89,5 +92,13 @@ int main(void){
|
|||||||
const char *ans = parse_cmd(txt);
|
const char *ans = parse_cmd(txt);
|
||||||
if(ans) USB_send(ans);
|
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 "proto.h"
|
||||||
#include "usart.h"
|
#include "usart.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
|
uint8_t starttest = 50;
|
||||||
|
|
||||||
char *omit_spaces(const char *buf){
|
char *omit_spaces(const char *buf){
|
||||||
while(*buf){
|
while(*buf){
|
||||||
if(*buf > ' ') break;
|
if(*buf > ' ') break;
|
||||||
@ -154,6 +157,8 @@ const char* helpmsg =
|
|||||||
"'p' - toggle USB pullup\n"
|
"'p' - toggle USB pullup\n"
|
||||||
"'N' - read number (dec, 0xhex, 0oct, bbin) and show it in decimal\n"
|
"'N' - read number (dec, 0xhex, 0oct, bbin) and show it in decimal\n"
|
||||||
"'R' - software reset\n"
|
"'R' - software reset\n"
|
||||||
|
"'T' - test usb sending a very large message\n"
|
||||||
|
"'U' - get USB status\n"
|
||||||
"'W' - test watchdog\n"
|
"'W' - test watchdog\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -168,6 +173,7 @@ static void add2buf(const char *s){
|
|||||||
*bptr = 0;
|
*bptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern uint8_t usbON;
|
||||||
const char *parse_cmd(const char *buf){
|
const char *parse_cmd(const char *buf){
|
||||||
initbuf();
|
initbuf();
|
||||||
if(buf[1] == '\n' || !buf[1]){ // one symbol commands
|
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");
|
usart_send("Soft reset\n");
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
break;
|
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':
|
case 'W':
|
||||||
USB_send("Wait for reboot\n");
|
USB_send("Wait for reboot\n");
|
||||||
usart_send("Wait for reboot\n");
|
usart_send("Wait for reboot\n");
|
||||||
|
|||||||
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include <stm32f3.h>
|
#include <stm32f3.h>
|
||||||
|
|
||||||
|
extern uint8_t starttest;
|
||||||
|
|
||||||
const char *parse_cmd(const char *buf);
|
const char *parse_cmd(const char *buf);
|
||||||
char *omit_spaces(const char *buf);
|
char *omit_spaces(const char *buf);
|
||||||
char *getnum(const char *buf, uint32_t *N);
|
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/>.
|
* 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.h"
|
||||||
#include "usb_lib.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 tx_succesfull = 1;
|
||||||
static volatile uint8_t rxNE = 0;
|
static volatile uint8_t rxNE = 0;
|
||||||
|
|
||||||
static int sstrlen(const char *s){
|
volatile uint32_t Tlast = 0;
|
||||||
if(!s) return 0;
|
|
||||||
int l = 0;
|
void send_next(){
|
||||||
while(*s++) ++l;
|
static int lastdsz = 0;
|
||||||
return l;
|
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?)
|
// interrupt IN handler (never used?)
|
||||||
@ -45,6 +67,7 @@ static void transmit_Handler(){ // EP3IN
|
|||||||
uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]);
|
uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]);
|
||||||
// clear CTR keep DTOGs & STATs
|
// clear CTR keep DTOGs & STATs
|
||||||
USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr
|
USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr
|
||||||
|
send_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void receive_Handler(){ // EP2OUT
|
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
|
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(){
|
void usb_proc(){
|
||||||
switch(USB_Dev.USB_Status){
|
switch(USB_Dev.USB_Status){
|
||||||
case USB_STATE_CONFIGURED:
|
case USB_STATE_CONFIGURED:
|
||||||
|
|||||||
@ -24,7 +24,10 @@
|
|||||||
|
|
||||||
#define BUFFSIZE (64)
|
#define BUFFSIZE (64)
|
||||||
|
|
||||||
|
extern volatile uint32_t Tlast;
|
||||||
|
|
||||||
void usb_proc();
|
void usb_proc();
|
||||||
|
void send_next();
|
||||||
void USB_send(const char *buf);
|
void USB_send(const char *buf);
|
||||||
int USB_receive(char *buf);
|
int USB_receive(char *buf);
|
||||||
|
|
||||||
|
|||||||
@ -27,11 +27,14 @@ void USB_setup(){
|
|||||||
// setup pullup
|
// setup pullup
|
||||||
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
|
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
|
||||||
USBPU_OFF();
|
USBPU_OFF();
|
||||||
GPIOA->MODER = (GPIOA->MODER & (~GPIO_MODER_MODER15_Msk | GPIO_MODER_MODER11_Msk | GPIO_MODER_MODER12_Msk)) |
|
//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 & (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
|
// USB - alternate function 14 @ pins PA11/PA12
|
||||||
GPIOA->AFR[1] = (GPIOA->AFR[1] & ~(GPIO_AFRH_AFRH3_Msk | GPIO_AFRH_AFRH4_Msk)) |
|
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;
|
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
|
||||||
USB->CNTR = USB_CNTR_FRES; // Force USB Reset
|
USB->CNTR = USB_CNTR_FRES; // Force USB Reset
|
||||||
for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms
|
for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user