• AVR Freaks

dsPIC33CK256MP508 UART collision bit

Author
drmike
Starting Member
  • Total Posts : 32
  • Reward points : 0
  • Joined: 2013/07/21 13:23:44
  • Location: 0
  • Status: offline
2019/11/08 18:24:07 (permalink)
0

dsPIC33CK256MP508 UART collision bit

I'm using two dsPIC33CK256MP508 in IrDA mode.  Both sides can transmit and one side can receive, most of the time.  But I can't get them to both transmit and receive.  I'm seeing the TXCIF bit in U1STA getting set and the receive side gets 0xff every time even though a good signal is coming in (via scope capture).  The UART has a lot of erratta, but nothing mentions this.  There is no documentation on the TXCIF bit which is called "collision".  But this is a full duplex system and there can be no collisions, so I don't understand what the processor is doing. 
 
The only other clue I have is that after one side receives a block of 24 bytes (sometimes perfectly with the CRC check) it does not send the first character back when loading the U1TXREG.  It sends the next two chars, but the other side just sees 0xff (with TXCIF set). 
 
Register setup (both sides):
/*  set up IR UART comm link  CTS/RTS off, 8 bit, 1 stop no parity,
 *  BRGH = 0, URX, UTX enabled, IrDA mode */
    
    U1BRG = 124;                      // main clock is 75 MHz so this gives 37500 baud
    U1MODEH = 0x0044;
    U1MODE = 0x801E;

    IEC0bits.U1RXIE = 1;  // enable rx interrupt
    IEC0bits.U1TXIE = 1;  // enable tx interrupt
Interrupt routines:
// *****************************************************************************
/*
 UART RX interrupt routine.
 */
extern unsigned char rxbf[64];
extern int rxput, rxgo;

void __attribute__ ( ( __interrupt__ , auto_psv ) ) _U1RXInterrupt(void)
{
    IFS0bits.U1RXIF = 0; // clear interrupt flag
    rxbf[rxput] = U1RXREG;
    rxput++;
    rxput &= 0x3f; // circular buffer
    rxgo++; // tell main another char came in
}

// *****************************************************************************
/*
 UART TX interrupt routine.
 */
extern unsigned char txbf[32];
extern int txget, txgo;

void __attribute__ ( ( __interrupt__ , auto_psv ) ) _U1TXInterrupt(void)
{
    IFS0bits.U1TXIF = 0; // clear interrupt flag
    if(!txgo)
    {
        U1MODEbits.UTXEN = 0;
        return;
    }
    U1TXREG = txbf[txget];
    txget++;
    txgo--; // down count till end
}

 
Seems pretty simple and it should just work.  What am I missing?
EDIT:  I tried a few things and now I'm even more confused.  I'm sure I'm doing something stupid, but I can't see it.
1) I tried changing to UART2 and I got the same results. 
2) I tried moving the input from RP46 to RP44, and got the same results.
I don't think the collision bit means anything, but it would be nice to know what conditions would make it valid.  The manual does not say.
For the IrDA setup I have two processors with the exact same hardware (and before I moved the pin) the exact same I/O.  One processor can receive and transmit just fine, but the other processor can only transmit.  What's weird is that it knows that it got 3 bytes just like I see on the scope, but it always comes out of the UART as 0xFF.  And that is across different UART's and different pins.
The only difference is that one processor transmits first and then tries to receive, while the one that works receives first and then transmits ACK.  Maybe something to do with full buffers - the transmit message is 24 bytes long which is 3 full FIFO's worth - but that should not have anything to do with the receive shift register.
I am super confused - maybe the processor has failed somehow, but I don't see how it can know there was a start and stop bit and not see the data.  I'll keep playing with it, but any ideas will be greatly appreciated!
post edited by drmike - 2019/11/09 10:38:07
#1

