LIN network - how do use LINbreak detect interrupt in receiving LIN Message.

Status
Not open for further replies.

Franky_74

Member
Hello - i have a big topic an i need help.

* Background
At my work we have some trouble with our electronics and we get some suspect error message reported from our customer as reported from field tests.
Our electronics component are coupled by a Lin network together.
One electronic component which bring the error send some internal data out in classical serial data.

Because we want to have this data i search for a method and suggest the OPEN LOG tool.

As our customer send more detailed error reports i know we also need the LIN data. (19200)

So i try to port the software of the OPEN Log device to Teensy 3.1 base.
At this time the Openlog is ported more or less to teensy - if i'm sure i will make this version public.
But as i say i also want to Log the raw Lin data.
Principially it should an easy task - but i need some help, because this project need to be finishd in one week - the customer waits for a possibility to log the data.
It's not a offical project because we did'nt have software writer capacity for it and it's normally not my task to write SW so i try to solve this topic in my freetime. But my girlfriend di'nt like it because we will marry in two weeks and this too need some preparations.
At this time i did'nt have a plan how to detect the LIN break by interrupt and to read out one ID data sequence.

Could someone show me a way how to use a serial interrupt and how it is possible to use the Linbreak detect function.


My system setting:

Uart 1 - LIN data.
Uart 3 - serial data from test device
Spi - Micro SD Card Adapter

I hope someone can show me the way to solve this topic - because i ordered 30 Teensy 3.1 and 30 Micro SD Card adapters.
I try to read the documentation but at this time it's neccesary to RFM but - as i say my time to my weeding day is not so long.

Best regards,
Frank
 
An easy way to detect the Lin Line-Break is to check for the Framing-Error on the UART there is surely something similar in the Teensy3 with that you can modify the code templates below.

Look at this document K20P64M72SF1RM.pdf the Chip from the Teensy under 47.3.5 UART Status Register 1 (UART_S1) the Teensy can native handle LIN communication. So far some reading is necessary, sorry.

Some hints for you, for the comminication look there.

https://github.com/gandrewstone/LIN and

https://github.com/MarkusLange/LIN_for_Arduino_AVR
 
Last edited:
Thanks for your answer.

Makus - many thanks for your Link to your code and for sharing - it is really usefull

If i understand your code correct - than it is necessary to check (poll for Framing Error bit (Uart_S1[1] - clear it - and then read the Lin frame

Its a nice solution - but I'm not sure about the timing aspects

If i read and write only small ammounts to sd-card it should work fine.

But in my case i have a buffer of 8k which is written to SD - - therefore i prefer ISR methode - so i should be sure that no frame is missed.....

the reason for this is that the maximum acces time if i write to a SD card is in a range of 520 ms (deponds on sd card size and type in this case 64GB intenso) thatswhy i prefer to have a big buffer size.
Also the teensys will be used in hot and EMC noisy enviroment.
All this factors can influence the write time.


At this time i modify different files to use the ISR variant - but at this time i don't know what i'm done wrong.

Schema :
in the setup routine i initiallise the serial port.

ins the configuration routine i set in Uart0_S2


Linbreak detection enable Bit
Breaktransmit bit

then i activate the

NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);

every time i get an interrupt the routine uart0_status_isr is called

if the Linbreakdetectflag is set i increase Lincounter and reset the Linbreakdetectflag by writing a 1 to it...

this is the idea behind:

if this work in irq mode the rx transmit buffer should be filled by the isr .

but at this time - i can set the register
if i connect external Linbus devices: than triggers this Linpackets the Linbreakdetect flag

my Linpacketcounter is not increased
Linbreakdetectflag seems not to trigger because the ISR seems not to be processed

Something wron happens with Linstatus counter because the value of Serial.LINSTATUS() = -1 but i set in serial1.c the startvalue to 20


I'm sure something is wrong with my ISR but i did'nt find why it di'dnt work ;-(



I post the code and the file whicjh are modified by my. modification is in boldI hope it is ok if i post the comlete files with modification....

Many thanks for reading and helping....


I will split it in 3 Parts because file limits

Frank
0. my test sketch



// set this to the hardware serial port you wish to use
#define HWSERIAL Serial1


#define Serial_MODE 0
#define LIN_MODE 1
#define UART_MODE LIN_MODE


#define LEDPIN 13

char ledVal = 0;
int Lincounter= 0;
int LoopCounter= 0;


void setup() {
Serial.begin(57600);
HWSERIAL.begin(19200);
pinMode(LEDPIN, OUTPUT);
ledVal = 0;
digitalWrite(LEDPIN, ledVal); // Start the LED off
NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);
}

