Browse Source

Use DMAMEM for USB serial transmit buffer

teensy4-core
PaulStoffregen 5 years ago
parent
commit
9557c81817
3 changed files with 19 additions and 11 deletions
  1. +0
    -3
      teensy4/WProgram.h
  2. +3
    -0
      teensy4/avr/pgmspace.h
  3. +16
    -8
      teensy4/usb_serial.c

+ 0
- 3
teensy4/WProgram.h View File

#include "wiring.h" #include "wiring.h"
#include "HardwareSerial.h" #include "HardwareSerial.h"


#define DMAMEM __attribute__ ((section(".dmabuffers"), used))
#define FASTRUN __attribute__ ((section(".fastrun") ))

#ifdef __cplusplus #ifdef __cplusplus


#include "avr_emulation.h" #include "avr_emulation.h"

+ 3
- 0
teensy4/avr/pgmspace.h View File



#include <inttypes.h> #include <inttypes.h>


#define DMAMEM __attribute__ ((section(".dmabuffers"), used))
#define FASTRUN __attribute__ ((section(".fastrun") ))
#define PROGMEM __attribute__((section(".progmem"))) #define PROGMEM __attribute__((section(".progmem")))

#define PGM_P const char * #define PGM_P const char *
#define PSTR(str) ({static const char data[] PROGMEM = (str); &data[0];}) #define PSTR(str) ({static const char data[] PROGMEM = (str); &data[0];})



+ 16
- 8
teensy4/usb_serial.c View File

#include "core_pins.h"// for delay() #include "core_pins.h"// for delay()
//#include "HardwareSerial.h" //#include "HardwareSerial.h"
#include <string.h> // for memcpy() #include <string.h> // for memcpy()
#include "avr/pgmspace.h" // for PROGMEM, DMAMEM, FASTRUN


#include "debug/printf.h" #include "debug/printf.h"
#include "core_pins.h" #include "core_pins.h"
volatile uint8_t usb_cdc_line_rtsdtr=0; volatile uint8_t usb_cdc_line_rtsdtr=0;
volatile uint8_t usb_cdc_transmit_flush_timer=0; volatile uint8_t usb_cdc_transmit_flush_timer=0;


//static usb_packet_t *rx_packet=NULL;
//static usb_packet_t *tx_packet=NULL;
static volatile uint8_t tx_noautoflush=0; static volatile uint8_t tx_noautoflush=0;
extern volatile uint8_t usb_high_speed; extern volatile uint8_t usb_high_speed;


static void timer_stop(); static void timer_stop();
static void usb_serial_flush_callback(void); static void usb_serial_flush_callback(void);


#define TX_NUM 7
#define TX_SIZE 1024 /* should be a multiple of CDC_TX_SIZE */
#define TX_NUM 4
#define TX_SIZE 2048 /* should be a multiple of CDC_TX_SIZE */
static transfer_t tx_transfer[TX_NUM] __attribute__ ((used, aligned(32))); static transfer_t tx_transfer[TX_NUM] __attribute__ ((used, aligned(32)));
static uint8_t txbuffer[TX_SIZE * TX_NUM];
DMAMEM static uint8_t txbuffer[TX_SIZE * TX_NUM];
static uint8_t tx_head=0; static uint8_t tx_head=0;
static uint16_t tx_available=0; static uint16_t tx_available=0;
static uint16_t tx_packet_size=0; static uint16_t tx_packet_size=0;
memcpy(txdata, data, tx_available); memcpy(txdata, data, tx_available);
//*(txbuffer + (tx_head * TX_SIZE)) = 'A' + tx_head; // to see which buffer //*(txbuffer + (tx_head * TX_SIZE)) = 'A' + tx_head; // to see which buffer
//*(txbuffer + (tx_head * TX_SIZE) + 1) = ' '; // really see it //*(txbuffer + (tx_head * TX_SIZE) + 1) = ' '; // really see it
usb_prepare_transfer(xfer, txbuffer + (tx_head * TX_SIZE), TX_SIZE, 0);
uint8_t *txbuf = txbuffer + (tx_head * TX_SIZE);
usb_prepare_transfer(xfer, txbuf, TX_SIZE, 0);
arm_dcache_flush_delete(txbuf, TX_SIZE);
usb_transmit(CDC_TX_ENDPOINT, xfer); usb_transmit(CDC_TX_ENDPOINT, xfer);
if (++tx_head >= TX_NUM) tx_head = 0; if (++tx_head >= TX_NUM) tx_head = 0;
size -= tx_available; size -= tx_available;


void usb_serial_flush_output(void) void usb_serial_flush_output(void)
{ {

if (!usb_configuration) return; if (!usb_configuration) return;
if (tx_available == 0) return; if (tx_available == 0) return;
tx_noautoflush = 1; tx_noautoflush = 1;
transfer_t *xfer = tx_transfer + tx_head; transfer_t *xfer = tx_transfer + tx_head;
usb_prepare_transfer(xfer, txbuffer + (tx_head * TX_SIZE), TX_SIZE - tx_available, 0);
uint8_t *txbuf = txbuffer + (tx_head * TX_SIZE);
uint32_t txnum = TX_SIZE - tx_available;
usb_prepare_transfer(xfer, txbuf, txnum, 0);
arm_dcache_flush_delete(txbuf, txnum);
usb_transmit(CDC_TX_ENDPOINT, xfer); usb_transmit(CDC_TX_ENDPOINT, xfer);
if (++tx_head >= TX_NUM) tx_head = 0; if (++tx_head >= TX_NUM) tx_head = 0;
tx_available = 0; tx_available = 0;
if (tx_available == 0) return; if (tx_available == 0) return;
//printf("flush callback, %d bytes\n", TX_SIZE - tx_available); //printf("flush callback, %d bytes\n", TX_SIZE - tx_available);
transfer_t *xfer = tx_transfer + tx_head; transfer_t *xfer = tx_transfer + tx_head;
usb_prepare_transfer(xfer, txbuffer + (tx_head * TX_SIZE), TX_SIZE - tx_available, 0);
uint8_t *txbuf = txbuffer + (tx_head * TX_SIZE);
uint32_t txnum = TX_SIZE - tx_available;
usb_prepare_transfer(xfer, txbuf, txnum, 0);
arm_dcache_flush_delete(txbuf, txnum);
usb_transmit(CDC_TX_ENDPOINT, xfer); usb_transmit(CDC_TX_ENDPOINT, xfer);
if (++tx_head >= TX_NUM) tx_head = 0; if (++tx_head >= TX_NUM) tx_head = 0;
tx_available = 0; tx_available = 0;

Loading…
Cancel
Save