This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LIN Driver / HalCoGen

Other Parts Discussed in Thread: HALCOGEN

I am working on a LIN-Projekt but couldn't find an example to work with.  I describe the conecpt in short here, maybe it starts a helpful discussion and/or answers my open questions.

Init (generated with HalCoGen 3.6.0)

TX/RX-Mask both set to 0xFF HGEN = 1 -> all ID's should be accepted. I am using master mode, my guess is that I'll get interrupts for all ID's even tough my ECU sends them since it's the master. Does it mean that any ID generates an ID_RX and an ID_TX interrupt because there is no masking?

ID-Interrupt, RX-INT enabled, TX-INT can't be enabled in HalCoGen (bug?), enabled it by hand in my code

 

Header-Task

periodically calls linSendHeader(linREG, id); to generate appropriate headers

 

LIN-Taks

set up data for tx-respone or copy data from rx-response

Interrupt Routine

check what caused the interrupt

if  ID interrupt: read ID and notify LIN-TASK.

if  TX_RDY inerrupt: linSetLength();   linSend();       / / writing to last byte of lin->TDx clears this interrupt

if  RX_RDY interrupt: linSetLength();   linGetData();   // reading of last byte from  lin->RDx[i] clears this interrupt

exit -> read linREG->INTVECT0 to clear ID interrupt

In general I find it confusing how to clear interrupts. Is it appropriate to write a 1 to the the corresponding bit in the flag register to clr the interrupt, or is it necessary to read the linREG->INTVECT0  register? If reading the flag is appropriate it would make more sense to handle the tx/rx-response on task level, handling it on interrupt level and copying it on task level creates overhead. If clearing the interrupt by writing a 1 to the bit in the flag register does the job then I would be wondering what the INTVECT0  does.

 

Regards,