void loop() {
int incomingByte;
digitalWrite(LEDPIN, ledVal ^= 1);
delay(200);



// incomingByte = Serial.read();
Serial.print("Linstatus_t: ");
// Serial.println(incomingByte, DEC);

Serial.println(Serial.LINSTATUS(), DEC);

Serial.print("UART_S2: ");
// Serial.println(incomingByte, DEC);

Serial.println(UART0_S2, BIN);

Serial.print("Loop_counter : ");

Serial.println(LoopCounter, DEC);



// HWSERIAL.print("USB received:");
// HWSERIAL.println(incomingByte, DEC);

if (HWSERIAL.available() > 0) {
incomingByte = HWSERIAL.read();
Serial.print("UART received: ");
Serial.println(incomingByte, DEC);
HWSERIAL.print("UART received:");
HWSERIAL.println(incomingByte, DEC);
}

if (LoopCounter < 1000) LoopCounter++;
else LoopCounter = 0;

}







1. modify the mk20dx128.h because some bit definitions for registers are missing:


#define UART_S2_LBKDIF (uint8_t)0x80 // Lin Break Detect Interrupt Flag
#define UART_S2_RXEDGIF (uint8_t)0x40 // RxD Pin Active Edge Interrupt Flag
#define UART_S2_MSBF (uint8_t)0x20 // Most significant Byte First
#define UART_S2_RXINV (uint8_t)0x10 // Receive Data Inversion
#define UART_S2_RWUID (uint8_t)0x08 // Receiver Wakeup Idle Detect
#define UART_S2_BRK13 (uint8_t)0x04 // Break Transmit Character Lenght
#define UART_S2_LBKDE (uint8_t)0x02 // LIN Break detection Enable
#define UART_S2_RAF (uint8_t)0x01 // Receiver Active Flag



2. modify. serial1.c

/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.RX
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "mk20dx128.h"
#include "core_pins.h"
#include "HardwareSerial.h"


// at this time useless i a prior version i try to use a definition like this in my sketch to change the mod of uart by this defines
//#define Serial_MODE 0
//#define LIN_MODE 1
//#define UART_MODE LIN_MODE
///////
#define Serial_MODE 0
#define LIN_MODE 1
#define UART_MODE LIN_MODE


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

#define TX_BUFFER_SIZE 64 // number of outgoing bytes to buffer
#define RX_BUFFER_SIZE 2048// number of incoming bytes to buffer
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest


////////////////////////////////////////////////////////////////
// changes not recommended below this point....
////////////////////////////////////////////////////////////////

#ifdef SERIAL_9BIT_SUPPORT
static uint8_t use9Bits = 0;
#define BUFTYPE uint16_t
#else
#define BUFTYPE uint8_t
#define use9Bits 0
#endif

