Parcourir la source

Use software-based RTS on Serial2 and Serial3

teensy4-core
PaulStoffregen il y a 8 ans
Parent
révision
6e0dd8ab39
2 fichiers modifiés avec 80 ajouts et 6 suppressions
  1. +40
    -3
      teensy3/serial2.c
  2. +40
    -3
      teensy3/serial3.c

+ 40
- 3
teensy3/serial2.c Voir le fichier

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


#define TX_BUFFER_SIZE 40
#define RX_BUFFER_SIZE 64
#define TX_BUFFER_SIZE 40 // 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_PIN10_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); CORE_PIN10_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 serial2_set_transmit_pin(uint8_t pin) void serial2_set_transmit_pin(uint8_t pin)


int serial2_set_rts(uint8_t pin) int serial2_set_rts(uint8_t pin)
{ {
if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) 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 (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return 0; if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return 0;
if (pin == 22) { if (pin == 22) {
CORE_PIN22_CONFIG = PORT_PCR_MUX(3); CORE_PIN22_CONFIG = PORT_PCR_MUX(3);
return 0; return 0;
} }
UART1_MODEM |= UART_MODEM_RXRTSE; UART1_MODEM |= UART_MODEM_RXRTSE;
*/
return 1; return 1;
} }


{ {
if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return 0; if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return 0;
if (pin == 23) { if (pin == 23) {
CORE_PIN23_CONFIG = PORT_PCR_MUX(3); // TODO: weak pullup or pulldown?
CORE_PIN23_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_PE; // weak pulldown
} else { } else {
UART1_MODEM &= ~UART_MODEM_TXCTSE; UART1_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;
} }


UART1_C2 |= (UART_C2_RE | UART_C2_RIE | UART_C2_ILIE); UART1_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 = UART1_C2; c = UART1_C2;

+ 40
- 3
teensy3/serial3.c Voir le fichier

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


#define TX_BUFFER_SIZE 40
#define RX_BUFFER_SIZE 64
#define TX_BUFFER_SIZE 40 // 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_PIN8_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); CORE_PIN8_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 serial3_set_transmit_pin(uint8_t pin) void serial3_set_transmit_pin(uint8_t pin)
int serial3_set_rts(uint8_t pin) int serial3_set_rts(uint8_t pin)
{ {
if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return 0; if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) 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 == 2) { if (pin == 2) {
CORE_PIN2_CONFIG = PORT_PCR_MUX(3); CORE_PIN2_CONFIG = PORT_PCR_MUX(3);
} else { } else {
return 0; return 0;
} }
UART2_MODEM |= UART_MODEM_RXRTSE; UART2_MODEM |= UART_MODEM_RXRTSE;
*/
return 1; return 1;
} }


{ {
if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return 0; if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return 0;
if (pin == 14) { if (pin == 14) {
CORE_PIN14_CONFIG = PORT_PCR_MUX(3); // TODO: weak pullup or pulldown?
CORE_PIN14_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_PE; // weak pulldown
} else { } else {
UART2_MODEM &= ~UART_MODEM_TXCTSE; UART2_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;
} }


void serial3_clear(void) void serial3_clear(void)
{ {
rx_buffer_head = rx_buffer_tail; rx_buffer_head = rx_buffer_tail;
if (rts_pin) rts_assert();
} }


// status interrupt combines // status interrupt combines
rx_buffer[head] = n; rx_buffer[head] = n;
rx_buffer_head = head; rx_buffer_head = head;
} }
if (rts_pin) {
int avail;
tail = tx_buffer_tail;
if (head >= tail) avail = head - tail;
else avail = RX_BUFFER_SIZE + head - tail;
if (avail >= RTS_HIGH_WATERMARK) rts_deassert();
}
} }
c = UART2_C2; c = UART2_C2;
if ((c & UART_C2_TIE) && (UART2_S1 & UART_S1_TDRE)) { if ((c & UART_C2_TIE) && (UART2_S1 & UART_S1_TDRE)) {

Chargement…
Annuler
Enregistrer