add cdc usart
This commit is contained in:
parent
b345a72511
commit
07c30fffc8
16 changed files with 620 additions and 0 deletions
89
V203/usb/ch32v203/usart.cpp
Normal file
89
V203/usb/ch32v203/usart.cpp
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
#include "system.h"
|
||||||
|
#include "../common/usart.h"
|
||||||
|
static Usart * pInstance = nullptr;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
[[gnu::interrupt]] void USART1_IRQHandler (void);
|
||||||
|
};
|
||||||
|
void USART1_IRQHandler (void) {
|
||||||
|
if (pInstance) pInstance->irq();
|
||||||
|
};
|
||||||
|
|
||||||
|
Usart::Usart(const uint32_t _baud) noexcept : BaseLayer (), tx_ring () {
|
||||||
|
pInstance = this;
|
||||||
|
// 1. Clock Enable
|
||||||
|
RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r) -> auto {
|
||||||
|
r.B.USART1EN = SET;
|
||||||
|
r.B.IOPAEN = SET;
|
||||||
|
//r.B.AFIOEN = SET; // není nutné
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
// 2. GPIO Alternate Config - default TX/PA9, RX/PA10
|
||||||
|
GPIOA.CFGHR.modify([](GPIOA_Type::CFGHR_DEF & r) -> auto {
|
||||||
|
r.B.MODE9 = 1u;
|
||||||
|
r.B.CNF9 = 2u; // or 3u for open drain
|
||||||
|
r.B.MODE10 = 0u;
|
||||||
|
r.B.CNF10 = 1u; // floating input
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
RCC.APB2PRSTR.B.USART1RST = SET;
|
||||||
|
RCC.APB2PRSTR.B.USART1RST = RESET;
|
||||||
|
// 5. USART registry 8.bit bez parity
|
||||||
|
USART1.CTLR1.modify([] (USART1_Type::CTLR1_DEF & r) -> auto {
|
||||||
|
r.B.RE = SET;
|
||||||
|
r.B.TE = SET;
|
||||||
|
r.B.RXNEIE = SET;
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
USART1.CTLR2.modify ([](USART1_Type::CTLR2_DEF & r) -> auto {
|
||||||
|
r.B.STOP = 0u;
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
SetBaud(_baud);
|
||||||
|
// NVIC
|
||||||
|
NVIC.EnableIRQ (USART1_IRQn);
|
||||||
|
USART1.CTLR1.B.UE = SET; // nakonec povolit globálně
|
||||||
|
}
|
||||||
|
void Usart::irq () {
|
||||||
|
volatile USART1_Type::STATR_DEF status (USART1.STATR); // načti status přerušení
|
||||||
|
char rdata, tdata;
|
||||||
|
|
||||||
|
if (status.B.TXE) { // od vysílače
|
||||||
|
if (tx_ring.Read (tdata)) { // pokud máme data
|
||||||
|
USART1.DATAR.B.DR = (uint8_t) tdata; // zapíšeme do výstupu
|
||||||
|
} else { // pokud ne
|
||||||
|
USART1.CTLR1.B.TXEIE = RESET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (status.B.RXNE) { // od přijímače
|
||||||
|
rdata = (USART1.DATAR.B.DR); // načteme data
|
||||||
|
Up (&rdata, 1u); // a pošleme dál
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t Usart::Down(const char * data, const uint32_t len) {
|
||||||
|
unsigned n = 0u;
|
||||||
|
for (n=0u; n<len; n++) {
|
||||||
|
if (!tx_ring.Write(data[n])) break;
|
||||||
|
}
|
||||||
|
USART1.CTLR1.B.TXEIE = SET; // po povolení přerušení okamžitě přeruší
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
void Usart::SetBaud (const uint32_t _baud) const {
|
||||||
|
const ONE_BIT b = USART1.CTLR1.B.UE;
|
||||||
|
if (b == SET) USART1.CTLR1.B.UE = RESET;
|
||||||
|
const uint32_t HCLK = SystemCoreClock; // hodiny pro USART zde nejsou děleny
|
||||||
|
const uint32_t tmp = HCLK / _baud; // lze je tedy zapsat přímo
|
||||||
|
USART1.BRR.R = tmp;
|
||||||
|
if (b == SET) USART1.CTLR1.B.UE = SET;
|
||||||
|
}
|
||||||
|
bool Usart::IOCtrl (const CTRL_TYPES_DEF type, const void * data, const uint32_t len) {
|
||||||
|
switch (type) {
|
||||||
|
case USB_USART_SET_PARAM : {
|
||||||
|
const USB_CDC_LineCoding * lc = reinterpret_cast<const USB_CDC_LineCoding *>(data);
|
||||||
|
SetBaud(lc->baud); // Pouze změníme rychlost, ostatní parametry ingorujme
|
||||||
|
} return true;
|
||||||
|
// Ostatní IOCtrl zatím nebudeme obsluhovat, je to celkem zbytečné
|
||||||
|
default : break;
|
||||||
|
};
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ enum CTRL_TYPES_DEF {
|
||||||
USB_USART_SET_DTR_RTS,
|
USB_USART_SET_DTR_RTS,
|
||||||
USB_USART_INIT,
|
USB_USART_INIT,
|
||||||
};
|
};
|
||||||
|
static_assert (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__, "Bad ENDIAN");
|
||||||
struct USB_CDC_LineCoding {
|
struct USB_CDC_LineCoding {
|
||||||
uint32_t baud;
|
uint32_t baud;
|
||||||
uint8_t stop, parity, data;
|
uint8_t stop, parity, data;
|
||||||
|
|
60
V203/usb/common/mirror.h
Normal file
60
V203/usb/common/mirror.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#ifndef MIRROR_H
|
||||||
|
#define MIRROR_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "baselayer.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Obraceč datového toku.
|
||||||
|
* @class Mirror
|
||||||
|
* @brief Obraceč datového toku má 2 třídy.
|
||||||
|
*
|
||||||
|
* TwoTop je vlastní obraceč, dědí vlastnosti BaseLayer, pouze metoda Up je přetížena -
|
||||||
|
* to je to vlastní převrácení. Hlavní třída Mirror, jejíž instance je pak v kódu použita
|
||||||
|
* obsahuje 2 rovnocenné instance třídy TwoTop, které musí být ve stacku vždy navrchu.
|
||||||
|
* První část stacku volá Up jedné instance, druhá Up té druhé. Proto tam musí být dvě.
|
||||||
|
* Podobně by šel udělat něco jako Fork, odbočení datového toku.
|
||||||
|
|
||||||
|
* A zase - všechny metody jsou tak jednoduché, že jsou celé v hlavičce, tedy inline.
|
||||||
|
*
|
||||||
|
* @class TwoTop
|
||||||
|
* @brief Vlastní obraceč.
|
||||||
|
* Ono to vypadá hodně zmateně, ale používá se to snadno - dokonce to funguje.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TwoTop : public BaseLayer {
|
||||||
|
public:
|
||||||
|
/// Konstruktor
|
||||||
|
explicit TwoTop () noexcept : BaseLayer (), x (nullptr) {};
|
||||||
|
/// Setter pro x
|
||||||
|
void setX (BaseLayer & bl) { x = & bl; };
|
||||||
|
/// Přetížení metody Up, nic jiného není potřeba
|
||||||
|
uint32_t Up (const char* data, uint32_t len) {
|
||||||
|
if (!x) return 0; // pro jistotu
|
||||||
|
// To, co přišlo zespoda, pošlu druhou instancí zase dolů
|
||||||
|
return x->Down (data, len);
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
/// Fakticky ukazatel na druhou instanci TwoTop
|
||||||
|
BaseLayer * x;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Mirror {
|
||||||
|
public:
|
||||||
|
/// Konstruktor
|
||||||
|
explicit Mirror () noexcept : L(), R() {
|
||||||
|
L.setX (R); R.setX (L);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Zřetězení voláme 2x. Poprvé pro jednu +=, podruhé -= pro druhou instanci TwoTop.
|
||||||
|
Protože je tato třída navrchu (vlevo), operátor nic nevrací.
|
||||||
|
*/
|
||||||
|
void operator += (BaseLayer& bl) { L += bl; return; };
|
||||||
|
void operator -= (BaseLayer& bl) { R += bl; return; };
|
||||||
|
private:
|
||||||
|
TwoTop L, R; //!< 2 instance Top
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIRROR_H
|
22
V203/usb/common/usart.h
Normal file
22
V203/usb/common/usart.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef USART_H
|
||||||
|
#define USART_H
|
||||||
|
#include "fifo.h"
|
||||||
|
#include "baselayer.h"
|
||||||
|
#include "ctrlinterface.h"
|
||||||
|
/** @class Usart
|
||||||
|
* @brief Sériový port.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Usart : public BaseLayer, public CDC_CtrlInterface {
|
||||||
|
FIFO<char, 64> tx_ring;
|
||||||
|
public:
|
||||||
|
explicit Usart (const uint32_t baud = 9600) noexcept;
|
||||||
|
uint32_t Down (const char * data, const uint32_t len) override;
|
||||||
|
void SetBaud (const uint32_t baud) const;
|
||||||
|
// Obsluha přerušení musí být veřejná.
|
||||||
|
void irq (void);
|
||||||
|
// Přetížení pro CDC.
|
||||||
|
bool IOCtrl (const CTRL_TYPES_DEF type, const void * data, const uint32_t len) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // USART_H
|
52
V203/usb/usart/Makefile
Normal file
52
V203/usb/usart/Makefile
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
TARGET?= ch32v203
|
||||||
|
TOOL ?= gcc
|
||||||
|
#TOOL ?= clang
|
||||||
|
|
||||||
|
PRJ = example
|
||||||
|
|
||||||
|
VPATH = . ./$(TARGET) ./common
|
||||||
|
BLD = ./build/
|
||||||
|
DFLAGS = -d
|
||||||
|
LFLAGS = -g
|
||||||
|
LDLIBS =
|
||||||
|
BFLAGS = --strip-unneeded
|
||||||
|
|
||||||
|
CFLAGS = -MMD -Wall -Wno-parentheses -ggdb -fno-exceptions -ffunction-sections -fdata-sections
|
||||||
|
CFLAGS+= -I. -I./$(TARGET) -I./common
|
||||||
|
DEL = rm -f
|
||||||
|
|
||||||
|
# zdrojaky
|
||||||
|
OBJS = main.o hack.o
|
||||||
|
OBJS += usb_desc.o cdc_class.o usart.o
|
||||||
|
|
||||||
|
include $(TARGET)/$(TOOL).mk
|
||||||
|
BOBJS = $(addprefix $(BLD),$(OBJS))
|
||||||
|
|
||||||
|
all: $(BLD) $(PRJ).elf
|
||||||
|
# ... atd.
|
||||||
|
-include $(BLD)*.d
|
||||||
|
# linker
|
||||||
|
$(PRJ).elf: $(BOBJS)
|
||||||
|
-@echo [LD $(TOOL),$(TARGET)] $@
|
||||||
|
@$(LD) $(LFLAGS) -o $(PRJ).elf $(BOBJS) $(LDLIBS)
|
||||||
|
-@echo "size:"
|
||||||
|
@$(SIZE) $(PRJ).elf
|
||||||
|
-@echo "listing:"
|
||||||
|
$(DUMP) $(DFLAGS) $(PRJ).elf > $(PRJ).lst
|
||||||
|
-@echo "OK."
|
||||||
|
$(COPY) $(BFLAGS) -O binary $(PRJ).elf $(PRJ).bin
|
||||||
|
# preloz co je potreba
|
||||||
|
$(BLD)%.o: %.c
|
||||||
|
-@echo [CC $(TOOL),$(TARGET)] $@
|
||||||
|
@$(CC) -std=gnu99 -c $(CFLAGS) $< -o $@
|
||||||
|
$(BLD)%.o: %.cpp
|
||||||
|
-@echo [CX $(TOOL),$(TARGET)] $@
|
||||||
|
@$(CXX) -std=c++17 -fno-rtti -c $(CFLAGS) $< -o $@
|
||||||
|
$(BLD):
|
||||||
|
mkdir $(BLD)
|
||||||
|
flash: $(PRJ).elf
|
||||||
|
minichlink -w $(PRJ).bin flash -b
|
||||||
|
# vycisti
|
||||||
|
clean:
|
||||||
|
$(DEL) $(BLD)* *.lst *.bin *.elf *.map *~
|
||||||
|
.PHONY: all clean flash run
|
1
V203/usb/usart/ch32v203
Symbolic link
1
V203/usb/usart/ch32v203
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../ch32v203/
|
1
V203/usb/usart/common
Symbolic link
1
V203/usb/usart/common
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../common/
|
21
V203/usb/usart/hack.c
Normal file
21
V203/usb/usart/hack.c
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
size_t strlen (const char *s) {
|
||||||
|
size_t l = 0;
|
||||||
|
while (*s++) l++;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
void *memcpy (void *dest, const void *src, size_t n) {
|
||||||
|
const char *s = (const char *) src;
|
||||||
|
char *d = (char *) dest;
|
||||||
|
int i;
|
||||||
|
for (i=0; i<n; i++) d[i] = s[i];
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
void *memset (void *s, int c, size_t n) {
|
||||||
|
char *p = (char *) s;
|
||||||
|
int i;
|
||||||
|
for (i=0; i<n; i++) p[i] = c;
|
||||||
|
return s;
|
||||||
|
}
|
25
V203/usb/usart/main.cpp
Normal file
25
V203/usb/usart/main.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "cdc_class.h"
|
||||||
|
#include "usart.h"
|
||||||
|
#include "mirror.h"
|
||||||
|
/** Převodník USB_CDC - USART
|
||||||
|
* Datový formát je pevný - 8 bit, 1 stop bit, bez parity.
|
||||||
|
* Změnu po USB by šlo dost jednoduše dodělat, ale nepovažoval jsem to za nutné.
|
||||||
|
* Baudová rychlost se dá po USB změnit na libovolnou hodnotu.
|
||||||
|
*
|
||||||
|
* Výhoda tohoto řešení je, že nad USARTem může běžet nějaký protokol
|
||||||
|
* přímo v tomto čipu. Jinak je to asi nejlevnější řešení. Zřejmě to
|
||||||
|
* nebude snášet velké rychlosti (nad 115200 Bd).
|
||||||
|
* */
|
||||||
|
static cdc_class cdc;
|
||||||
|
static Usart usart;
|
||||||
|
static Mirror top;
|
||||||
|
int main () {
|
||||||
|
cdc.init();
|
||||||
|
top += cdc;
|
||||||
|
top -= usart;
|
||||||
|
cdc.attach(usart);
|
||||||
|
for (;;) {
|
||||||
|
/* Vše probíhá v přerušení */
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
24
V203/usb/usart/test/Makefile
Normal file
24
V203/usb/usart/test/Makefile
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
PR = test.elf
|
||||||
|
CC = gcc
|
||||||
|
CXX= g++ -std=c++17
|
||||||
|
AS = as
|
||||||
|
CFLAGS = -Wall -Os
|
||||||
|
MFLAGS = -o $(PR)
|
||||||
|
LFLAGS = -lpthread
|
||||||
|
|
||||||
|
all : $(PR)
|
||||||
|
|
||||||
|
OBJECTS = main.o usart.o baud.o
|
||||||
|
|
||||||
|
$(PR) : $(OBJECTS)
|
||||||
|
$(CXX) $(MFLAGS) $(OBJECTS) $(LFLAGS)
|
||||||
|
clean:
|
||||||
|
rm -f *.o *~
|
||||||
|
%.o : %.c
|
||||||
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
%.o : %.cpp
|
||||||
|
$(CXX) -c $(CFLAGS) -o $@ $<
|
||||||
|
%.o : %.s
|
||||||
|
$(AS) -o $@ $<
|
||||||
|
|
||||||
|
.PHONY : all clean
|
14
V203/usb/usart/test/baud.cpp
Normal file
14
V203/usb/usart/test/baud.cpp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include <asm/termbits.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "usart.h"
|
||||||
|
|
||||||
|
void UsartClass::setBaud (int baud) {
|
||||||
|
struct termios2 tio;
|
||||||
|
|
||||||
|
ioctl(fd, TCGETS2, &tio);
|
||||||
|
tio.c_cflag &= ~CBAUD;
|
||||||
|
tio.c_cflag |= BOTHER;
|
||||||
|
tio.c_ispeed = baud;
|
||||||
|
tio.c_ospeed = baud;
|
||||||
|
ioctl(fd, TCSETS2, &tio);
|
||||||
|
}
|
45
V203/usb/usart/test/main.cpp
Normal file
45
V203/usb/usart/test/main.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include "usart.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
class Top : public BaseLayer {
|
||||||
|
static constexpr int max = 1024;
|
||||||
|
volatile unsigned index;
|
||||||
|
int passcnt;
|
||||||
|
char buffer [max];
|
||||||
|
public:
|
||||||
|
explicit Top () : BaseLayer(), index(0u), passcnt(0) {}
|
||||||
|
void puts (const char * str) {
|
||||||
|
const unsigned l = strlen(str);
|
||||||
|
Down(str, l);
|
||||||
|
}
|
||||||
|
uint32_t Up(const char * data, const uint32_t len) override {
|
||||||
|
for (unsigned n=0; n<len; n++) {
|
||||||
|
const char c = data [n];
|
||||||
|
buffer [index++] = c;
|
||||||
|
if (c == '\n') {
|
||||||
|
buffer [index - 2] = '\0';
|
||||||
|
printf("Rx (%d) %s\n", passcnt++, buffer);
|
||||||
|
index = 0u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static const char * TestString = "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG'S BACK 1234567890\r\n";
|
||||||
|
static volatile bool loop = false;
|
||||||
|
static void Handler (int) {
|
||||||
|
loop = false;
|
||||||
|
}
|
||||||
|
int main (void) {
|
||||||
|
loop = true;
|
||||||
|
signal (SIGINT, Handler);
|
||||||
|
UsartClass usart ("/dev/serial/by-id/usb-Kizarm_Labs._USB__=__USART_0002-if00", 9600);
|
||||||
|
Top top;
|
||||||
|
top += usart;
|
||||||
|
while (loop) {
|
||||||
|
top.puts(TestString);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
84
V203/usb/usart/test/usart.cpp
Normal file
84
V203/usb/usart/test/usart.cpp
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "usart.h"
|
||||||
|
|
||||||
|
UsartClass::UsartClass (const char * name, const int baudrate) : BaseLayer() {
|
||||||
|
id = name;
|
||||||
|
running = false;
|
||||||
|
fd = ::open (id, O_RDWR);
|
||||||
|
if (fd < 0) return;
|
||||||
|
|
||||||
|
timeout = 12'000'000 / baudrate; // cca pro 1 byte
|
||||||
|
|
||||||
|
struct termios LineFlags;
|
||||||
|
int attr = tcgetattr (fd, &LineFlags);
|
||||||
|
if (attr) {
|
||||||
|
printf ("Nelze zjistit parametry portu %s\r\n", name);
|
||||||
|
::close (fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// nastaveni komunikacnich parametru do struct termios
|
||||||
|
LineFlags.c_iflag = IGNPAR /* | IXON | IXOFF*/; // ignoruj chyby parity
|
||||||
|
LineFlags.c_oflag = 0; // normalni nastaveni
|
||||||
|
LineFlags.c_cflag = CS8 | CREAD | CLOCAL; // 8-bit, povol prijem
|
||||||
|
LineFlags.c_lflag = 0; // Raw input bez echa
|
||||||
|
LineFlags.c_cc [VMIN] = 1; // minimalni pocet znaku pro cteni
|
||||||
|
LineFlags.c_cc [VTIME] = 1; // read timeout 0.1 s
|
||||||
|
|
||||||
|
tcsetattr (fd, TCSANOW, &LineFlags);
|
||||||
|
fcntl (fd, F_SETFL, 0);
|
||||||
|
|
||||||
|
int flag = TIOCM_DTR;
|
||||||
|
ioctl(fd, TIOCMBIS, & flag);
|
||||||
|
|
||||||
|
setBaud(baudrate);
|
||||||
|
|
||||||
|
printf ("Port %s opened (%d) at %d Bd\r\n", id, fd, baudrate);
|
||||||
|
usleep (10000);
|
||||||
|
running = true;
|
||||||
|
pthread_create (&rc, NULL, UsartClass::UsartHandler, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
UsartClass::~UsartClass() {
|
||||||
|
running = false;
|
||||||
|
pthread_cancel (rc);
|
||||||
|
|
||||||
|
int flag = TIOCM_DTR;
|
||||||
|
ioctl(fd, TIOCMBIC, & flag);
|
||||||
|
|
||||||
|
::close (fd);
|
||||||
|
printf ("Port %s closed\r\n", id);
|
||||||
|
}
|
||||||
|
uint32_t UsartClass::Up (const char * data, uint32_t len) {
|
||||||
|
return BaseLayer::Up (data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t UsartClass::Down (const char * data, uint32_t len) {
|
||||||
|
if (!running) return 0;
|
||||||
|
const unsigned maxchunk = 32; // USB bulk len (64) je moc
|
||||||
|
unsigned offset = 0, remain = len;
|
||||||
|
while (remain) {
|
||||||
|
const unsigned chunk = remain > maxchunk ? maxchunk : remain;
|
||||||
|
const unsigned writn = ::write (fd, data + offset, chunk);
|
||||||
|
usleep (timeout * writn); // závisí na baud rate
|
||||||
|
offset += writn;
|
||||||
|
remain -= writn;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UsartClass::ReadLoop (void) {
|
||||||
|
int n;
|
||||||
|
while (running) {
|
||||||
|
// Nutno číst po jednom nebo použít timer, jinak to po prvním čtení zdechne.
|
||||||
|
n = ::read (fd, rxbuf, 1);
|
||||||
|
if (!n) continue;
|
||||||
|
Up (rxbuf, n);
|
||||||
|
}
|
||||||
|
}
|
32
V203/usb/usart/test/usart.h
Normal file
32
V203/usb/usart/test/usart.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef USARTCLASS_H
|
||||||
|
#define USARTCLASS_H
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include "../common/baselayer.h"
|
||||||
|
|
||||||
|
static constexpr unsigned BUFLEN = 1024u;
|
||||||
|
// Bottom
|
||||||
|
class UsartClass : public BaseLayer {
|
||||||
|
public:
|
||||||
|
UsartClass (const char* name, const int baudrate);
|
||||||
|
uint32_t Up (const char* data, uint32_t len);
|
||||||
|
uint32_t Down(const char* data, uint32_t len);
|
||||||
|
virtual ~UsartClass ();
|
||||||
|
protected:
|
||||||
|
void ReadLoop (void);
|
||||||
|
static void* UsartHandler (void* p) {
|
||||||
|
UsartClass* inst = (UsartClass*) p;
|
||||||
|
inst->ReadLoop();
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
void setBaud (int baud);
|
||||||
|
public:
|
||||||
|
bool running;
|
||||||
|
private:
|
||||||
|
const char * id; //!< Identifikátor třídy pro ladění
|
||||||
|
char rxbuf[BUFLEN];
|
||||||
|
int fd;
|
||||||
|
int timeout;
|
||||||
|
pthread_t rc;
|
||||||
|
};
|
||||||
|
#endif // USARTCLASS_H
|
83
V203/usb/usart/usb_desc.cpp
Normal file
83
V203/usb/usart/usb_desc.cpp
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/********************************** (C) COPYRIGHT *******************************
|
||||||
|
* File Name : usb_desc.c
|
||||||
|
* Author : WCH
|
||||||
|
* Version : V1.0.0
|
||||||
|
* Date : 2022/08/20
|
||||||
|
* Description : usb device descriptor,configuration descriptor,
|
||||||
|
* string descriptors and other descriptors.
|
||||||
|
*********************************************************************************
|
||||||
|
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||||
|
* Attention: This software (modified or not) and binary are used for
|
||||||
|
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "usb_desc.h"
|
||||||
|
|
||||||
|
/* Device Descriptor */
|
||||||
|
const uint8_t MyDevDescr[] =
|
||||||
|
{
|
||||||
|
0x12, // bLength
|
||||||
|
0x01, // bDescriptorType (Device)
|
||||||
|
0x10, 0x01, // bcdUSB 1.10
|
||||||
|
0x02, // bDeviceClass
|
||||||
|
0x00, // bDeviceSubClass
|
||||||
|
0x00, // bDeviceProtocol
|
||||||
|
DEF_USBD_UEP0_SIZE, // bMaxPacketSize0 64
|
||||||
|
(uint8_t)DEF_USB_VID, (uint8_t)(DEF_USB_VID >> 8), // idVendor 0x1A86
|
||||||
|
(uint8_t)DEF_USB_PID, (uint8_t)(DEF_USB_PID >> 8), // idProduct 0x5537
|
||||||
|
DEF_IC_PRG_VER, 0x00, // bcdDevice 0.01
|
||||||
|
0x01, // iManufacturer (String Index)
|
||||||
|
0x02, // iProduct (String Index)
|
||||||
|
0x03, // iSerialNumber (String Index)
|
||||||
|
0x01, // bNumConfigurations 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Configuration Descriptor */
|
||||||
|
const uint8_t MyCfgDescr[] =
|
||||||
|
{
|
||||||
|
/* Configure descriptor */
|
||||||
|
0x09, 0x02, 0x43, 0x00, 0x02, 0x01, 0x00, 0x80, 0x32,
|
||||||
|
|
||||||
|
/* Interface 0 (CDC) descriptor */
|
||||||
|
0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,
|
||||||
|
|
||||||
|
/* Functional Descriptors */
|
||||||
|
0x05, 0x24, 0x00, 0x10, 0x01,
|
||||||
|
|
||||||
|
/* Length/management descriptor (data class interface 1) */
|
||||||
|
0x05, 0x24, 0x01, 0x00, 0x01,
|
||||||
|
0x04, 0x24, 0x02, 0x02,
|
||||||
|
0x05, 0x24, 0x06, 0x00, 0x01,
|
||||||
|
|
||||||
|
/* Interrupt upload endpoint descriptor */
|
||||||
|
0x07, 0x05, 0x81, 0x03, (uint8_t)DEF_USBD_ENDP1_SIZE, (uint8_t)( DEF_USBD_ENDP1_SIZE >> 8 ), 0x01,
|
||||||
|
|
||||||
|
/* Interface 1 (data interface) descriptor */
|
||||||
|
0x09, 0x04, 0x01, 0x00, 0x02, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
/* Endpoint descriptor */
|
||||||
|
0x07, 0x05, 0x02, 0x02, (uint8_t)DEF_USBD_ENDP2_SIZE, (uint8_t)( DEF_USBD_ENDP2_SIZE >> 8 ), 0x00,
|
||||||
|
|
||||||
|
/* Endpoint descriptor */
|
||||||
|
0x07, 0x05, 0x83, 0x02, (uint8_t)DEF_USBD_ENDP3_SIZE, (uint8_t)( DEF_USBD_ENDP3_SIZE >> 8 ), 0x00,
|
||||||
|
};
|
||||||
|
#define DEF_STRDESC(p,n) w_text<(sizeof(p)>>1)>n={sizeof(n)-2u,3u,{p}}
|
||||||
|
template<const unsigned N> struct w_text {
|
||||||
|
uint8_t len, typ;
|
||||||
|
const char16_t str [N];
|
||||||
|
};
|
||||||
|
static const DEF_STRDESC((u"Kizarm Labs."), str_1);
|
||||||
|
static const DEF_STRDESC((u"USB <=> USART"),str_2);
|
||||||
|
static const DEF_STRDESC((u"0002"), str_3);
|
||||||
|
/* Language Descriptor */
|
||||||
|
static const uint8_t LangDescr[] = {
|
||||||
|
0x04, 0x03, 0x09, 0x04
|
||||||
|
};
|
||||||
|
const uint8_t * StringDescArray [DEF_MAX_STRINGS] = {
|
||||||
|
LangDescr,
|
||||||
|
reinterpret_cast<const uint8_t*> (&str_1),
|
||||||
|
reinterpret_cast<const uint8_t*> (&str_2),
|
||||||
|
reinterpret_cast<const uint8_t*> (&str_3),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
66
V203/usb/usart/usb_desc.h
Normal file
66
V203/usb/usart/usb_desc.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/********************************** (C) COPYRIGHT *******************************
|
||||||
|
* File Name : usb_desc.h
|
||||||
|
* Author : WCH
|
||||||
|
* Version : V1.0.0
|
||||||
|
* Date : 2022/08/20
|
||||||
|
* Description : header file of usb_desc.c
|
||||||
|
*********************************************************************************
|
||||||
|
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||||
|
* Attention: This software (modified or not) and binary are used for
|
||||||
|
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef USER_USB_DESC_H_
|
||||||
|
#define USER_USB_DESC_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* global define */
|
||||||
|
/* file version */
|
||||||
|
#define DEF_FILE_VERSION 0x01
|
||||||
|
/* usb device info define */
|
||||||
|
#define DEF_USB_VID 0x1A86
|
||||||
|
#define DEF_USB_PID 0xFE0C
|
||||||
|
/* USB device descriptor, device serial number(bcdDevice) */
|
||||||
|
#define DEF_IC_PRG_VER DEF_FILE_VERSION
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* usb device endpoint size define */
|
||||||
|
#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */
|
||||||
|
/* FS */
|
||||||
|
#define DEF_USBD_FS_PACK_SIZE 64 /* usb fs device max bluk/int pack size */
|
||||||
|
#define DEF_USBD_FS_ISO_PACK_SIZE 1023 /* usb fs device max iso pack size */
|
||||||
|
/* LS */
|
||||||
|
#define DEF_USBD_LS_UEP0_SIZE 8 /* usb ls device end-point 0 size */
|
||||||
|
#define DEF_USBD_LS_PACK_SIZE 64 /* usb ls device max int pack size */
|
||||||
|
|
||||||
|
/* Pack size */
|
||||||
|
#define DEF_USBD_ENDP1_SIZE DEF_USBD_FS_PACK_SIZE
|
||||||
|
#define DEF_USBD_ENDP2_SIZE DEF_USBD_FS_PACK_SIZE
|
||||||
|
#define DEF_USBD_ENDP3_SIZE DEF_USBD_FS_PACK_SIZE
|
||||||
|
#define DEF_USBD_ENDP4_SIZE DEF_USBD_FS_PACK_SIZE
|
||||||
|
#define DEF_USBD_ENDP5_SIZE DEF_USBD_FS_PACK_SIZE
|
||||||
|
#define DEF_USBD_ENDP6_SIZE DEF_USBD_FS_PACK_SIZE
|
||||||
|
#define DEF_USBD_ENDP7_SIZE DEF_USBD_FS_PACK_SIZE
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* usb device Descriptor length, length of usb descriptors, if one descriptor not
|
||||||
|
* exists , set the length to 0 */
|
||||||
|
#define DEF_USBD_DEVICE_DESC_LEN ((uint8_t)MyDevDescr[0])
|
||||||
|
#define DEF_USBD_CONFIG_DESC_LEN ((uint16_t)MyCfgDescr[2] + (uint16_t)(MyCfgDescr[3] << 8))
|
||||||
|
#define DEF_USBD_REPORT_DESC_LEN 0
|
||||||
|
|
||||||
|
#define DEF_MAX_STRINGS (4)
|
||||||
|
/******************************************************************************/
|
||||||
|
/* external variables */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif // __cplusplus
|
||||||
|
extern const uint8_t MyDevDescr[ ];
|
||||||
|
extern const uint8_t MyCfgDescr[ ];
|
||||||
|
extern const uint8_t * StringDescArray [DEF_MAX_STRINGS];
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif // __cplusplus
|
||||||
|
#endif /* USER_USB_DESC_H_ */
|
Loading…
Reference in a new issue