1 Reply Latest reply on Oct 18, 2019 11:11 AM by KyTr_1955226

    Using a One-Shot Timer as a UART message timeout?

    KyTr_1955226

      Hi everyone,

       

      I'm having an issue with using a One-Shot Timer as a serial message timeout.  I have a RS232 serial device I'm communicating with via the PSoC and I need to detect end of transmission and echo the transmission back to a host PC.  Unfortunately there is no delimiter character of any kind from the device that I can use to know when a transmission is done, so I'm stuck using a timeout.

       

      The device is 2400 Baud, so I have configured a 10mS One-Shot mode timer as my timeout.  I want to Reload/Restart the timer when a character is received, and when I hit the timer ISR, I know the transmission is done.

       

      According to the datasheet, calling Timer_Stop() should reload the period value into the timer when operating in One-Shot.  This does not appear to be happening as it should.

       

      I have a scope capture of the serial data alongside when the timer ISR is firing (Blue toggles when Timer ISR fires).  The cursors are placed where the timer in theory should be starting (10mS before the ISR fires):

      Here's the code for the relevant ISRs.  Note that file-scope globals (DV_CharIndex and DV_UART_MsgDone) are both declared as volatile, and the UART RX ISR has a higher priority than the Timer ISR:

       

      UART RX ISR:

      /*Receive ISR
       *  - Fires when character received at DV_UART
       *  - Reads any received characters into next buffer location(s)
       *  - Starts timer to determine end of message (see Message Timer ISR)
       */
      void DV_RX_ISR_Interrupt_InterruptCallback (void){
          uint8_t status = DV_UART_ReadRxStatus();
        
          if (((status & DV_UART_RX_STS_STOP_ERROR) > 0) ||
              ((status & DV_UART_RX_STS_OVERRUN) > 0) || 
              ((status & DV_UART_RX_STS_PAR_ERROR) > 0)){
              DV_UART_Err = true;
          }
          
          while ((status == DV_UART_RX_STS_FIFO_NOTEMPTY) && (!DV_UART_Err)){
              DV_MsgTimer_Stop();    //This should be stopping the timer and reloading the period value
              DV_UART_MsgIn[DV_CharIndex++] = DV_UART_ReadRxData();
              status = DV_UART_ReadRxStatus();
          }
          
          DV_MsgTimer_WriteCounter(DV_MsgTimer_INIT_PERIOD);    //This should also be reloading the period value
          DV_MsgTimer_Start();
          DV_RX_ISR_ClearPending();
          
      }
      

       

       

      Timer ISR:

      /*DV Message Timer ISR
       *  - When this timer elapses, message is complete.
       *  - Sets DV_MsgDone flag and disables DV_MsgTimer.
      */
      void DV_TMR_ISR_Interrupt_InterruptCallback (void){
          HB_LED_Write(!HB_LED_Read());
          DV_MsgTimer_ReadStatusRegister();
          DV_TMR_ISR_ClearPending();
          DV_CharIndex = 0;
          DV_UART_MsgDone = true;
          DV_MsgTimer_Stop();
      }
      

       

       

      So I'm a little confused as to why this isn't working properly.  The timer doesn't appear to be resetting on the Stop/WriteCounter calls  as evidenced by the timer ISR firing in the middle of a transmission.  I'm a little stumped as to why this isn't working the way I'm expecting.

       

      Anyone have any thoughts?  Thanks in advance!

       

      [EDIT] I should also note that I am not actually talking to the device in question, but simulating expected behavior through a test rig.  I am sending a command via DV_UART_TX (DV_UART_PutString()) and have a loopback cable connected that directs it right back into DV_UART_RX.  I don't think that should cause an issue, but it's worth mentioning.  The expected behavior is very similar to what I'm simulating.  I send a command to the device, it echoes back the command plus some extra data bytes.  Only real difference should be that it will take longer to get serial data back in production than when I'm using the loopback.