static volatile BUFTYPE tx_buffer[TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[RX_BUFFER_SIZE];
static volatile uint8_t transmitting = 0;
static volatile uint8_t *transmit_pin=NULL;

//#if UART_MODE == LIN_MODE
static volatile uint16_t lin_break_count = 20; // set it for test to 20 because in terminal program i see a value of -1
//#endif


#if TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
static volatile uint8_t rx_buffer_head = 0;
static volatile uint8_t rx_buffer_tail = 0;
#endif

// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer

#define C2_ENABLE UART_C2_TE | UART_C2_RE | UART_C2_RIE | UART_C2_ILIE
#define C2_TX_ACTIVE C2_ENABLE | UART_C2_TIE
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE

void serial_begin(uint32_t divisor)
{
SIM_SCGC4 |= SIM_SCGC4_UART0; // turn on clock, TODO: use bitband
rx_buffer_head = 0;
rx_buffer_tail = 0;
tx_buffer_head = 0;
tx_buffer_tail = 0;
transmitting = 0;
CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
UART0_BDH = (divisor >> 13) & 0x1F;
UART0_BDL = (divisor >> 5) & 0xFF;
UART0_C4 = divisor & 0x1F;
//UART0_C1 = 0;
UART0_C1 = UART_C1_ILT;
UART0_TWFIFO = 2; // tx watermark, causes S1_TDRE to set
UART0_RWFIFO = 4; // rx watermark, causes S1_RDRF to set
UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
UART0_C2 = C2_TX_INACTIVE;
// #if UART_MODE == LIN_MODE
UART0_S2 = UART0_S2 | UART_S2_BRK13 | UART_S2_LBKDE;
// #endif


NVIC_SET_PRIORITY(IRQ_UART0_STATUS, IRQ_PRIORITY);
NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);
}

void serial_format(uint32_t format)
{
uint8_t c;

c = UART0_C1;
c = (c & ~0x13) | (format & 0x03); // configure parity
if (format & 0x04) c |= 0x10; // 9 bits (might include parity)
UART0_C1 = c;
if ((format & 0x0F) == 0x04) UART0_C3 |= 0x40; // 8N2 is 9 bit with 9th bit always 1
c = UART0_S2 & ~0x10;
if (format & 0x10) c |= 0x10; // rx invert
UART0_S2 = c;
c = UART0_C3 & ~0x10;
if (format & 0x20) c |= 0x10; // tx invert
UART0_C3 = c;
#ifdef SERIAL_9BIT_SUPPORT
c = UART0_C4 & 0x1F;
if (format & 0x08) c |= 0x20; // 9 bit mode with parity (requires 10 bits)
UART0_C4 = c;
use9Bits = format & 0x80;
#endif
}

void serial_end(void)
{
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
while (transmitting) yield(); // wait for buffered data to send
NVIC_DISABLE_IRQ(IRQ_UART0_STATUS);
UART0_C2 = 0;
CORE_PIN0_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_tail = 0;
}

void serial_set_transmit_pin(uint8_t pin)
{
while (transmitting) ;
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
transmit_pin = portOutputRegister(pin);
}

void serial_putchar(uint32_t c)
{
uint32_t head, n;

if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
if (transmit_pin) *transmit_pin = 1;
head = tx_buffer_head;
if (++head >= TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((UART0_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
UART0_D = n;
tx_buffer_tail = tail;
}
} else if (priority >= 256) {
yield();
}
}
tx_buffer[head] = c;
transmitting = 1;
tx_buffer_head = head;
UART0_C2 = C2_TX_ACTIVE;
}

void serial_write(const void *buf, unsigned int count)
{
const uint8_t *p = (const uint8_t *)buf;
const uint8_t *end = p + count;
uint32_t head, n;

if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
if (transmit_pin) *transmit_pin = 1;
while (p < end) {
head = tx_buffer_head;
if (++head >= TX_BUFFER_SIZE) head = 0;
if (tx_buffer_tail == head) {
UART0_C2 = C2_TX_ACTIVE;
do {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((UART0_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
UART0_D = n;
tx_buffer_tail = tail;
}
} else if (priority >= 256) {
yield();
}
} while (tx_buffer_tail == head);
}
tx_buffer[head] = *p++;
transmitting = 1;
tx_buffer_head = head;
}
UART0_C2 = C2_TX_ACTIVE;
}

void serial_flush(void)
{
while (transmitting) yield(); // wait
}

int serial_available(void)
{
uint32_t head, tail;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head >= tail) return head - tail;
return RX_BUFFER_SIZE + head - tail;
}


int LIN_detected()
{



return lin_break_count;
}

int serial_getchar(void)
{
uint32_t head, tail;
int c;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= RX_BUFFER_SIZE) tail = 0;
c = rx_buffer[tail];
rx_buffer_tail = tail;
return c;
}

int serial_peek(void)
{
uint32_t head, tail;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= RX_BUFFER_SIZE) tail = 0;
return rx_buffer[tail];
}

