add fifo to usart, test

This commit is contained in:
Kizarm 2024-10-17 13:36:01 +02:00
parent 95b08e26ae
commit 9140ee66f9
2 changed files with 44 additions and 11 deletions

View file

@ -19,18 +19,24 @@ static constexpr unsigned Timeout = 5000; // us
* */ * */
class Middle : public BaseLayer { class Middle : public BaseLayer {
static constexpr unsigned max = 128; static constexpr unsigned max = 128;
FIFO<char,max> rx_ring;
volatile unsigned index; volatile unsigned index;
char buffer [max]; char buffer [max];
public: public:
explicit Middle () noexcept : BaseLayer(), index(0u) {} explicit Middle () noexcept : BaseLayer(), rx_ring(), index(0u) {}
/* Up() v původním řetězci volalo fakticky Down() v cdc_class. /* Up() v původním řetězci volalo fakticky Down() v cdc_class.
* Vzhledem k tomu, že len je zde 1 a USB musí vyvolat odeslání * Vzhledem k tomu, že len je zde 1 a USB musí vyvolat odeslání
* paketu, zdržuje to a přerušení zde může být ignorováno. * paketu, zdržuje to a přerušení zde může být ignorováno.
* Tohle ho významně zkrátí, ale zase musí být v hlavní smyčce * Tohle ho významně zkrátí, ale zase musí být v hlavní smyčce
* odeslání dat pomocí metody pass(). * odeslání dat pomocí metody pass(). Ukázalo se, že je nutné
* předávat data přes další frontu. Pak to funguje full duplex
* na rychlosti 4 MBd bez ztráty znaků.
* */ * */
uint32_t Up(const char * data, const uint32_t len) override { uint32_t Up(const char * data, const uint32_t len) override {
for (unsigned n=0; n<len; n++) buffer [index++] = data [n]; for (unsigned n=0; n<len; n++) {
if (!rx_ring.Write (data[n])) break;
else index += 1u;
}
return len; return len;
} }
// Down je průchozí, bylo by možné toto zcela vypustit. // Down je průchozí, bylo by možné toto zcela vypustit.
@ -41,10 +47,16 @@ public:
* */ * */
void pass () { void pass () {
/* Je to dost zjednodušeno, odešle se 64 bytový paket, /* Je to dost zjednodušeno, odešle se 64 bytový paket,
* nebo po 5 ms to co zůstalo v bufferu. * nebo po 5 ms to co zůstalo ve frontě.
* */ * */
if ((is_timeout() and index) or (index >= 64)) { if ((is_timeout() and index) or (index >= 64)) {
block(buffer, index); unsigned n;
for (n=0u; n<max; n++) {
if (!rx_ring.Read (buffer[n])) break;
}
if (!n) return;
index = 0u;
block(buffer, n);
} }
} }
protected: protected:
@ -55,7 +67,6 @@ public:
rem -= n; rem -= n;
ofs += n; ofs += n;
} }
index = 0;
set_timeout_us(Timeout); set_timeout_us(Timeout);
} }
}; };

View file

@ -1,45 +1,67 @@
#include "usart.h" #include "usart.h"
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <cstdlib>
#include <signal.h> #include <signal.h>
#include <unistd.h>
#include <chrono>
using namespace std::chrono;
class Top : public BaseLayer { class Top : public BaseLayer {
static constexpr int max = 1024; static constexpr int max = 1024;
unsigned tx_cnt, rx_cnt;
volatile unsigned index; volatile unsigned index;
int passcnt; int passcnt;
char buffer [max]; char buffer [max];
public: public:
explicit Top () : BaseLayer(), index(0u), passcnt(0) {} explicit Top () : BaseLayer(), tx_cnt(0u), rx_cnt(0u), index(0u), passcnt(0) {}
void puts (const char * str) { void puts (const char * str) {
const unsigned l = strlen(str); const unsigned l = strlen(str);
Down(str, l); tx_cnt += Down(str, l);
} }
uint32_t Up(const char * data, const uint32_t len) override { uint32_t Up(const char * data, const uint32_t len) override {
rx_cnt += len;
for (unsigned n=0; n<len; n++) { for (unsigned n=0; n<len; n++) {
const char c = data [n]; const char c = data [n];
buffer [index++] = c; buffer [index++] = c;
if (c == '\n') { if (c == '\n') {
buffer [index - 2] = '\0'; buffer [index - 2] = '\0';
printf("Rx (%d) %s\n", passcnt++, buffer); printf("Rx (%d) %s \r", passcnt++, buffer);
fflush(stdout);
index = 0u; index = 0u;
} }
} }
return len; return len;
} }
void result (const int t) {
const double real_br = 1.0e6 * (double) tx_cnt / (double) t;
printf("\nTx %d, Rx %d, tx = %g bytes/s\n", tx_cnt, rx_cnt, real_br);
}
}; };
static const char * TestString = "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG'S BACK 1234567890\r\n"; static const char * TestString = "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG'S BACK 1234567890\r\n";
static volatile bool loop = false; static volatile bool loop = false;
static void Handler (int) { static void Handler (int) {
loop = false; loop = false;
} }
int main (void) { int main (int argc, char * argv[]) {
// 4 MBd je maximum.
int baud = 4'000'000;
if (argc > 1) {
baud = atoi (argv[1]);
}
loop = true; loop = true;
signal (SIGINT, Handler); signal (SIGINT, Handler);
UsartClass usart ("/dev/serial/by-id/usb-Kizarm_Labs._USB__=__USART_0002-if00", 1'000'000); //UsartClass usart ("/dev/ttyACM0", baud); // obecně
UsartClass usart ("/dev/serial/by-id/usb-Kizarm_Labs._USB__=__USART_0002-if00", baud);
Top top; Top top;
top += usart; top += usart;
auto start = high_resolution_clock::now();
while (loop) { while (loop) {
top.puts(TestString); top.puts(TestString);
} }
auto stop = high_resolution_clock::now();
usleep(100'000);
int duration = duration_cast<microseconds>(stop - start).count();
top.result(duration);
return 0; return 0;
} }