Problems with IRQ_UART0_STATUS and attachInterruptVector

Status
Not open for further replies.

Markus_L811

Well-known member
Hello,

I have enabled an trigger event on UART0_S2, the UART_S2_LBKDE Flag, so I attached my ISR routine to it, when the Flag is fired the IRQ_UART0_STATUS does nothing. Even there is nothing inside the ISR routine he should jump in it, it look like IRQ_UART0_STATUS don't look inside UART0_S2.


Simpified Sketch
Code:
#define PRINTBIN(Num) for (uint32_t t = (1UL<< (sizeof(Num)*8)-1); t; t >>= 1) Serial.write(Num  & t ? '1' : '0'); // Prints a binary number with leading zeros (Automatic Handling)

//Lin Initailisation
#define linspeed                19200

int activeBufIndex;
uint8_t *activeBuf;
constexpr int max_LinBUS_Datasize = 10;

int pointer = 0;

void uart0isr_status() {
  UART0_S2 |= UART_S2_LBKDIF;
  UART0_S2 |= UART_S2_RXEDGIF;
  pointer++;
}

void uart0isr_error() {
  UART0_S1 &= ~UART_S1_OR;
  pointer++;
}

void setup() {
  Serial.begin(115200);
  pinMode(19, OUTPUT);
  LinBUS_begin();
}

void loop() {
  Serial.print("UART0_S1 ");
  PRINTBIN(UART0_S1);

  Serial.print(" UART0_S2 ");
  PRINTBIN(UART0_S2);
  Serial.println();
  
  Serial.println(pointer);
  delay(250);
}

void LinBUS_begin(void) {
  Serial1.begin(linspeed);

  attachInterruptVector(IRQ_UART0_STATUS, uart0isr_status);
  attachInterruptVector(IRQ_UART0_ERROR, uart0isr_error);

  // We fill bytes from the buffer in the framing error ISR, so we
  // can set to the same priority.
  NVIC_SET_PRIORITY(IRQ_UART0_ERROR, NVIC_GET_PRIORITY(IRQ_UART0_STATUS));

  //UART0_S2 &= ~UART_S2_RXINV;
  //UART0_C1 |= UART_C1_M;
  //UART0_C4 &= ~UART_C4_M10;
  //UART0_C1 |= UART_C1_PE;
  
  // Enable LinBreakdetection on UART0
  UART0_S2 |= UART_S2_LBKDE;
  NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);
  
  // Enable UART0 interrupt on frame error
  //UART0_C3 |= UART_C3_FEIE;
  //UART0_C3 |= UART_C3_ORIE;
  NVIC_ENABLE_IRQ(IRQ_UART0_ERROR);
}

Output
Code:
12:11:55.173 -> UART0_S1 11000000 UART0_S2 00000010
12:11:55.173 -> 0
12:11:55.173 -> UART0_S1 11000000 UART0_S2 00000010
12:11:55.173 -> 0
12:11:55.173 -> UART0_S1 11000000 UART0_S2 00000010
12:11:55.173 -> 0
12:11:55.173 -> UART0_S1 11000000 UART0_S2 00000010
12:11:55.173 -> 0
12:11:55.173 -> UART0_S1 11000000 UART0_S2 00000010
12:11:55.173 -> 0
12:11:55.173 -> UART0_S1 11000000 UART0_S2 00000010
12:11:55.173 -> 0
12:11:55.173 -> UART0_S1 11000000 UART0_S2 00000010
12:11:55.173 -> 0
12:11:55.405 -> UART0_S1 11000000 UART0_S2 00000010
12:11:55.405 -> 0
12:11:55.675 -> UART0_S1 11000000 UART0_S2 00000010
12:11:55.675 -> 0
12:11:55.929 -> UART0_S1 11001000 UART0_S2 11000010
12:11:55.929 -> 0
12:11:56.176 -> UART0_S1 11001000 UART0_S2 11000010
12:11:56.176 -> 0
12:11:56.430 -> UART0_S1 11001000 UART0_S2 11000010
12:11:56.430 -> 0
12:11:56.678 -> UART0_S1 11001000 UART0_S2 11000010