Jürgen

  • Jürgen,

    Ju_We said:
    TX/RX-Mask both set to 0xFF HGEN = 1 -> all ID's should be accepted. I am using master mode, my guess is that I'll get interrupts for all ID's even tough my ECU sends them since it's the master. Does it mean that any ID generates an ID_RX and an ID_TX interrupt because there is no masking?

    That is what our TRM says, 26.7.9 of SPNU499b

     

    Ju_We said:
    ID-Interrupt, RX-INT enabled, TX-INT can't be enabled in HalCoGen (bug?), enabled it by hand in my code

    Ok, I see all these interrupts, and I can enable ID-Interrupt and RX Interrupt but not TX Interrupt and not Break interrupt.  Is that similar to your case, they show up but you cannot change the control?

    Ju_We said:
    In general I find it confusing how to clear interrupts. Is it appropriate to write a 1 to the the corresponding bit in the flag register to clr the interrupt, or is it necessary to read the linREG->INTVECT0  register?

       The interrupt vector register is intended to help you write a 2nd level dispatch.  For example suppose the primary vector is for the SCI/LIN,  at the start of your SCI/LIN handler you could read the INTVECT0 register and use it's value (from 0 to 16) in say a switch(index){  case 0:  //No interrupt ...} type dispatch.  Or you could even do something quicker at the assembly level.   But it is not necessary to use INTVECT0.  You can always just work with the flag register and check each bit individually.    I'm not sure why the INTVECT0 register read doesn't clear the RXRDY and TXRDY though - see the note.  So for those interrupts you would need to write a 1 to the flag bit in SCIFLR even if you use INTVECT0.

    Ju_We said:
    If reading the flag is appropriate it would make more sense to handle the tx/rx-response on task level, handling it on interrupt level and copying it on task level creates overhead.

      There are tradeoffs either way.  If you spend too much time in the ISR by doing too much processing, and you leave interrupts disabled, then you are going to impact the worst case response time of your system because other interrupts have to wait until your SCI/LIN ISR finishes.  On the other hand if you could write a fast ISR and it' faster than signalling a task that the interrupt happended and what the flags are, then it may make sense to do the work in the ISR.    With SCI/LIN there are a lot of flags so probably a good idea to bump most of the work out of the ISR and to a task.     One thing to note: if you have enabled an interrupt, and you try to exit the ISR with the interrupt flag still set, you will almost surely wind up right back in the ISR again.   [note that while you're stepping during a debug session, usually interrupts are disabled by the debugger.  so you might see your code stepping out of the ISR and it might look like you're not put back in, but when you 'run' you'd find yourself in the ISR again...]

    Ju_We said:
    If clearing the interrupt by writing a 1 to the bit in the flag register does the job then I would be wondering what the INTVECT0  does.

      Explained this one in the answer to 2 questions above...  it's for dispatch purposes.

  • Hi Anthony,

     

    thanks for your quick reply, I'll look into the details and we'll see. I can confirm the HalCoGen behavior you described. I see the TX/Break interrupts but can't enable them either.

     

    Best Regards,

    Juergen

  • I actually thought about it, it makes perfect sense to grey out the TX-RDY-IINTERRUPT. It would be ready most of the time and the interrupt would be triggered most of the time. The TRM acutally suggest to turn it off most of the time only turn it on when TX response is expected.

    Juergen

  • Hi Juergen,

    Ok.  Makes sense especially since the buffer allows you to load all the transmit bytes at once.

    Jut wanted to check if there are still any open questions on this thread?

     

  • Hi Anthony,

    of course I have some open questions :) I implemented a LIN Master and tested it on a slave with following frames:

    frame_1; ID=0x01; len=8; rx_response necessary

    frame_2; ID=0x2B; len=4; tx_response necessary

    frame_3; ID=0x03; len=4; tx_response necessary

    frame_4; ID=0x02; len=2; rx_response necessary

    Running a rx_frame (e.g. frame_1) works fine. Running the whole schedule won't work because I am facing some trouble with frames which require tx_reponse .

    I attateched code, stripped down to what is relevant:

    TASK AppTask_LIN_Scheduler(): send headers

    TASK AppTask_LIN(): wait for LIN interrupts and handle rx/tx response

    LIN_INTERRUPT: IRQHandler_LIN_ID():

    read linREG->INTVECT0 to find cause of interrupt

    if tx-interrput:

           linREG->FLR |= LIN_TX_READY;      /* clr tx interrput;  doesn't clear the flag as expected             */
           linREG->CLEARINT |= LIN_TX_READY; /* disable TX INT   turns off all interrupts of lin module */

     

    linREG->FLR |= LIN_RX_READY does what I expect, it clears that flag, why does  linREG->FLR |= LIN_TX_READY   not clear the tx-flag?

    linREG->CLEARINT |= LIN_TX_READY -> maybe I missunderstand how to turn off a specific interrupt. From TMI I'd say this should turn off onl the TX_RDY interrupt of the LIN module, however it seems to turn off all interrupts in the module.

     

     Regards,

    Juergen

    6445.app_lin.c

  • Juergen,

    Ju_We said:
    linREG->FLR |= LIN_RX_READY does what I expect, it clears that flag, why does  linREG->FLR |= LIN_TX_READY   not clear the tx-flag?

    According to the documentation in the TRM - the TX_READY - bit 9 - is listed as R/W but it's not 'write 1 to clear' like the LIN_RX_READY bit is.
    It's an indication that the transmit buffer is empty, and to clear this indication you feed the transmit buffer.  If you're done transmitting your 'packet' then you should turn disable the interrupt rather than continuing to feed the buffer data.   Then at the start of the next packet, enable the interrupt after feeding the first data.

    Ju_We said:
    linREG->CLEARINT |= LIN_TX_READY -> maybe I missunderstand how to turn off a specific interrupt. From TMI I'd say this should turn off onl the TX_RDY interrupt of the LIN module, however it seems to turn off all interrupts in the module.

    This happens because the register is designed such that you write a '1' to clear the interrupt enable, and write a '0' to leave it alone.  But when you read the register, it returns a '1' if the interrupt is disabled.

    So, linREG->CLEARINT = 0xFFFFFFFF would make sure all the interrupts are disabled, actually.   linREG->CLEARINT = linREG->CLEARINT would almost do the same; because every interrupt that read as enabled (reads back as '1') would be written back as a '1' and writing '1' disables the interrupt.   The *exception* of course would happen if another task interrupted and set an additional (not already enalbed) interrupt enable bit -- between the read of linREG->CLEARINT and writing back the value that was read.  

    Therefore, you probably should just do:   linREG->CLEARINT = LIN_TX_READY if you only want to clear LIN_TX_READY.  In other words the "|=" needs to be changed to simply "=".

    EDIT:  I forgot to add - the |= on the FLR is potentially a problem since it will clear any other interrupt flags that are set too.  Just like the problem with |= on the CLEARINT register. But, for the FLR depending on your use case, it may not be as simple as doing: linREG->FLR = LIN_RX_READY instead of linREG->FLR |= LIN_RX_READY.  There is one bit in FLR that is a configuration bit -- a potential problem mixing configuration bits in the same register as status flags.  bit 10 - TXWAKE.  if you're intending to use a multiprocessor mode (idle line or address) you might need to fix this bit up before writing to SCITD after you have cleared flags in FLR.