void serial_clear(void)
{
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
UART0_C2 &= ~(UART_C2_RE | UART_C2_RIE | UART_C2_ILIE);
UART0_CFIFO = UART_CFIFO_RXFLUSH;
UART0_C2 |= (UART_C2_RE | UART_C2_RIE | UART_C2_ILIE);
rx_buffer_head = rx_buffer_tail;
}

// status interrupt combines
// Transmit data below watermark UART_S1_TDRE
// Transmit complete UART_S1_TC
// Idle line UART_S1_IDLE
// Receive data above watermark UART_S1_RDRF
// LIN break detect UART_S2_LBKDIF
// RxD pin active edge UART_S2_RXEDGIF

void uart0_status_isr(void)
{
uint32_t head, newhead, tail, n;
uint8_t avail, c;

if (UART0_S2 & UART_S2_LBKDIF)
{
__disable_irq();
if (lin_break_count < 100)
{
lin_break_count++;
UART0_S2 = UART0_S2 | UART_S2_LBKDIF; // to clear the LIN Flag write it
}
else lin_break_count = 0;
__enable_irq();

}




if (UART0_S1 & (UART_S1_RDRF | UART_S1_IDLE)) {
__disable_irq();
avail = UART0_RCFIFO;
if (avail == 0) {
// The only way to clear the IDLE interrupt flag is
// to read the data register. But reading with no
// data causes a FIFO underrun, which causes the
// FIFO to return corrupted data. If anyone from
// Freescale reads this, what a poor design! There
// write should be a write-1-to-clear for IDLE.
c = UART0_D;
// flushing the fifo recovers from the underrun,
// but there's a possible race condition where a
// new character could be received between reading
// RCFIFO == 0 and flushing the FIFO. To minimize
// the chance, interrupts are disabled so a higher
// priority interrupt (hopefully) doesn't delay.
// TODO: change this to disabling the IDLE interrupt
// which won't be simple, since we already manage
// which transmit interrupts are enabled.
UART0_CFIFO = UART_CFIFO_RXFLUSH;
__enable_irq();
} else {
__enable_irq();
head = rx_buffer_head;
tail = rx_buffer_tail;
do {
n = UART0_D;
if (use9Bits && (UART0_C3 & 0x80)) n |= 0x100;
newhead = head + 1;
if (newhead >= RX_BUFFER_SIZE) newhead = 0;
if (newhead != tail) {
head = newhead;
rx_buffer[head] = n;
}
} while (--avail > 0);
rx_buffer_head = head;
}
}
c = UART0_C2;
if ((c & UART_C2_TIE) && (UART0_S1 & UART_S1_TDRE)) {
head = tx_buffer_head;
tail = tx_buffer_tail;
do {
if (tail == head) break;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
avail = UART0_S1;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
UART0_D = n;
} while (UART0_TCFIFO < 8);
tx_buffer_tail = tail;
if (UART0_S1 & UART_S1_TDRE) UART0_C2 = C2_TX_COMPLETING;
}
if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) {
transmitting = 0;
if (transmit_pin) *transmit_pin = 0;
UART0_C2 = C2_TX_INACTIVE;
}
}



void serial_print(const char *p)
{
while (*p) {
char c = *p++;
if (c == '\n') serial_putchar('\r');
serial_putchar(c);
}
}

static void serial_phex1(uint32_t n)
{
n &= 15;
if (n < 10) {
serial_putchar('0' + n);
} else {
serial_putchar('A' - 10 + n);
}
}

void serial_phex(uint32_t n)
{
serial_phex1(n >> 4);
serial_phex1(n);
}

void serial_phex16(uint32_t n)
{
serial_phex(n >> 8);
serial_phex(n);
}

void serial_phex32(uint32_t n)
{
serial_phex(n >> 24);
serial_phex(n >> 16);
serial_phex(n >> 8);
serial_phex(n);
}


3. in HardwareSerial_h i modify and public HardwareSerial

/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef HardwareSerial_h
#define HardwareSerial_h

#include "mk20dx128.h"
#include <inttypes.h>

// uncomment to enable 9 bit formats
//#define SERIAL_9BIT_SUPPORT