Any advice to it? May my I made some mistakes.
 
Last edited:
The global pointer variable must be declared volatile, since it will be modified within an ISR. After that, at least the pointer should be incremented at each run of the ISR.
 
From that, we can already conclude that your ISR is never called.

Since the Flag is called he should
Code:
12:11:55.675 -> UART0_S1 11000000 UART0_S2 00000010
12:11:55.929 -> UART0_S1 11001000 UART0_S2 11000010

Teensy 3.0 Manuel on Page 1061
LinBRK_Flag.JPG
 
Modified Version:

Code:
#define LBKDIE  0x80
#define RXEDGIE 0x40

#define PRINTBIN(Num) for (uint32_t t = (1UL<< (sizeof(Num)*8)-1); t; t >>= 1) Serial.write(Num  & t ? '1' : '0'); // Prints a binary number with leading zeros (Automatic Handling)

//Lin Initailisation
#define linspeed                19200

int activeBufIndex;
uint8_t *activeBuf;
constexpr int max_LinBUS_Datasize = 10;

volatile int pointer = 0;

void uart0isr_status() {
  __disable_irq();
  int b = UART0_D;
  UART0_S2 |= UART_S2_LBKDIF;
  UART0_S2 |= UART_S2_RXEDGIF;
  pointer++;
  __enable_irq();
}

void uart0isr_error() {
  __disable_irq();
//  UART0_S1 &= ~UART_S1_OR;
  pointer++;
  __enable_irq();
}

void setup() {
  Serial.begin(115200);
  pinMode(19, OUTPUT);
  LinBUS_begin();
}

void loop() {
  Serial.print("UART0_S1 ");
  PRINTBIN(UART0_S1);

  Serial.print(" UART0_S2 ");
  PRINTBIN(UART0_S2);

  Serial.print(" UART0_BDH ");
  PRINTBIN(UART0_BDH);
  Serial.print(" Pointer ");
  
  Serial.println(pointer);
  delay(250);
}

void LinBUS_begin(void) {
  Serial1.begin(linspeed);

  attachInterruptVector(IRQ_UART0_STATUS, uart0isr_status);
  //attachInterruptVector(IRQ_UART0_ERROR, uart0isr_error);

  // We fill bytes from the buffer in the framing error ISR, so we
  // can set to the same priority.
  //NVIC_SET_PRIORITY(IRQ_UART0_ERROR, NVIC_GET_PRIORITY(IRQ_UART0_STATUS));

  //UART0_S2 &= ~UART_S2_RXINV;
  //UART0_C1 |= UART_C1_M;
  //UART0_C4 &= ~UART_C4_M10;
  //UART0_C1 |= UART_C1_PE;
  
  // Enable LinBreakdetection on UART0
  //UART0_BDH |= LBKDIE;
  //UART0_BDH |= RXEDGIE;
  UART0_S2 |= UART_S2_LBKDE;
  NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);
  
  // Enable UART0 interrupt on frame error
  //UART0_C3 |= UART_C3_FEIE;
  //UART0_C3 |= UART_C3_ORIE;
  //NVIC_ENABLE_IRQ(IRQ_UART0_ERROR);
}

Runs equal to the first until I activate he LBKDIE, it stops there if the LinBreak is detectet imho.

Code:
12:39:29.981 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 00000001 Pointer 0
12:39:30.120 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 00000001 Pointer 0
12:39:30.502 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 00000001 Pointer 0
12:39:30.606 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 00000001 Pointer 0
12:39:30.954 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 00000001 Pointer 0
12:39:31.127 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 00000001 Pointer 0
12:39:31.373 -> UART0_S1 11001000 UART0_S2 11000010 UART0_BDH 00000001 Pointer 0
12:39:31.616 -> UART0_S1 11001000 UART0_S2 11000010 UART0_BDH 00000001 Pointer 0
...

