|
|
View previous topic :: View next topic |
Author |
Message |
peter273
Joined: 07 Mar 2008 Posts: 5
|
PCWH 4.042 versus PCWHD 4.120: I2C and MPLAB issues |
Posted: Tue Aug 30, 2011 10:00 am |
|
|
Migrating a number of 18F4685 projects from pcwh4.042 to pcwhd4.120 I early encountered some weird things between the two versions (two upto now).
1) environmental issues in MPLAB
================================
I historically use Microchip MPLab (now V8.73) or Visual Studio for development environment since I never really liked the CCS visual environment.
Creation of a working visual environment was always simple using the MPLab project wizard: adding just one or two files (project.c and project.h) and compiling once always automatically added all the include files into the project window.
After migration from PCWH4.042 to PCWHD4.120 I found the project file list in MPLab no longer automatically updating the files as included in the code, all files need to be added manually to the MPLab project.
This lack of updating has the downside that if one or more files is not listed in the project window not all symbols are listed, searching not always returns all searched for, etc...
This lack-of-updating is true for loaded "old" V4.042 projects as well as newly created V4.120 projects created with the MPLab project wizard.
I tried installing PCW and MPLab in several sequences to solve this, even tried it on xp/32, vista/32 and win7/64 but to no avail: PCWHD4.120 never automatically adds files to the MPLAB project files list as PCWH4.042 does.
In some cases, right-clicking the project and selecting "reload" even gets me several (if not most) files listed twice in the project window (but it never adds any "forgotten" included files) Anybody any idea what's going on here???
Is there any parameter I have forgotten to set? Or a regkey to be updated manually?
(note: I have administrator rights on all machines mentioned)
And yes, I did use the setup_mplab_plugin.exe V2.0.0.13 as available from ccsinfo download site.
2) compiler issues:
===================
I'm operating a number of physical real-time interactive modules all equipped with 18F4685 for now, in time I will be migrating them to dsPIC30.
First step is to migrate from PCWH4.042 to PCWHD4.120 and (hopefully) get it all operational, then migrate from 18F4685 to dsPIC30 and (again
hopefully) get it all operational.
All physical modules use I2C for (quasi) real time interaction, and (after alot of blood, sweat and tears) all works fine using PCWH4.042.
However: when migrating the code to PCWHD4.120 communication through I2C fails completely.
I will not post too much code for now, would lead me too far since several SW-modules are involved so I'll stick to what I found.
In compiler V4.120 there's an option NO_STRETCH in #use I2C, this option is NOT set in V4.120 to allow for clock stretching (option wasn't available in V4.042).
In essence, my i2c slave interrupt routine follows the sequence (pseudo code)
Code: |
- switch off the i2c interrupt
- clear the interrupt flag
- get i2c isr state, check if 0x00, <0x80, 0x80 or >0x80
- act upon i2c isr state:
- receive: organize received byte in RX-header-buffer or RX-databuffer at calculated location
if received RX-databytes match size as indicated by the header, set flag for normal program to handle the received data
- respond: create new TX-header for TX-datablock and send first/next calculated byte of header/data
if all are sent clear the TXbuffer-full flag for re-use of TX-datablock by the normal program
- clear the interrupt flag
- switch on the i2c interrupt again
- release i2c clock so master can send next byte
|
(header buffers contain checksum, number of datablock-bytes, type of content for datablock, etc...)
In upgrading compiler I'd expect everything to be still working, and no devious register-fiddling in the compiled code without me knowing.
Compiling with PCWH4.042 I see the function i2c_read() compiling into
Code: |
.................... dummy = i2c_read(I2C_1);
02376: BTFSS FC7.0 //test buffer full status bit
02378: BRA 2376 //step back until byte received
0237A: MOVFF FC9,B25 //get the received byte, store it in dummy
|
BUT: Compiling with PCWH4.120 I see the function i2c_read() compiling into alot more and even unwanted code
Code: |
.................... dummy = i2c_read(I2C_1);
00554: BCF FC6.6 //clear receive overflow bit <==== why here?????? Should be done in an error intercept!
00556: BTFSS F9E.3 //check MSSP interrupt flag <==== I normally clear it when entering the interrupt, so it WILL hang here
00558: BRA 0556 //step back until interrupt flag ; On top: why check an interrupt flag when having a buffer full flag?????
0055A: MOVF FC9,W //get received byte
0055C: BSF FC6.4 //release i2c clock <==== compiler inserted, and I don't like the messing with it without me knowing it
0055E: MOVWF x05 //store received byte in dummy
|
As far as I see it, V4.042 i2c_read() compiles (almost) as it should:
getting the byte and that's it.
Nevertheless I don't need the compiler-inserted wait-until-received since I earlier test by using i2c_poll() to avoid a lockup so there's always some "wasted code" inserted here by the compiler.
As far as I see it, V4.120 compiles in such a way that working code is messed up: it unexpectedly checks an interrupt flag without being instructed to by high end code and it ignores the buffer-full flag which in fact should be used if wanting to wait.
The only fix I found to have **identical** compilation like V4.042 is replacing the line i2c_read(I2C_1) by
Code: |
.................... while (!(S_SSPSTAT.BF)); //only inserted to get identical code as V4.042
00554: BTFSS FC7.0 //test buffer full status bit
00556: BRA 0554 //step back until byte received
.................... dummy = S_SSPBUF.SSPBUF;
00558: MOVFF FC9,B05 //store received byte in dummy
|
This results in working code again (at least: for me it does), all systems running again.
Downside: I do not have platform independent code any more, since using built-in functions messes up things. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Aug 30, 2011 1:04 pm |
|
|
Quote: |
After migration from PCWH4.042 to PCWHD4.120 I found the project file
list in MPLab no longer automatically updating the files as included in the
code, all files need to be added manually to the MPLab project.
|
I found that too, and it's annoying. The compiler doesn't automatically
add the PIC's header file (ie., 18F4685.h) and other #include files to the
MPLAB project window when you compile the project. I don't know
whether it's a mistake by CCS or a deliberate new feature. But somebody
ought to question them about it.
Quote: |
- switch off the i2c interrupt
- clear the interrupt flag
- get i2c isr state, check if 0x00, <0x80, 0x80 or >0x80
- act upon i2c isr state:
- receive: organize received byte in RX-header-buffer or RX-databuffer at calculated location
if received RX-databytes match size as indicated by the header, set flag for normal program to handle the received data
- respond: create new TX-header for TX-datablock and send first/next calculated byte of header/data
if all are sent clear the TXbuffer-full flag for re-use of TX-datablock by the normal program
- clear the interrupt flag
- switch on the i2c interrupt again
- release i2c clock so master can send next byte
|
There are no nested interrupts. You're not going to be interrupted inside
the #int_ssp isr by a 2nd ssp interrupt while processing the first one.
Regarding your isr .LST file problems, can you post a very short little
test program so I can try to duplicate it ? Here's my attempt below,
but it's not doing what you're doing. I need to see your code.
(Please don't put in anything that's not essential to the compilation
or to show the .LST file problems. Don't put in excess unused #defines,
#includes, variables, etc. Only what's needed to make it compile).
Code: | #include <18F4685.h>
#fuses XT,NOWDT,BROWNOUT,PUT,NOPBADEN
#use delay(clock=4M)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3, FORCE_HW, stream=I2C_1)
#int_ssp
void ssp_isr(void)
{
int8 dummy;
dummy = i2c_read(I2C_1);
}
//==========================
void main()
{
while(1);
} |
|
|
|
peter273
Joined: 07 Mar 2008 Posts: 5
|
|
Posted: Tue Aug 30, 2011 3:41 pm |
|
|
PCM programmer wrote: |
There are no nested interrupts. You're not going to be interrupted inside
the #int_ssp isr by a 2nd interrupt while processing the first one.
|
Coming from and migrating between a variety of processors/controllers (PIC, 80C5xx, 68000, several intels including x86,...) during 25+ years now I've become used to always expecting the unexpected and spending lots of time in finding out why the hell it doesn't work... again .
That's one of the reasons to also and always expect nested interrupts I guess, just in case of migration to a chip which does support it.
Also and FYI: 18F4685 does support interrupts interrupting interrupts by using the keyword HIGH with the PCH.
PCM programmer wrote: |
Regarding your isr .LST file problems, can you post a very short little
test program so I can try to duplicate it ? Here's my attempt below,
but it's not doing what you're doing.
|
What you didn't insert is the interrupt-flag manipulation on my entering the interrupt (see pseudo-code in my first post).
When looking in my first post at the V4.120 compiled code, you can see i2c_read() relies upon the interrupt flag to find out if anything was received instead of relying upon the buffer-full flag like the V4.042 code does. Both codes then continue if the flag (one or the other depending upon compiler version) is set.
Whatever I do with the interrupt flag upon entering the interrupt itself SHOULDN'T be of any influence in the assembler code for i2c_read(), in fact i2c_read() may ONLY (and at most) look at the buffer-full flag and has to totally ignore the interrupt flag.
To put it another way: I entered the interrupt BECAUSE the interrupt flag got set in the first place, so why check and wait until the interrupt flag gets set before reading the received byte in the assembler for i2c_read().
This code should be able to reproduce the error since as far as I see it all comes down to the assembler code unexpectedly checking the (in my case cleared) interrupt flag in V4.120.
I do not calculate or store the "dummy" variable in any buffer here, so it's just the bare essentials with a "show onscreen" in main.
Also keep in mind I do not respond-to-master in this code if master wants to read a byte, so master will hang if reading from slave in this code.
Code: |
#include <18F4685.h>
#use delay(clock=40000000)
#use rs232(baud=115200, xmit=PIN_C6, RCV=PIN_C7, PARITY=N, BITS=8, STREAM=RS232_1)
#use I2C(SLAVE, sda=PIN_C4,scl=PIN_C3, address=0x10, FAST, FORCE_HW, STREAM=I2C_1)
int8 dummy;
#int_ssp
void ssp_isr(void)
{
//disable interrupt
disable_interrupts(INT_SSP);
//clear interrupt flag
clear_interrupt(INT_SSP);
//poll before using i2c_read, V4.042 compiles to wait by default for this flag and hangs if somehow it isn't set
if(i2c_poll(I2C_1))
{
//the actual receive, it will hang here in V4.120 if
//the interrupt flag was cleared like I did above
dummy = i2c_read(I2C_1);
}
//clear interrupt flag
clear_interrupt(INT_SSP);
//enable interrupt again
enable_interrupts(INT_SSP);
S_SSPCON1.CKP = 1; //release i2c clock
}
//==========================
void main()
{
dummy = 0;
//clear and enable i2c interrupt
clear_interrupt(INT_SSP);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(TRUE)
{
if(dummy)
{
//only printf char if printable
if(isprint(dummy))
fprintf(RS232_1, "%c", dummy);
//always printf hex representation
fprintf(RS232_1, "\t0x%2X\r\n", dummy);
dummy = 0;
}
}
}
|
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed Aug 31, 2011 3:04 am |
|
|
Quote: | Also and FYI: 18F4685 does support interrupts interrupting interrupts by using the keyword HIGH with the PCH. |
But the feature isn't used in your code. So all the disable_interrupt(), clear_interrupt() stuff in your code seems pretty useless, at least. I would refer to the basic interrupt action for clarity, as suggested by PCM programmer. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 31, 2011 1:33 pm |
|
|
Quote: |
00554: BCF FC6.6 //clear receive overflow bit <==== why here?????? Should be done in an error intercept!
|
I found the likely answer to this question by searching with Google for erratas:
Quote: | site:microchip.com -forums type:pdf errata i2c slave BF SSPIF |
In the 18F4620 errata below, Microchip says to clear the SSPOV flag as
a work-around. This errata is also in other PICs, so I think it's likely that
CCS just added it to all 18F-series i2c slave code.
http://ww1.microchip.com/downloads/en/DeviceDoc/80200d.pdf
Quote: | 28. Module: MSSP
In an I2C system with multiple slave nodes, an
unaddressed slave may respond to bus activity
when data on the bus matches its address. The
first occurrence will set the BF bit. The second
occurrence will set the BF and the SSPOV bits. In
both situations, the SSPIF bit is not set and an
interrupt will not occur. The device will vector to the
Interrupt Service Routine only if the interrupt is
enabled and an address match occurs.
Work around
The I2C slave must clear the SSPOV bit after each
I2C event to maintain normal operation. |
|
|
|
|
|
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
|