 |
 |
| View previous topic :: View next topic |
| Author |
Message |
AlastairM
Joined: 28 Apr 2008 Posts: 36
|
| dsPIC UART error recovery |
Posted: Wed Mar 04, 2026 3:41 am |
|
|
dsPIC33CH128MP202 dual core (this code is on the master)
compiler 5.123
sorry! code rather complex so here are the relevant bits snipped out:
| Code: |
#include <33CH128MP202.h>
#use delay(internal=20MHz)
#define MODBUS_SERIAL_RX_PIN PIN_B15
#define MODBUS_SERIAL_TX_PIN PIN_B14
#define MODBUS_SERIAL_BAUD 9600
#define MODBUS_SERIAL_STOP_BITS 1
#define MODBUS_PARITY "NONE"
#pin_select U1TX=MODBUS_SERIAL_TX_PIN
#pin_select U1RX=MODBUS_SERIAL_RX_PIN
#use rs232(baud=MODBUS_SERIAL_BAUD, UART1, bits=8, stop=MODBUS_SERIAL_STOP_BITS, parity=N, stream=MODBUS_SERIAL, errors) |
The incoming data is read in interrupt INT_RDA and works perfectly for hours of testing. Unless the power is cycled and occasionally the UART dies!
The Modbus serial port is connected to a WiFi module which at power turn on sends some debug info to the PIC which, I think, occasionally kills the UART (completely fixed by a _MCLR_ reset)
My workaround is to delay the WiFi module from sending serial data at turn on and minimise the data sent.
But my main query is why isn't the UART1 error state fixed by a getc() like it should be with ERRORS switch utilised in the #USE RS232?
Are there any other ways the UART1 can be temporarily killed? (there is a second UART for debug so I can see that the program is running as intended but the INT_RDA isn't triggered. (I can see incoming data on the 'scope)
What error bits / debugging would be best to test my hypothesis of why it's not working? - I've run out of ideas!
Thanks
Alastair |
|
 |
newguy
Joined: 24 Jun 2004 Posts: 1930
|
|
Posted: Wed Mar 04, 2026 5:23 pm |
|
|
It's been a while since I looked into the issue of UART error conditions and a great deal has been lost to the fog of time but I do remember that in the end I was grateful that CCS will handle these things for me. From what I recall clearing UART error conditions wasn't as straightforward as I thought it was but the processor's data sheet will help guide you.
Have you read the relevant UART status/control registers and examined/printed them when running normally and when the lockup occurs? I've downloaded the data sheet for the processor and there are a number of bits in various registers that seem to be asserted when various error conditions arise. If you know the specific errors, clearing them should be rather straightforward.
The most straightforward brute force approach would be to use the processor's PMD (peripheral module disable) to kill the UART's power entirely, then re-enable and reconfigure it. I'd consider this to be your last resort though; you should be able to monitor the UART's status registers and be able to remedy the problem without resorting to this extreme. Indeed, your observation that a /MCLR reset restores operation would point toward a register somehow getting loaded with an incorrect value under certain hard to duplicate conditions. |
|
 |
AlastairM
Joined: 28 Apr 2008 Posts: 36
|
|
Posted: Wed Mar 04, 2026 6:05 pm |
|
|
Hi, thanks for the reply.
I should probably just stop the external module from streaming data so soon after turn on but it's easier to clear the error at the dsPIC end for now...
When the fault occurs FERR and OERR are set in U1STA (23C).
OERR, I think, is the flag which means the UART has stalled.
as a quick fix I look for OERR to be set and then in the main loop read characters until it clears. Once cleared the interrupt fires again and everything works as expected
| Code: |
if(OERR)
{
fprintf(MASTER_RS232,"\r\nError!");
while(kbhit(MODBUS_SERIAL))
{
fgetc(MODBUS_SERIAL);
fprintf(MASTER_RS232,"\r\nClearing error!");
delay_ms(200);
}
}
|
It must be a race condition as the #USE RS232 command sets up the UART while characters are being received from the external WiFi module and kills it before the Rx interrupt is set up and able to read the characters. After this point the interrupt doesn't fire and fgetc() in the interrupt routine doesn't get called and so can't clear the fault.
The above code reads 7 times and then everything works again. I think the buffer is 4 deep so I'm not sure why it reads so many times (the WiFi module is idle at this point) |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|