And if LBKDIE is activ:
Code:
12:43:12.572 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
12:43:12.780 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
12:43:13.058 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
12:43:13.266 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
12:43:13.544 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
12:43:13.788 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
12:43:14.030 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
12:43:14.274 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
12:43:14.517 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
12:43:14.763 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
12:43:15.039 -> UART0_S1 11000000 UART0_S2 00000010 UART0_BDH 10000001 Pointer 0
 
The Master if asked: Teensy 3.0 and up

Code:
//Lin Initailisation
#define linspeed                19200
unsigned long Tbit = 1000000/linspeed;

//Tbits Header
#define breakdelimiter              1

#define syncfieldPIDinterbytedelay  0
int syncfieldPIDinterbytespace = syncfieldPIDinterbytedelay*Tbit;
#define breakfieldinterbytedelay    2
int breakfieldinterbytespace = breakfieldinterbytedelay*Tbit;

//Tbit Response
#define responsedelay               8
int responsespace = responsedelay*Tbit;
#define interbytedelay              0
int interbytespace = interbytedelay*Tbit;

void setup() {
  Serial.begin(19200);
  Lininit();
}

void loop() {
  Serial.println("los");
  delay(2000);
  LinBreak();
  delay(2000);
}

void Lininit() {
  Serial1.begin(linspeed);
  pinMode(0, INPUT_PULLUP);
}

//working
void LinBreak() {
//  // 10 Bits transmitted
//  UART0_S2 &= ~UART_S2_BRK13;
//  UART0_C1 &= ~UART_C1_M;

//  // 11 Bits transmitted
//  UART0_S2 &= ~UART_S2_BRK13;
//  UART0_C1 |= UART_C1_M;
//  UART0_C4 &= ~UART_C4_M10;

//  // 12 Bits transmitted
//  UART0_S2 &= ~UART_S2_BRK13;
//  UART0_C1 |= UART_C1_M;
//  UART0_C4 |= UART_C4_M10;
//  UART0_C1 |= UART_C1_PE;

  // 13 Bits transmitted
  UART0_S2 |= UART_S2_BRK13;
  UART0_C1 &= ~UART_C1_M;

//  // 14 Bits transmitted
//  UART0_S2 |= UART_S2_BRK13;
//  UART0_C1 |= UART_C1_M;

  // Toggle SBK to send Break
  UART0_C2 |= UART_C2_SBK;
  UART0_C2 &= ~UART_C2_SBK;
  Serial1.write(0x55); //Sync
  delayMicroseconds(syncfieldPIDinterbytespace);
  Serial1.write(0x23); // PID
  delayMicroseconds(breakfieldinterbytespace);
  
  Serial1.write(0x41); // Data
}

Just connect Master TX to Slave RX for testing
 
Interesting thing:

Code:
  // Enable LinBreakdetection on UART0
  UART0_BDH |= LBKDIE;
  UART0_BDH |= RXEDGIE;
  //UART0_S2 |= UART_S2_LBKDE;
  NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);

Is LBKDIE or RXEDGIE enabled it breaks even if UART_S2_LBKDE is not set.
 
The NXP UART-Testfiles looks like this:

uart_tests_main.c
Code:
#include "common.h"
#include "uart.h"
#include "mcg.h"
#include "uart_tests.h"

/* Globals from sysinit.c */
extern int core_clk_khz;
extern int core_clk_mhz;
extern int periph_clk_khz;

