|
|
View previous topic :: View next topic |
Author |
Message |
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
Using I2C IRQs from bootloader and application |
Posted: Thu Nov 07, 2019 11:29 am |
|
|
I created a simple proof-of-concept PIC24 bootloader the other day, and now I have started implementing an I2C firmware update capability to it. I ran into a snag, and after reading through some old threads here on similar issues, I think I know what to ask.
Originally, I thought I could use I2C FORCE_SW as a SLAVE (bootloader), but I see that is not supported. I will have to use I2C interrupts.
However, if the bootloader has the I2C interrupt in its main vector table, it won't be able to get to the application routine (which will also use I2C). From ex_pcd_boatloader.c, interrupts are redirected like this:
Code: | #int_default
void isr(void)
{
jump_to_isr(LOADER_END+5);
} |
When I looked at Microchips EZBL bootloader, it looked like they took all the IRQs and then passed them on (using a special API applications use to access timers and such).
Is that the only option? _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Thu Nov 07, 2019 11:35 am |
|
|
For a bootloader you should be able to poll the interrupt flags. This avoids messing with the main application interrupt vectors. |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Thu Nov 07, 2019 1:42 pm |
|
|
gaugeguy wrote: | For a bootloader you should be able to poll the interrupt flags. This avoids messing with the main application interrupt vectors. |
I adapted this code which looks like it polls for a Start, then receives until it gets a Stop. The registers (for 24FJ256GA106 in this case, but the code is cross platform):
SLAVE:
Code: | // IC2C3STAT - sto(P) and (S)tart bits for status.
#word I2C3STAT = getenv("SFR:I2C3STAT")
#bit P = I2C3STAT.4 // bit 4 - stop
#bit S = I2C3STAT.3 // bit 3 - start
#bit RBF = I2C3STAT.1 // bit 1 - RBF receive buffer status bit |
...and the code that waits for incoming data:
Code: | unsigned int bytesRead;
while (S==0); // Wait for start.
bytesRead = 0;
while (1) // Read incoming bytes.
{
if (RBF == 1) // Read Buffer Full?
{
buffer[bytesRead++] = i2c_read(SYSTEM_BUS);
if (bytesRead > size)
{
break;
}
}
if (P == 1) // Stop?
{
break;
}
} |
I've blasted a few hundred messages of different byte sizes to it, and it's worked fine.
The production code we use at work does all of this inside an ISR, so the next thing I have to add is the way to turn around and send a response back to the Master. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Fri Nov 08, 2019 8:43 am |
|
|
I bailed on this, since it seems the original author was not using it on a shared bus. The way it checks the receive buffer register makes it respond to all traffic on the line. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Fri Nov 08, 2019 9:48 am |
|
|
gaugeguy wrote: | For a bootloader you should be able to poll the interrupt flags. This avoids messing with the main application interrupt vectors. |
I started looking at this. On my PIC24 board, I am wanting to use I2C3. I find:
Quote: | IFS5 - Interrupt Flag Status Register 5
SI2CSIF - Slave I2C3 Event Interrupt Flag Status Bit |
I can see it toggle to 1 when data comes in, via:
Code: | #word IFS5 = getenv("SFR:IFS5")
#bit SI2C3IF = IFS5.4 // bit 4 - slave I2C3 IRQ status |
The only others I see are:
IEC5 - Interrupt Enable Control Register 5 (SI2C3IE)
and
IPC21 - Interrupt Priority Control Register 21 (SI2C3IP)
Where does the rest of the state come from in i2c_isr_state()? I think the high bit there may be the RW status bit (in or out data?), then the other 7-bits are the incoming byte count... Is that being done by the library?
Thanks! _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Fri Nov 08, 2019 10:19 am |
|
|
Don't worry. Yes it is done in the library, it is reset when an
address byte is received. You can just use I2C_ISR_state as normal
in your polled code. It doesn't mind at all that your service routine is not
actually in an 'interrupt' as such.
Look at my reply here (why have you got two threads running for the
same question?):
<http://www.ccsinfo.com/forum/viewtopic.php?t=58338> |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Fri Nov 08, 2019 11:22 am |
|
|
Ttelmah wrote: | Look at my reply here (why have you got two threads running for the
same question?): |
This thread was for the question of how to have bootloader Vector table end up at the Application's vector table.
jump_to_isr ()
As soon as I have it tested, I'll mark this one as solved. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
|
|
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
|