Browse Source

RTS/CTS support for Serial1 on Teensy LC & 3.x (experimental)

main
PaulStoffregen 9 years ago
parent
commit
2c726eae11
2 changed files with 46 additions and 4 deletions
  1. +6
    -0
      teensy3/HardwareSerial.h
  2. +40
    -4
      teensy3/serial1.c

+ 6
- 0
teensy3/HardwareSerial.h View File

serial_format(format); } serial_format(format); }
virtual void end(void) { serial_end(); } virtual void end(void) { serial_end(); }
virtual void transmitterEnable(uint8_t pin) { serial_set_transmit_pin(pin); } virtual void transmitterEnable(uint8_t pin) { serial_set_transmit_pin(pin); }
virtual bool attachRts(uint8_t pin) { return serial_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial_set_cts(pin); }
virtual int available(void) { return serial_available(); } virtual int available(void) { return serial_available(); }
virtual int peek(void) { return serial_peek(); } virtual int peek(void) { return serial_peek(); }
virtual int read(void) { return serial_getchar(); } virtual int read(void) { return serial_getchar(); }
serial2_format(format); } serial2_format(format); }
virtual void end(void) { serial2_end(); } virtual void end(void) { serial2_end(); }
virtual void transmitterEnable(uint8_t pin) { serial2_set_transmit_pin(pin); } virtual void transmitterEnable(uint8_t pin) { serial2_set_transmit_pin(pin); }
virtual bool attachRts(uint8_t pin) { return serial2_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial2_set_cts(pin); }
virtual int available(void) { return serial2_available(); } virtual int available(void) { return serial2_available(); }
virtual int peek(void) { return serial2_peek(); } virtual int peek(void) { return serial2_peek(); }
virtual int read(void) { return serial2_getchar(); } virtual int read(void) { return serial2_getchar(); }
serial3_format(format); } serial3_format(format); }
virtual void end(void) { serial3_end(); } virtual void end(void) { serial3_end(); }
virtual void transmitterEnable(uint8_t pin) { serial3_set_transmit_pin(pin); } virtual void transmitterEnable(uint8_t pin) { serial3_set_transmit_pin(pin); }
virtual bool attachRts(uint8_t pin) { return serial3_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial3_set_cts(pin); }
virtual int available(void) { return serial3_available(); } virtual int available(void) { return serial3_available(); }
virtual int peek(void) { return serial3_peek(); } virtual int peek(void) { return serial3_peek(); }
virtual int read(void) { return serial3_getchar(); } virtual int read(void) { return serial3_getchar(); }

+ 40
- 4
teensy3/serial1.c View File

// Tunable parameters (relatively safe to edit these numbers) // Tunable parameters (relatively safe to edit these numbers)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////


#define TX_BUFFER_SIZE 64 // number of outgoing bytes to buffer
#define RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#define TX_BUFFER_SIZE 64 // number of outgoing bytes to buffer
#define RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#define RTS_HIGH_WATERMARK 40 // RTS requests sender to pause
#define RTS_LOW_WATERMARK 26 // RTS allows sender to resume
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest #define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest




static volatile uint8_t *transmit_pin=NULL; static volatile uint8_t *transmit_pin=NULL;
#define transmit_assert() *transmit_pin = 1 #define transmit_assert() *transmit_pin = 1
#define transmit_deassert() *transmit_pin = 0 #define transmit_deassert() *transmit_pin = 0
static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1
#elif defined(KINETISL) #elif defined(KINETISL)
static volatile uint8_t *transmit_pin=NULL; static volatile uint8_t *transmit_pin=NULL;
static uint8_t transmit_mask=0; static uint8_t transmit_mask=0;
#define transmit_assert() *(transmit_pin+4) = transmit_mask; #define transmit_assert() *(transmit_pin+4) = transmit_mask;
#define transmit_deassert() *(transmit_pin+8) = transmit_mask; #define transmit_deassert() *(transmit_pin+8) = transmit_mask;
static volatile uint8_t *rts_pin=NULL;
static uint8_t rts_mask=0;
#define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask;
#endif #endif
#if TX_BUFFER_SIZE > 255 #if TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0; static volatile uint16_t tx_buffer_head = 0;
CORE_PIN1_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); CORE_PIN1_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
rx_buffer_head = 0; rx_buffer_head = 0;
rx_buffer_tail = 0; rx_buffer_tail = 0;
if (rts_pin) rts_deassert();
} }


void serial_set_transmit_pin(uint8_t pin) void serial_set_transmit_pin(uint8_t pin)
int serial_set_rts(uint8_t pin) int serial_set_rts(uint8_t pin)
{ {
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return 0; if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return 0;
if (pin < CORE_NUM_DIGITAL) {
rts_pin = portOutputRegister(pin);
#if defined(KINETISL)
rts_mask = digitalPinToBitMask(pin);
#endif
pinMode(pin, OUTPUT);
rts_assert();
} else {
rts_pin = NULL;
return 0;
}
/*
if (pin == 6) { if (pin == 6) {
CORE_PIN6_CONFIG = PORT_PCR_MUX(3); CORE_PIN6_CONFIG = PORT_PCR_MUX(3);
} else if (pin == 19) { } else if (pin == 19) {
return 0; return 0;
} }
UART0_MODEM |= UART_MODEM_RXRTSE; UART0_MODEM |= UART_MODEM_RXRTSE;
*/
return 1; return 1;
} }


{ {
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return 0; if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return 0;
if (pin == 18) { if (pin == 18) {
CORE_PIN18_CONFIG = PORT_PCR_MUX(3); // TODO: weak pullup or pulldown?
CORE_PIN18_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_PE; // weak pulldown
} else if (pin == 20) { } else if (pin == 20) {
CORE_PIN20_CONFIG = PORT_PCR_MUX(3); // TODO: weak pullup or pulldown?
CORE_PIN20_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_PE; // weak pulldown
} else { } else {
UART0_MODEM &= ~UART_MODEM_TXCTSE; UART0_MODEM &= ~UART_MODEM_TXCTSE;
return 0; return 0;
if (++tail >= RX_BUFFER_SIZE) tail = 0; if (++tail >= RX_BUFFER_SIZE) tail = 0;
c = rx_buffer[tail]; c = rx_buffer[tail];
rx_buffer_tail = tail; rx_buffer_tail = tail;
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = RX_BUFFER_SIZE + head - tail;
if (avail <= RTS_LOW_WATERMARK) rts_assert();
}
return c; return c;
} }


UART0_C2 |= (UART_C2_RE | UART_C2_RIE | UART_C2_ILIE); UART0_C2 |= (UART_C2_RE | UART_C2_RIE | UART_C2_ILIE);
#endif #endif
rx_buffer_head = rx_buffer_tail; rx_buffer_head = rx_buffer_tail;
if (rts_pin) rts_assert();
} }


// status interrupt combines // status interrupt combines
} }
} while (--avail > 0); } while (--avail > 0);
rx_buffer_head = head; rx_buffer_head = head;
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = RX_BUFFER_SIZE + head - tail;
if (avail >= RTS_HIGH_WATERMARK) rts_deassert();
}
} }
} }
c = UART0_C2; c = UART0_C2;

Loading…
Cancel
Save