cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 5, 3 & 1

KyTr_1955226
Valued Contributor

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):

pastedImage_6.png

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();

}

pastedImage_4.png

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.

0 Likes
1 Solution
KyTr_1955226
Valued Contributor

UPDATE:

Switching the enabling/disabling of the timer to hardware seems to work as I intend:

pastedImage_0.png

Can't really figure why this is working and my software solution isn't, but I actually might prefer doing it this way.

View solution in original post

0 Likes
1 Reply