ISRRX.OnData stops firing

Coding and general discussion relating to user created compiler modules

Moderators: David Barker, Jerry Messina

Post Reply
tcdev
Posts: 15
Joined: Thu Jan 15, 2015 12:31 am

ISRRX.OnData stops firing

Post by tcdev » Tue Jan 20, 2015 5:55 am

Hi gurus,

I've only just recently inherited a project to debug and am having problems getting the code - as delivered - to function correctly.

I've purchased the most recent Swordfish compiler as the client doesn't have access to it - the previous contractor owned the copy. I can only assume it's an older revision as the code didn't compile out-of-the-box on my machine, and I've been assured that it's the latest source. The errors pertained to equality comparisons of a Byte variable to character literals - which I've since fixed.

Anyway, to the issue at hand. The code uses the ISRRX module, and no other interrupts. It initialises the OnData callback and appears to function correctly for approximately 20 seconds on average, then stops firing. Seems to be no obvious pattern or packet type.

I've added code to flash a LED in the OnData subroutine and as expected, it flashes for the initial 20s or so, and then stops flashing, coinciding with the communications failure.

Can anyone suggest why I would get this behaviour? I haven't come across any code that enables/disables the interrupt elsewhere in the code, so I can't see why this would be happening suddenly. The hardware came pre-programmed with the old firmware (CP0=ON, so I can't re-read) and it didn't have this issue. I can only assume there's something different in the latest compiler and/or ISRRX module that older versions didn't have to worry about?

I'm an embedded software engineer but with a total of 1 day's experience programming PICs, let-alone Swordfish BASIC, I'm at a loss where to even start looking.

EDIT: I've just noticed that the code is calling USART.Write within the OnData callback. Is that kosher? FTR the code is awful! :cry:

EDIT2: I've just noticed that it doesn't appear to be consuming bytes. OnData simply references ISRRX.DataChar and doesn't call any read routines... could it be a buffer over-run that is preventing OnData being called again?

User avatar
Coccoliso
Posts: 152
Joined: Mon Feb 17, 2014 10:34 am

Re: ISRRX.OnData stops firing

Post by Coccoliso » Tue Jan 20, 2015 7:27 am

Hello Tcdev,
in the example USART\Interrupt_OnData.bas I think is what you used the routine you call a SUB .. try to turn it into EVENT.
I had a similar problem after the last update of the compiler and David suggested I change the SUB in EVENT.
Yes the OnData not perform any change of the registers, is called when you receive a new byte but in the example is used for demonstration purposes only for make changes to the received character.
Use the OnData to call in it something different?

tcdev
Posts: 15
Joined: Thu Jan 15, 2015 12:31 am

Re: ISRRX.OnData stops firing

Post by tcdev » Tue Jan 20, 2015 7:30 am

OK, found an issue, but can't explain it.

I noticed that the length of time that communications were working was related to ISRRX.RX_BUFFER_SIZE. Now I've confirmed that it is getting ISRRX.BufferOverrun when communications fails.

Herein lies the problem; my OnData subroutine has ISRRX.ProcessByte = false. Looking at the ISRRX module, this should in effect disable buffering and therefore prevent BufferOverrun from ever being set to true!?!

So either I'm doing something really dumb, don't understand Swordfish BASIC, or there's a bug?

ISRRX.ProcessByte is a public alias for FProcessByte. Are public aliases read/write? Could this be the source of the issue?

tcdev
Posts: 15
Joined: Thu Jan 15, 2015 12:31 am

Re: ISRRX.OnData stops firing

Post by tcdev » Tue Jan 20, 2015 7:39 am

@Coccoliso: you're a saviour! Changing to an event did indeed fix the issue! Thanks!

Now I'm absorbing the documentation on events and trying to understand how that would change referencing a Public alias in the calling ISR...

User avatar
David Barker
Swordfish Developer
Posts: 1194
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Re: ISRRX.OnData stops firing

Post by David Barker » Tue Jan 20, 2015 11:21 am

I would add that OnData() should only be used for just very simple processing. Maybe changing one char into another, or setting a flag if a particular character is seen. I would not be inclined to add lots of code in there unless I was prepared to investigate underlying register usage to ensure correct context saving.

When I'm writing projects and dealing with incoming RS232 data I always just buffer everything and process from with my main code block. This ensures that (a) no incoming data is missed (b) processing the buffer from within the main code block removes all possibility of fails due to incorrect context save.

Jerry Messina
Swordfish Developer
Posts: 1246
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: ISRRX.OnData stops firing

Post by Jerry Messina » Tue Jan 20, 2015 11:54 am

Ditto what David said.

A little background...

The hardware stack of the PIC18 is very limited. Swordfish uses a compile-time 'stack' and a technique called frame recycling to allocate ram. When a program is compiled, SF does a call-graph analysis to see which routines call which so that it knows whether a ram location can be reused or not. This all works very well and typically results in programs being able to use "more ram" than a completely static allocation method. The rub comes in when you have interrupts, which are asynchronous so they can basically happen at any time. If you call a sub/function from an ISR the ram that was allocated to that routine may already be in use, and SF has no way of knowing this.

SF handles this in two ways:
- save()/restore blocks to inform the compiler which routines you're calling in the ISR so that it knows to preserve that routines ram
- events

Events are basically indirect function calls (ie the event handle is a pointer to a function). Since an event pointer can't be tracked at compile time, events are allocated their own unique stack frame space. This lets them be called from an ISR without having to worry so much about the ram used by the event.

There are a number of caveats to this, so be sure to read the sections on interrupts, frame recycling, and events in the manual. Read them carefully. In the end, the limitations aren't much different than any other PIC18 compiler... you actually have a bit more flexibility.
I've just noticed that the code is calling USART.Write within the OnData callback. Is that kosher?
I suppose so, but it's not the best of arrangements. USART.Write() is a blocking function, and since it's being called from the OnData event, it's executing inside the usart rx ISR. Be sure to never write more than one byte or you'll start to get overrun errors. Once an overrun occurs the uart is blocked from receiving any more bytes until you reset it or call USART.ClearOverrun()
...events and trying to understand how that would change referencing a Public alias in the calling ISR...
That's probably not the real issue. It's more likely a ram allocation misstep due to the Event being declared a Sub

Post Reply