#define SERIAL_7E1 0x02
#define SERIAL_7O1 0x03
#define SERIAL_8N1 0x00
#define SERIAL_8N2 0x04
#define SERIAL_8E1 0x06
#define SERIAL_8O1 0x07
#define SERIAL_7E1_RXINV 0x12
#define SERIAL_7O1_RXINV 0x13
#define SERIAL_8N1_RXINV 0x10
#define SERIAL_8N2_RXINV 0x14
#define SERIAL_8E1_RXINV 0x16
#define SERIAL_8O1_RXINV 0x17
#define SERIAL_7E1_TXINV 0x22
#define SERIAL_7O1_TXINV 0x23
#define SERIAL_8N1_TXINV 0x20
#define SERIAL_8N2_TXINV 0x24
#define SERIAL_8E1_TXINV 0x26
#define SERIAL_8O1_TXINV 0x27
#define SERIAL_7E1_RXINV_TXINV 0x32
#define SERIAL_7O1_RXINV_TXINV 0x33
#define SERIAL_8N1_RXINV_TXINV 0x30
#define SERIAL_8N2_RXINV_TXINV 0x34
#define SERIAL_8E1_RXINV_TXINV 0x36
#define SERIAL_8O1_RXINV_TXINV 0x37
#ifdef SERIAL_9BIT_SUPPORT
#define SERIAL_9N1 0x84
#define SERIAL_9E1 0x8E
#define SERIAL_9O1 0x8F
#define SERIAL_9N1_RXINV 0x94
#define SERIAL_9E1_RXINV 0x9E
#define SERIAL_9O1_RXINV 0x9F
#define SERIAL_9N1_TXINV 0xA4
#define SERIAL_9E1_TXINV 0xAE
#define SERIAL_9O1_TXINV 0xAF
#define SERIAL_9N1_RXINV_TXINV 0xB4
#define SERIAL_9E1_RXINV_TXINV 0xBE
#define SERIAL_9O1_RXINV_TXINV 0xBF
#endif
// bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit
// bit3: mode10: 1=10bit, 0=8bit
// bit4: rxinv, 0=normal, 1=inverted
// bit5: txinv, 0=normal, 1=inverted
// bit6: unused
// bit7: actual data goes into 9th bit


#define BAUD2DIV(baud) (((F_CPU * 2) + ((baud) >> 1)) / (baud))
#define BAUD2DIV3(baud) (((F_BUS * 2) + ((baud) >> 1)) / (baud))

// C language implementation
//
#ifdef __cplusplus
extern "C" {
#endif
void serial_begin(uint32_t divisor);
void serial_format(uint32_t format);
void serial_end(void);
void serial_set_transmit_pin(uint8_t pin);
void serial_putchar(uint32_t c);
void serial_write(const void *buf, unsigned int count);
void serial_flush(void);
int serial_available(void);
int LIN_detected(void);
int serial_getchar(void);
int serial_peek(void);
void serial_clear(void);
void serial_print(const char *p);
void serial_phex(uint32_t n);
void serial_phex16(uint32_t n);
void serial_phex32(uint32_t n);

void serial2_begin(uint32_t divisor);
void serial2_format(uint32_t format);
void serial2_end(void);
void serial2_putchar(uint32_t c);
void serial2_write(const void *buf, unsigned int count);
void serial2_flush(void);
int serial2_available(void);
int serial2_getchar(void);
int serial2_peek(void);
void serial2_clear(void);

void serial3_begin(uint32_t divisor);
void serial3_format(uint32_t format);
void serial3_end(void);
void serial3_putchar(uint32_t c);
void serial3_write(const void *buf, unsigned int count);
void serial3_flush(void);
int serial3_available(void);
int serial3_getchar(void);
int serial3_peek(void);
void serial3_clear(void);

#ifdef __cplusplus
}
#endif