/********************************************************************/
void main (void)
{
	char ch;
        int test_failed;
        
  	    printf("\nRunning the UART test project\n\n");
                
        /* Make sure the clocks are enabled to all UARTs */
       	SIM_SCGC4 |= (SIM_SCGC4_UART0_MASK | SIM_SCGC4_UART1_MASK | SIM_SCGC4_UART2_MASK | SIM_SCGC4_UART3_MASK);
        SIM_SCGC1 |= (SIM_SCGC1_UART4_MASK | SIM_SCGC1_UART5_MASK);
        
        /* Enable a full set of UART signals for each of the UART modules */
 
        /* Enable UART0 functions on PTD */
        PORTD_PCR4 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTD_PCR5 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTD_PCR6 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTD_PCR7 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

        /* Enable the UART1 functions on PTE */
        PORTE_PCR0 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTE_PCR1 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTE_PCR2 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTE_PCR3 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
		
        /* Enable the UART2 functions on PTE */ /* Use for 256 BGA */               
        PORTE_PCR16 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTE_PCR17 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTE_PCR18 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
  	PORTE_PCR19 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        
        /* Enable the UART2 functions on PTD */ /* Use for 144 LQFP */
/*     PORTD_PCR0 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTD_PCR1 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTD_PCR2 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
  	PORTD_PCR3 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
*/        

        /* Enable the UART3 functions on PTC */
        PORTC_PCR16 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTC_PCR17 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTC_PCR18 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTC_PCR19 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        
        /* Enable the UART4 functions on PTC */
        PORTC_PCR12 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTC_PCR13 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTC_PCR14 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTC_PCR15 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        
        /* Enable the UART5 functions on PTE */
        PORTE_PCR8 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTE_PCR9 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTE_PCR10 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        PORTE_PCR11 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
        
        /* Enable the ABORT button IRQ, this is needed for some of the low
         * power mode tests. 
         *
         * NOTE: D9 needs to be removed from the board and J43 7-8 must be ON.
         */
        /* Configure the PTA4 pin for its GPIO function */
        PORTA_PCR4 = PORT_PCR_MUX(0x1); // GPIO is alt1 function for this pin
    
        /* Configure the PTA4 pin for rising edge interrupts */
        PORTA_PCR4 |= PORT_PCR_IRQC(0x9); 
    
        /* Enable the associated IRQ in the NVIC */
        enable_irq(87);      

 	/* initialize number of failed tests counter to zero */
	test_failed = 0;

        /* Run UART tests */

        /* UART register tests */
        test_failed += uart_reg_rst();
         
        /* Call register read/write test with different register values to test.
         * The UART module doesn't have a software reset bit to allow for easily
         * resetting the UART after this test. Since this test changes register
         * values from the defaults and would impact subsequent tests, the 
         * sci_reg_rw test should only be run on its own. These lines should be
         * commented out when running other tests. 
         */

        /* This is the start of the functional tests, so stop and initialize
         * all of the UARTs to a default state.
         */
        uart_init (UART0_BASE_PTR, core_clk_khz, TERMINAL_BAUD);                  
        uart_init (UART1_BASE_PTR, core_clk_khz, TERMINAL_BAUD); 
        uart_init (UART2_BASE_PTR, periph_clk_khz, TERMINAL_BAUD); 
        uart_init (UART3_BASE_PTR, periph_clk_khz, TERMINAL_BAUD); 
        uart_init (UART4_BASE_PTR, periph_clk_khz, TERMINAL_BAUD); 
        uart_init (UART5_BASE_PTR, periph_clk_khz, TERMINAL_BAUD);   
     
        test_failed += uart_lin_break_test();
 
	if (test_failed)
	{
		printf("\n\nTEST FAILED!!!\n");
		printf("\n\n%d test(s) failed.\n", test_failed);
	}
	else
		printf("\n\nAll tests PASS!\n\n");

	while(1)
	{
		ch = in_char();
		out_char(ch);
	} 
}

