View previous topic :: View next topic |
Author |
Message |
MgSc
Joined: 16 Aug 2013 Posts: 4
|
problem in migrating to V5 [SOLVED] |
Posted: Fri Aug 16, 2013 7:25 am |
|
|
Hi everyone,
I'm having some problem to migrating to V5 from CCS...
I have a code that usually worked with V4... So I updating to V5 and now it isn't working the usart in #int_rda as it used to.
With V4 I used to receive a string of data at #int_rda, but with V5 (just upgrading the compiler) I'm receiving just the first byte.
Could someone tell me if got something like that and if solved the problem?
Last: V4.107
New: V5.011
Pic: 24FJ256GA108
Thank you!
Last edited by MgSc on Mon Aug 19, 2013 12:32 pm; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Fri Aug 16, 2013 7:34 am |
|
|
Start by writing your RDA handler right!.....
INT_RDA, means that _one_ character is ready to be received. No more.
It's the same in V4. However I'd suspect the routine you are using to get the string is behaving differently. Possibly defaulting to timing out for example...
Best Wishes |
|
|
MgSc
Joined: 16 Aug 2013 Posts: 4
|
|
Posted: Fri Aug 16, 2013 7:55 am |
|
|
I don't think it's the problem...
I did a modification just to get a test...
Code: |
char data_received;
#int_da
void fn_int_rda(){
data_received = getc();
output_toggle(led);
}
|
It works like this:
At really I received 10 bytes. But it entry in int_rda just once by time that I receive this string of 10 bytes.
I'm debugging with ICD3 and putting a break point I notice that the byte (the first one in the string) is correct, but i don't receive any other. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Fri Aug 16, 2013 8:06 am |
|
|
As Mr. T said , INT_RDA ONLY gets ONE character for the interrupt.
If your data is 10 bytes long, the ISR will be accessed 10 times.
Your 'main' program has to process the data( 'data_received' in your code).
I suggest you look at the 'ex_sisr.c' example program that CCS supplies in the examples folder. It shows how to create an Interrupt handler(ISR) that puts the incoming serial data into a 'buffer'.
Your 'main' program can then access the 'buffer' data and decide what to do with it.
hth
jay |
|
|
MgSc
Joined: 16 Aug 2013 Posts: 4
|
|
Posted: Fri Aug 16, 2013 8:19 am |
|
|
Hi temtronic,
that is the point...
the ISR isn't being accessed 10 times... Just one!
If it was being accessed 10 times I would be very happy!
In the V4 it works fine. |
|
|
drolleman
Joined: 03 Feb 2011 Posts: 116
|
|
Posted: Sun Aug 18, 2013 11:12 pm |
|
|
what I do is check at the end of the isr are there more char's? for instance if another interrupt caused a delay and an extra char is put in the buffer, the isr will never fire again. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Mon Aug 19, 2013 12:38 am |
|
|
Drolleman, the interrupt will fire again.
The RDA interrupt will continuously fire, if there is data in the buffer. Since (typically) a 'character time' is tens of thousand of instructions, the overhead of it firing a second time, doesn't normally matter.
However if receiving data at a high speed compared to the clock rate (115200bps, with say only an 8Mhz clock), then it is well worth checking if a second character is present.
The only standard thing that would make the ISR fire 'once', and not fire again for the later characters, is not having 'ERRORS' in the RS232 declaration, and disabling the RDA interrupt somewhere, or having re-entrant code, that results in the interrupt being disabled.
If you 'put a break point' in the interrupt with the ICD, then the interrupt _will_ only be accessed once. By the time you have seen that the ICD has stopped, the other nine characters will have already been missed, and unless there is 'ERRORS' in the RS232 declaration, the UART will be hung.
So. First thing, make sure you have 'ERRORS' in your #use RS232.
Then use this as a 'debug' ISR:
Code: |
char data_received[16];
int8 rx_ctr=0;
#int_rda
void fn_int_rda(){
data_received[rx_ctr++] = getc();
if (rx_ctr==16])
rx_ctr=0;
if (rx_ctr==10)
output_toggle(led);
}
|
Debug on it toggling the LED, then look at the contents of the array.
The second thing to try, is compiling with the option "#device CCS4" at the top of the source, near the fuses. There is one major change with CCS5, is saves a smaller number of registers for the interrupt handler. This only 'matters' if the code is doing something location 'specific' in the interrupt handler. This option restores the old behaviour.
Best Wishes |
|
|
MgSc
Joined: 16 Aug 2013 Posts: 4
|
|
Posted: Mon Aug 19, 2013 12:32 pm |
|
|
Hi all,
sorry for the delay in reply!!!
I found the problem...
The problem is that the CCS V5 is really enabling the NSTDIS(INTCON,15),
so the interrupt priority wasn't working...
I was configuring the IPCx and clearing the NSTDIS bit... but using "ENABLE_INTERRUPTS(INTR_GLOBAL);" at the end, putting NSTDIS to 1 again.
in the code compiled with CCS V4 "ENABLE_INTERRUPTS(INTR_GLOBAL);" it wasn't putting NSTDIS to 1 again. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Tue Aug 20, 2013 2:10 am |
|
|
You need to add
#DEVICE NESTED_INTERRUPTS=TRUE
or just
#DEVICE NESTED_INTERRUPTS
Which will then tell the compiler that you want nested interrupts. This was a documented change about a dozen versions ago in V4....
The only reason you hadn't met it was going straight from 4.107.
Quote from the 'readme.txt' for 4.118:
"The INTR_NESTING option for enable/disable interrupts has been
removed. The new way to enable nesting is to use the following
since too many problems occur when changing the nesting state
at run time:
#device NESTED_INTERRUPTS"
Best Wishes |
|
|
|