3

The problem

  • An external source sends these four bytes 0x2A, 0x42, 0x78, 0x25
  • The PIC32 UART Does not generate an int
  • The external source sends one more byte
  • The PIC32 UART then generates an int
  • In that int, Only the 0x25 byte from the previous transmission appears
  • i.e., the first three disappear
  • Once in awhile (Maybe 5% of the time) the UART does produce all 4 bytes properly

[Friday Evening Debug Results]

We wrote another echo routine; it just reads what it gets and writes it back out.

We built it in release mode (on advice of another here)

I wrote a routine to send the same number out 25 times, and see what I get back.

After that, I inc the value and send it out 25 times, and loop.

Results are appended at the end of this message.

I'm not getting the first null byte back. Based on various factors, I won't worry about that at this moment.

The next five rounds, I'm getting everything back perfectly

I'll try to include all relevant source code, hope it isn't a wall of text. If more code is needed to understand this, please ask.

This is the init code for the UART in question. I can include the

  //*****************************************************************//
  void initUART1(void)   // UART1 for MCU1/2 communication
  {
   U1MODE=0;                     //// Mode Register, Manual DS61168D page 180
   U1MODEbits.FRZ=0;
   U1MODEbits.SIDL=0;
   U1MODEbits.IREN=0;
   U1MODEbits.RTSMD=0;

   U1MODEbits.UEN=0b00;           //// Just TX/RX, No CTS/RTS

   U1MODEbits.WAKE=1;
   U1MODEbits.LPBACK=0;
   U1MODEbits.ABAUD=0;
   U1MODEbits.RXINV=0;
   U1MODEbits.BRGH=1;
   U1MODEbits.PDSEL=0b00;
   U1MODEbits.STSEL=0;

   U1STA=0;
   U1STAbits.ADM_EN=0;
   U1STAbits.UTXINV=0;
   U1STAbits.URXEN=1;
   U1STAbits.UTXBRK=0;
   U1STAbits.UTXEN=1;
   U1STAbits.ADDEN=0;
   U1STAbits.OERR=0;     
                                 //// Status register, Manual DS61168D page 183

   //U1BRG=21;                    ////  21 for 921600 (80 MIPS)
     U1BRG=172;                   //// 172 for 115200 (80 MIPS)

   IFS0bits.U1RXIF=0;
   IPC6bits.U1IP=5;
   IPC6bits.U1IS=3;
   IEC0bits.U1RXIE=1;

   U1MODEbits.ON=1;
  }


  //*****************************************************************//

This is the interrupt service routine that handles this specific UART

  //*********************************************************//
  void __ISR(_UART1_VECTOR, ipl5) IntUart1Handler(void)   //MCU communication port
  {     
    if(INTGetFlag(INT_SOURCE_UART_RX(UART1)))  //if it's a rx interrupt
    {
       U1RxBuf=UARTGetDataByte(UART1);

    switch (CmdRecording)
    {
     case 0:
           if(U1RxBuf=='*')
           {
            CmdRecording=1;  //set the cmd recording flag
            Command_U1[0]=U1RxBuf;
            TimeOut=1;  //time out=1 means the timeout for MCU1 command receiver is enabled
            initT3(0x0100);  //time out=0 means the timeout for MCU1 command receiver is enabled
           }
           else
         {
          putcharUART1('$');
          putcharUART1('e');
          putcharUART1('2');
          putcharUART1('%');
         }
           break;
     case 1:
           CmdRecording=2;  //set the cmd recording flag
           Command_U1[1]=U1RxBuf;
           break;
     case 2:
           CmdRecording=3;  //set the cmd recording flag
           Command_U1[2]=U1RxBuf;
           break;
     case 3:
           CmdRecording=0;  //reset the cmd recording flag
           Command_U1[3]=U1RxBuf;
           if(U1RxBuf=='%') //if this is the last command byte
           {
                if((Command_U1[1]=='O'))
            {
               CMD_Err=0;      //clear error
             CMD_OK=1;      //send cmd OK;
            }
              else if((Command_U1[1]=='e'))
            {
               CMD_OK=0;      //clear OK
             CMD_Err=1;     //send cmd Err;
            }
            else
            Command_flag=1;
           }
           else
           {
            Command_flag=0;
           }

           disableT3(0);  //the command receiving is done, disable the time out #0 (command receving time out)
           TimeOut=0;  //the command receiving is done, disable the time out

           break;
     default:
           break;
    }
     INTClearFlag(INT_SOURCE_UART_RX(UART1));
    }

    if ( INTGetFlag(INT_SOURCE_UART_TX(UART1)) )  //if it's a tx interrupt
    {
        INTClearFlag(INT_SOURCE_UART_TX(UART1));
    }
  }

  //***********************************************//