uart.c
Code:
void uart_init (UART_MemMapPtr uartch, int sysclk, int baud)
{
    register uint16 sbr, brfa;
    uint8 temp;
    
	/* Enable the clock to the selected UART */    
    if(uartch == UART0_BASE_PTR)
		SIM_SCGC4 |= SIM_SCGC4_UART0_MASK;
    else
    	if (uartch == UART1_BASE_PTR)
			SIM_SCGC4 |= SIM_SCGC4_UART1_MASK;
    	else
    		if (uartch == UART2_BASE_PTR)
    			SIM_SCGC4 |= SIM_SCGC4_UART2_MASK;
    		else
    			if(uartch == UART3_BASE_PTR)
    				SIM_SCGC4 |= SIM_SCGC4_UART3_MASK;
    			else
    				if(uartch == UART4_BASE_PTR)
    					SIM_SCGC1 |= SIM_SCGC1_UART4_MASK;
    				else
    					SIM_SCGC1 |= SIM_SCGC1_UART5_MASK;
                                
    /* Make sure that the transmitter and receiver are disabled while we 
     * change settings.
     */
    UART_C2_REG(uartch) &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK );

    /* Configure the UART for 8-bit mode, no parity */
    UART_C1_REG(uartch) = 0;	/* We need all default settings, so entire register is cleared */
    
    /* Calculate baud settings */
    sbr = (uint16)((sysclk*1000)/(baud * 16));
        
    /* Save off the current value of the UARTx_BDH except for the SBR field */
    temp = UART_BDH_REG(uartch) & ~(UART_BDH_SBR(0x1F));
    
    UART_BDH_REG(uartch) = temp |  UART_BDH_SBR(((sbr & 0x1F00) >> 8));
    UART_BDL_REG(uartch) = (uint8)(sbr & UART_BDL_SBR_MASK);
    
    /* Determine if a fractional divider is needed to get closer to the baud rate */
    brfa = (((sysclk*32000)/(baud * 16)) - (sbr * 32));
    
    /* Save off the current value of the UARTx_C4 register except for the BRFA field */
    temp = UART_C4_REG(uartch) & ~(UART_C4_BRFA(0x1F));
    
    UART_C4_REG(uartch) = temp |  UART_C4_BRFA(brfa);    

    /* Enable receiver and transmitter */
    UART_C2_REG(uartch) |= (UART_C2_TE_MASK | UART_C2_RE_MASK );
}

uart_rx_interrupt_tests.c
Code:
#include "common.h"
#include "uart.h"
#include "uart_tests.h"

/* Globals for counting number of interrupts */
int num_rdrf_int = 0;
int num_or_errors = 0;
int num_rxuf_errors = 0;
int num_parity_errors = 0;
int num_nf_errors = 0;
int num_framing_errors = 0;
int num_idle_int = 0;
int num_lin_breaks = 0;