// C++ interface
//
#ifdef __cplusplus
#include "Stream.h"
class HardwareSerial : public Stream
{
public:
virtual void begin(uint32_t baud) { serial_begin(BAUD2DIV(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial_begin(BAUD2DIV(baud));
serial_format(format); }
virtual void end(void) { serial_end(); }
virtual void transmitterEnable(uint8_t pin) { serial_set_transmit_pin(pin); }
virtual int available(void) { return serial_available(); }
virtual int peek(void) { return serial_peek(); }
virtual int read(void) { return serial_getchar(); }
virtual int LINSTATUS(void) { return LIN_detected(); }//LIN_detected(); }
virtual void flush(void) { serial_flush(); }
virtual void clear(void) { serial_clear(); }
virtual size_t write(uint8_t c) { serial_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
virtual size_t write(unsigned int n) { return write((uint8_t)n); }
virtual size_t write(int n) { return write((uint8_t)n); }
virtual size_t write(const uint8_t *buffer, size_t size)
{ serial_write(buffer, size); return size; }
virtual size_t write(const char *str) { size_t len = strlen(str);
serial_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial_putchar(c); return 1; }
};
extern HardwareSerial Serial1;

class HardwareSerial2 : public HardwareSerial
{
public:
virtual void begin(uint32_t baud) { serial2_begin(BAUD2DIV(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial2_begin(BAUD2DIV(baud));
serial2_format(format); }
virtual void end(void) { serial2_end(); }
virtual int available(void) { return serial2_available(); }
virtual int peek(void) { return serial2_peek(); }
virtual int read(void) { return serial2_getchar(); }
virtual int LINSTATUS(void) { return LIN_detected(); }//LIN_detected(); }
virtual void flush(void) { serial2_flush(); }
virtual void clear(void) { serial2_clear(); }
virtual size_t write(uint8_t c) { serial2_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
virtual size_t write(unsigned int n) { return write((uint8_t)n); }
virtual size_t write(int n) { return write((uint8_t)n); }
virtual size_t write(const uint8_t *buffer, size_t size)
{ serial2_write(buffer, size); return size; }
virtual size_t write(const char *str) { size_t len = strlen(str);
serial2_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial2_putchar(c); return 1; }
};
extern HardwareSerial2 Serial2;

class HardwareSerial3 : public HardwareSerial
{
public:
virtual void begin(uint32_t baud) { serial3_begin(BAUD2DIV3(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial3_begin(BAUD2DIV3(baud));
serial3_format(format); }
virtual void end(void) { serial3_end(); }
virtual int available(void) { return serial3_available(); }
virtual int peek(void) { return serial3_peek(); }
virtual int read(void) { return serial3_getchar(); }
virtual int LINSTATUS(void) { return LIN_detected();}//LIN_detected(); }
virtual void flush(void) { serial3_flush(); }
virtual void clear(void) { serial3_clear(); }
virtual size_t write(uint8_t c) { serial3_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
virtual size_t write(unsigned int n) { return write((uint8_t)n); }
virtual size_t write(int n) { return write((uint8_t)n); }
virtual size_t write(const uint8_t *buffer, size_t size)
{ serial3_write(buffer, size); return size; }
virtual size_t write(const char *str) { size_t len = strlen(str);
serial3_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial3_putchar(c); return 1; }
};
extern HardwareSerial3 Serial3;

#endif
#endif
4. in usb_serial.h

i also do the same modification.... it its wrong to do something like this but without i can't compile it.... onlyfor test

/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef USBserial_h_
#define USBserial_h_

#if defined(USB_SERIAL) || defined(USB_SERIAL_HID)

#include <inttypes.h>

#if F_CPU >= 20000000

// C language implementation
#ifdef __cplusplus
extern "C" {
#endif
int usb_serial_getchar(void);
int usb_serial_peekchar(void);
int usb_serial_available(void);
int usb_serial_read(void *buffer, uint32_t size);
void usb_serial_flush_input(void);
int usb_serial_putchar(uint8_t c);
int usb_serial_write(const void *buffer, uint32_t size);
void usb_serial_flush_output(void);
extern uint32_t usb_cdc_line_coding[2];
extern volatile uint8_t usb_cdc_line_rtsdtr;
extern volatile uint8_t usb_cdc_transmit_flush_timer;
extern volatile uint8_t usb_configuration;
#ifdef __cplusplus
}
#endif

#define USB_SERIAL_DTR 0x01
#define USB_SERIAL_RTS 0x02

// C++ interface
#ifdef __cplusplus
#include "Stream.h"
class usb_serial_class : public Stream
{
public:
void begin(long) { /* TODO: call a function that tries to wait for enumeration */ };
void end() { /* TODO: flush output and shut down USB port */ };
virtual int available() { return usb_serial_available(); }
virtual int read() { return usb_serial_getchar(); }
virtual int LINSTATUS(void) { return usb_serial_getchar(); }//LIN_detected(); }
virtual int peek() { return usb_serial_peekchar(); }
virtual void flush() { usb_serial_flush_output(); } // TODO: actually wait for data to leave USB...
virtual size_t write(uint8_t c) { return usb_serial_putchar(c); }
virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial_write(buffer, size); }
size_t write(unsigned long n) { return write((uint8_t)n); }
size_t write(long n) { return write((uint8_t)n); }
size_t write(unsigned int n) { return write((uint8_t)n); }
size_t write(int n) { return write((uint8_t)n); }
using Print::write;
void send_now(void) { usb_serial_flush_output(); }
uint32_t baud(void) { return usb_cdc_line_coding[0]; }
uint8_t stopbits(void) { uint8_t b = usb_cdc_line_coding[1]; if (!b) b = 1; return b; }
uint8_t paritytype(void) { return usb_cdc_line_coding[1] >> 8; } // 0=none, 1=odd, 2=even
uint8_t numbits(void) { return usb_cdc_line_coding[1] >> 16; }
uint8_t dtr(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; }
uint8_t rts(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; }
operator bool() { return usb_configuration && (usb_cdc_line_rtsdtr & (USB_SERIAL_DTR | USB_SERIAL_RTS)); }
size_t readBytes(char *buffer, size_t length) {
size_t count=0;
unsigned long startMillis = millis();
do {
count += usb_serial_read(buffer + count, length - count);
if (count >= length) return count;
} while(millis() - startMillis < _timeout);
setReadError();
return count;
}

};
extern usb_serial_class Serial;
#endif // __cplusplus


#else // F_CPU < 20 MHz

// Allow Arduino programs using Serial to compile, but Serial will do nothing.
#ifdef __cplusplus
#include "Stream.h"
class usb_serial_class : public Stream
{
public:
void begin(long) { };
void end() { };
virtual int available() { return 0; }
virtual int read() { return -1; }
virtual int peek() { return -1; }
virtual void flush() { }
virtual size_t write(uint8_t c) { return 1; }
virtual size_t write(const uint8_t *buffer, size_t size) { return size; }
size_t write(unsigned long n) { return 1; }
size_t write(long n) { return 1; }
size_t write(unsigned int n) { return 1; }
size_t write(int n) { return 1; }
using Print::write;
void send_now(void) { }
uint32_t baud(void) { return 0; }
uint8_t stopbits(void) { return 1; }
uint8_t paritytype(void) { return 0; }
uint8_t numbits(void) { return 8; }
uint8_t dtr(void) { return 1; }
uint8_t rts(void) { return 1; }
operator bool() { return true; }
};

extern usb_serial_class Serial;
#endif // __cplusplus

#endif // F_CPU

#endif // USB_SERIAL || USB_SERIAL_HID

#endif // USBserial_H
 
Impressiv what you done so far, I'm not sure but I think the
int frameerrordelay = ((breakfield + breakdelimiter) - uartlenght)*Tbit;
I added is not nessesary the Linbreak inside the T3 should repeat the right moment so it pass direct the time for the 0x55 sync-part. May Paul can help
 
state documentation....
at the end all is working fine...
my code at this time is some quick and dirty adaptation of the openlog source to teensy.

At this time i can log to an SD card:
LIN communication - (sniffer mode)
RS232

The Teensy serial1 is modified to recognise also Errors like FE.....
This is also how i implemented at the end as Markus_L811 recommend....
Markus - you have done such a nice job ;-)

Sometimes i will relese the clean code or if someone want the "dirt" adaptation - i can share it...

Best regard,
Frank
 
Status
Not open for further replies.
Back
Top