This is data that I saw when running the bytes through the "echo" system; i.e., the routine which reads one, writes one.

The PIC-32 is running at 80 MHz, and the UART is doing 115200 bps, so I'm not worried about the speed.

  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
  01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 
  02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 
  03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 
  04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 
  05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05
User.1
  • 2,562
  • 3
  • 33
  • 40
  • 1
    'Only the last byte appears' - where? You have this Command_U1 array - what's in the four bytes? – Martin James Mar 07 '13 at 17:57
  • Your ISR is primarily concerned with RX, for TX it merely clears the interrupt flag - I would suggest that this is not at all "all relevant source code" – Clifford Mar 07 '13 at 18:18
  • Command-U1 holds `0x00, 0x00, 0x00, 0x00` – User.1 Mar 07 '13 at 18:20
  • @Clifford, This is the PIC32 Interrupt routine that receives the bytes. This is the problem. When I send (from another source) bytes to this UART, I don't see the first 3. – User.1 Mar 07 '13 at 18:22
  • Just discovered: no int after sending 4 bytes. Am trying one at the time now. – User.1 Mar 07 '13 at 18:25
  • 5th byte generates int, providing 4th byte at the RXreg – User.1 Mar 07 '13 at 18:45
  • @User.1: Then you need to clarify the question; you talk about "sending the bytes". You should perhaps be clear that the data does not *appear at the receiver*; I reasonably assumed that you meant they did not appear at the output. – Clifford Mar 07 '13 at 18:46

1 Answers1

5

It looks like the UART probably has a 4 byte FIFO and does not generate an interrupt until the FIFO is full. I am not familiar with the part, but often you can program the UART to generate an interrupt at a specific FIFO level or after an n-character time-out, so that data in a non-full FIFO can be read. Further, if this is the case, your ISR should loop until the FIFO is emptied, rather than simply reading a single character.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • The Init code (supposedly) sets up the UART to generate an int on every byte. I sent him a fifth byte (sorry the editing crosses the internet cloud) and I got the fourth one. I am continuing to try single byte transmissions. – User.1 Mar 07 '13 at 18:57
  • You think? I just looked at the data sheet and you need to program `U1STAbits.URXISEL = 0` for that. I don't see that in your code. – Clifford Mar 07 '13 at 19:03
  • if you are right and I am wrong, THANKS !!! Let me examine. U1STA is holding `0x00001510` that appears to set URXISEL = 0, i.e., from Manual DS61168D-page 183, they say *00 = Interrupt flag bit is asserted while receive buffer is not empty (i.e., has at least 1 data character)* if I have my bits correct. Also, the init section has ` U1STA=0;` at the start which should clear everything. But keep the ideas rolling in. I am continuing my single byte experiments. – User.1 Mar 07 '13 at 19:08
  • I think zero is in fact the reset state, but if other code has run - a boot loader perhaps, it may have changed this state. – Clifford Mar 07 '13 at 19:10
  • Examples I can find use Microchips PIC32 library `UARTSetFifoMode()` call to set the FIFO mode, and other library functions for UART initialisation. It may be wise to use that library - it may do something that you are omitting - though I cannot see what that might be at present. – Clifford Mar 07 '13 at 19:49
  • I believe that the init code contains both ` U1MODE=0;` and `U1STA=0;` which should set everything to zero – User.1 Mar 08 '13 at 21:06