/* Globals from sysinit.c */
extern int core_clk_khz;
extern int core_clk_mhz;
extern int periph_clk_khz;
...
...
int uart_lin_break_test()
{
    UART_MemMapPtr tx_module, rx_module;
    char ch;
    uint32 i;    
    
    /* Make sure the number of LIN break interrupts is zero before starting */
    num_lin_breaks = 0;
    
    printf("\n\nStarting LIN break detect interrupt test.\n");

    /* Determine which UART to use as the transmitter for testing. UART2 or UART3
     * could be used. We'll use UART2 as long as it isn't used as the TERM_PORT.
     */
    if (TERM_PORT != UART2_BASE_PTR)
    {      
       tx_module = UART2_BASE_PTR;   // set the module pointer
       
       printf("\nUsing UART2 on the daughter card as the transmitter.");
       printf("\nConnect one end of a blue wire to J4 pin 2 (UART2_TX)");
    }      
    else
    {      
       tx_module = UART3_BASE_PTR;   // set the module pointer

       printf("\nUsing UART3 on the daughter card as the transmitter.");
       printf("\nConnect one end of a blue wire to J43 pin 2 (UART3_TX)");
    }

    printf("\nPress any key when ready.\n");
    ch = in_char();
    
    /* Determine which UART to use as the receiver for testing. UART4 or UART5
     * could be used. We'll use UART4 as long as it isn't used as the TERM_PORT.
     */
    if (TERM_PORT != UART4_BASE_PTR)
    {      
       rx_module = UART4_BASE_PTR;   // set the module pointer
       
       /* Configure NVIC to enable UART status interrupts for the receiver */
       enable_irq(53);
       
       printf("\nUsing UART4 on the daughter card as the receiver.");
       printf("\nConnect other end of blue wire to J13 pin 2 (UART4_RX)");
    }      
    else
    {      
       rx_module = UART5_BASE_PTR;   // set the module pointer

       /* Configure NVIC to enable UART status interrupts for the receiver */
       enable_irq(55);

       printf("\nUsing UART5 on the daughter card as the receiver.");
       printf("\nConnect other end of blue wire J9 pin 14 (UART5_RX)");
    }

    printf("\nPress any key when ready.\n");
    ch = in_char();
    
    printf("Setup complete. Starting LIN break detect test...\n");
    printf("This test should generate 2 LIN break detect interrupts.\n");
    
    /* Enable LIN break detection mode */
    UART_S2_REG(rx_module) |= UART_S2_LBKDE_MASK;
    
    /* Enable the LIN break detect interrupt */
    UART_BDH_REG(rx_module) |= UART_BDH_LBKDIE_MASK;

    /* Test sending a 10-bit break character. This should NOT generate an interrupt. */
    /* Set C2[SBK] bit to queue a break character for transmission */
    UART_C2_REG(tx_module) |= UART_C2_SBK_MASK; 
    
    /* Clear C2[SBK] so that only one break character is sent */
    UART_C2_REG(tx_module) &= ~UART_C2_SBK_MASK;
    
    /* Delay to allow time for interrupt */
    for( i=0; i < 0x1000; i++);    
    
    /* Test sending an 11-bit break character. This should generate an interrupt. */
    /* BRK13 = 0, M = 1, M10 = 0, PE = X  gives you a 11-bit break char */
    UART_C1_REG(tx_module) |= UART_C1_M_MASK;   

    /* Set C2[SBK] bit to queue a break character for transmission */
    UART_C2_REG(tx_module) |= UART_C2_SBK_MASK; 
    
    /* Clear C2[SBK] so that only one break character is sent */
    UART_C2_REG(tx_module) &= ~UART_C2_SBK_MASK;

    /* Delay to allow time for interrupt */
    for( i=0; i < 0x1000; i++);
    
    /* Configure the receiver for a 12-bit LIN break */
    UART_C1_REG(rx_module) |= UART_C1_M_MASK;
    
    /* Test sending an 11-bit break character. This should generate NOT an interrupt. */
    
    /* BRK13 = 0, M = 1, M10 = 0, PE = X  gives you a 11-bit break char */
    UART_C1_REG(tx_module) |= UART_C1_M_MASK;   

    /* Set C2[SBK] bit to queue a break character for transmission */
    UART_C2_REG(tx_module) |= UART_C2_SBK_MASK; 
    
    /* Clear C2[SBK] so that only one break character is sent */
    UART_C2_REG(tx_module) &= ~UART_C2_SBK_MASK;

    /* Delay to allow time for interrupt */
    for( i=0; i < 0x1000; i++);

	
    /* Test sending a 12-bit break character. This should generate an interrupt. */

    /* BRK13 = 0, M = 1, M10 = 1, PE = 1  gives you a 12-bit break char */
    UART_C4_REG(tx_module) |= UART_C4_M10_MASK;   
    UART_C1_REG(tx_module) |= UART_C1_PE_MASK;   

    /* Set C2[SBK] bit to queue a break character for transmission */
    UART_C2_REG(tx_module) |= UART_C2_SBK_MASK; 
    
    /* Clear C2[SBK] so that only one break character is sent */
    UART_C2_REG(tx_module) &= ~UART_C2_SBK_MASK;
    
    /* Delay to allow time for interrupt */
    for( i=0; i < 0x1000; i++);    
    
    
    /* All tests complete. Return to default UART settings */
    UART_C1_REG(rx_module) &= ~UART_C1_M_MASK;
    UART_S2_REG(rx_module) &= ~UART_S2_LBKDE_MASK;
    UART_BDH_REG(rx_module) &= ~UART_BDH_LBKDIE_MASK;
    
    UART_C1_REG(tx_module) &= ~UART_C1_M_MASK;   
    UART_C4_REG(tx_module) &= ~UART_C4_M10_MASK;   
    UART_C1_REG(tx_module) &= ~UART_C1_PE_MASK;       
    
         
    printf("\nNumber of LIN breaks detected during test = %d\n", num_lin_breaks);

    return (2 - num_lin_breaks);
}