6 Replies Related Threads

    Nikolay_Po
    Super Member
    • Total Posts : 1909
    • Reward points : 0
    • Joined: 2012/04/01 13:49:27
    • Location: Russia, Novorossiysk
    • Status: offline
    Re: dsPIC33CK256MP508 UART collision bit 2019/11/09 13:08:01 (permalink)
    0
    extern volatile int rxput, rxgo;

    The second qualifier is mandatory.
    #2
    drmike
    Starting Member
    • Total Posts : 32
    • Reward points : 0
    • Joined: 2013/07/21 13:23:44
    • Location: 0
    • Status: offline
    Re: dsPIC33CK256MP508 UART collision bit 2019/11/09 14:04:35 (permalink)
    0
    At the speeds I'm running several million cycles go by before these variables change, so that part works fine.  At this point I'm pretty sure I have faulty silicon.  I tried to just send all nulls, and it worked!  So then I sent a count 0, 1, 2, ... up to 0x18.  What I got was 0, FF, FE, FF, FC, FF, FE, FF, F8 ... which says a 0 is shifted in at the beginning and as soon as a 1 shows up, it stays 1's the rest of the way.  This happens on all the UART's.    Since all I actually need is ACK or NAK for my system to work, I can live with this.  I send a null for ACK and 1 for NAK which shows up as -1 (FF) and that's all I need. 
     
    When I need to build a bunch of these things it will be the first thing I better check.  The side that needs to get data needs all the bits to work!
    #3
    Nikolay_Po
    Super Member
    • Total Posts : 1909
    • Reward points : 0
    • Joined: 2012/04/01 13:49:27
    • Location: Russia, Novorossiysk
    • Status: offline
    Re: dsPIC33CK256MP508 UART collision bit 2019/11/09 15:13:56 (permalink)
    0
    drmike
    At the speeds I'm running several million cycles go by before these variables change, so that part works fine.

     
    Quite presumptuous sentence. If you're changing a variable inside of an interrupt and the variable is accessed by main() or different interrupt then you should use volatile qualifier. Else the compiler is free to ignore variable change done in different context. Just add to external variables declarations a volatile qualifier to be on safe side. Many peoples thought the silicon was faulty until they add "volatile".
     
    At this point I'm pretty sure I have faulty silicon.  I tried to just send all nulls, and it worked!  So then I sent a count 0, 1, 2, ... up to 0x18.  What I got was 0, FF, FE, FF, FC, FF, FE, FF, F8 ... which says a 0 is shifted in at the beginning and as soon as a 1 shows up, it stays 1's the rest of the way.

     
    You haven't mentioned which hardware you're using for IrDA transmission. I have none experience with IrDA but may guess that the receiver at the TX side may be overloaded by own side TX signal reflections and may require more time to recover. Did you check the waveform at the Rx pin at master side in working mode when there is an ACK signal after master transmission?
    #4
    drmike
    Starting Member
    • Total Posts : 32
    • Reward points : 0
    • Joined: 2013/07/21 13:23:44
    • Location: 0
    • Status: offline
    Re: dsPIC33CK256MP508 UART collision bit 2019/11/09 15:38:49 (permalink)
    0
    Even the debugger can see the data change, and the variables are changed as they are supposed to, so yes, it's probably a good idea for things when 100's of cycles go by before checking.  But when millions of cycles go by, updating isn't an issue.
    I do have the inputs to the RX on both sides up on my scope.  I'm using a WP7113F3BT IR transmitter (driven by MOSFET) along with its matching WP7113DP1B IR receiver.  When properly aligned (which was definitely a problem when I started) the voltage on the receive sides is 3.6 and 3.7 volts.  The pins I chose are 5V tolerant so this was OK.
     
    If cross talk was an issue, it would be an issue for both processors.  The receive side that is broken sees the zeros which are sent, then locks up and shifts as soon as it sees a 1.  If there was cross talk, the results would be more scrambled.
     
    Now that I think about it, it's kind of running in half duplex mode with one side sending and the other side waiting for the full message, and then responding.  So if there was cross talk, the sending side would see more data come in while it was sending.  Since I'm interrupt driven, those receive bytes would be noticed.  That's not what happens.  I know this 2 ways: 1) can stop the code with the debugger and 2) I have GPIO flags which fire in each part of the program.  If I was receiving data from cross talk I'd see it.
     
    And back to the volatile thing - I have the same code on both processors for the interrupts.  One works fine.  If that were really an issue, they'd both be broken equally.  That's what makes this so confusing - they should both either work, or both be broken. 
     
    Feels like Schrodinger's cat - one is dead and one is alive so the system is both dead and alive!
     
    Thanks for taking an interest.  Digging through the logic is very helpful.
    #5
    Antipodean
    Super Member
    • Total Posts : 1763
    • Reward points : 0
    • Joined: 2008/12/09 10:19:08
    • Location: Didcot, United Kingdom
    • Status: offline
    Re: dsPIC33CK256MP508 UART collision bit 2019/11/09 16:16:20 (permalink)
    0
    drmike
    Even the debugger can see the data change, and the variables are changed as they are supposed to, so yes, it's probably a good idea for things when 100's of cycles go by before checking.  But when millions of cycles go by, updating isn't an issue.
     



    No, you missed the point of what you were being told. 
     
    If you do not include the 'volatile' operator the compiler is likely to do away with that variable before a single clock cycle goes by.
     
     
     

    Do not use my alias in your message body when replying, your message will disappear ...

    Alan
    #6
    drmike
    Starting Member
    • Total Posts : 32
    • Reward points : 0
    • Joined: 2013/07/21 13:23:44
    • Location: 0
    • Status: offline
    Re: dsPIC33CK256MP508 UART collision bit 2019/11/09 17:15:48 (permalink)
    0
    Then I got lucky!  That didn't happen in this case.  It still doesn't have anything to do with the UART detection circuit.
    #7
    Jump to:
    © 2019 APG vNext Commercial Version 4.5