and the ISR
uart_isr.c
Code:
void uart_status_handler(UART_MemMapPtr channel)
{
    uint8 status, temp;
    
    /* Since the flag clearing mechanism will clear any flags in S1
     * that are set, we have to save off the value of the status register
     * and then check against the saved value to be able to detect all of
     * the flags that were set (if you read the status register over and 
     * over again, then you'll only capture the first one that was set.
     */
    
    /* Read and save the S1 value */
    status = UART_S1_REG(channel);
    
    printf("\nS1= 0x%02x",status);

    /* Check to see if the LIN break detect flag is set */
    if (UART_S2_REG(channel) & UART_S2_LBKDIF_MASK)
    {
        printf("\nUART LIN break detected.\n");
        num_lin_breaks++;

        /* Write 1 to flag to clear the flag */
        UART_S2_REG(channel) = UART_S2_LBKDIF_MASK;
    }
}

I didn't see what are different on my code or, what the UART init from Paul did different.
 

Attachments

  • uart-val-code.7z.zip
    228.1 KB · Views: 76
Deactivating the ILIE Idle Line Interrupt Enable does the trick

This works
Code:
#define LBKDIE  0x80

// Prints a binary number with leading zeros (Automatic Handling)
#define PRINTBIN(Num) for (uint32_t t = (1UL<< (sizeof(Num)*8)-1); t; t >>= 1) Serial.write(Num  & t ? '1' : '0');

//Lin Initailisation
#define linspeed                19200

volatile int pointer = 0;

void uart0isr_status() {
  uint8_t b;
  uint8_t status = UART0_S1;

  /* Check to see if the LIN break detect flag is set */
  if (UART0_S2 & UART_S2_LBKDIF) {
    pointer++;
    /* Write 1 to flag to clear the flag */
    UART0_S2 |= UART_S2_LBKDIF;
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(19, OUTPUT);
  LinBUS_begin();
}

void loop() {
  Serial.print("UART0_C1 ");
  PRINTBIN(UART0_C1);
  
  Serial.print(" UART0_C2 ");
  PRINTBIN(UART0_C2);
  
  Serial.print(" UART0_S1 ");
  PRINTBIN(UART0_S1);
  
  Serial.print(" UART0_S2 ");
  PRINTBIN(UART0_S2);
  
  Serial.print(" UART0_BDH ");
  PRINTBIN(UART0_BDH);
  Serial.print(" ");
  
  Serial.println(pointer);
  delay(1000);
}

void LinBUS_begin(void) {
  Serial1.begin(linspeed);
  UART0_C2 &= ~UART_C2_ILIE;
  UART0_C1 &= ~UART_C1_ILT;

  attachInterruptVector(IRQ_UART0_STATUS, uart0isr_status);

//  // 10 Bits transmitted
//  UART0_S2 &= ~UART_S2_BRK13;
//  UART0_C1 &= ~UART_C1_M;

//  // 11 Bits transmitted
//  UART0_S2 &= ~UART_S2_BRK13;
//  UART0_C1 |= UART_C1_M;
//  UART0_C4 &= ~UART_C4_M10;

//  // 12 Bits transmitted
//  UART0_S2 &= ~UART_S2_BRK13;
//  UART0_C1 |= UART_C1_M;
//  UART0_C4 |= UART_C4_M10;
//  UART0_C1 |= UART_C1_PE;

  // 13 Bits transmitted
  UART0_S2 |= UART_S2_BRK13;
  UART0_C1 &= ~UART_C1_M;

//  // 14 Bits transmitted
//  UART0_S2 |= UART_S2_BRK13;
//  UART0_C1 |= UART_C1_M;
  
  // Enable LinBreakdetection on UART0
  UART0_BDH |= LBKDIE;
  UART0_S2 |= UART_S2_LBKDE;
  NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);
}
 
Status
Not open for further replies.
Back
Top