PIC MCU Programming Page


November 16 2004
Much work is being done on my PIC Projects. Check the latest in the main news section.

April 27 2004
After struggling with Salvo, RTL8019AS, PIC18F6680, Hitech PICC18 and a new board, for the last month, I can tell you that I need a break.

However, (as you all know) there is no rest for the weary. So, Here is the detailed news. First of all, I tried reading the NIC registers from the interrupt routine. This turned out to be a major problem. So this is a no-no:


//
// High Priority vector
//
#pragma interrupt_level 0
void interrupt HighISR(void)
{
	BYTE s;
	//
	// The NIC gets the highest priority.
	// This could get to be a VERY busy handler.
	// We MUST keep latency to a minimum.
	if( (INT0IE) && (INT0IF) ) {
		s=NICGetP(ISR);                                     // We need to save the ISR value
		NICPutP(ISR, s);                                    // Whatever the reason was, we reset the interrupt
		// Now, reset the PIC Interrupt flag.
		// The earlyest we do this, the better.
		INT0IF=0;
		OSSignalMsgQ(MSG_GOT_PAK_MAC, (OStypeMsgP) 1);
	}
}
		

This was a nightmare. I was getting consistent bad data from the NIC and everything was messed up. I tried to fix it in many different ways but nothing worked. As per Andrew Kalman's suggestion (the man who wrote Salvo), I tried this:


//
// High Priority vector
//
#pragma interrupt_level 1
void interrupt HighISR(void)
{
	//
	// The NIC gets the highest priority.
	// This could get to be a VERY busy handler.
	// We MUST keep latency to a minimum.
	if( (INT0IE) && (INT0IF) ) {
		highISRactivity=TRUE;
		// Now, reset the PIC Interrupt flag.
		// The earlyest we do this, the better.
		INT0IF=0;
	}
}
		

When, the main code takes over it does:


113     //
114     // Start the multitasking loop
115     //
116     for(;;) {
117         if( highISRactivity || RB0 ) {                  // RB0 High indicates a NIC pending interrupt
118             if( highISRactivity ) {
119                 GIEH=0;                                 // Disable interrupts
120                     highISRactivity=FALSE;              // Reset FLAG
121                 GIEH=1;                                 // Enable interrupts
122             }
123             s=NICGet(ISR);                          // We need to save the ISR value
124             NICPut(ISR, s);                         // Whatever the reason was, we reset the interrupt
125             if( s & 0x1f ) {                        // RDC, OVW, TXE, RXE, PTX, PRX
126                 //
127                 // It is important that we check for errors first. The last thing we want
128                 // is to send a bad packet through the state machine
129                 if( s & 0x1c ) {
130                     MACPacketRXBuf[MACPacketIX]=s;                      // Save the ISR value to the MAC_ISR qu
131                     // Let's send the error to the appropriate routine
132                     OSProtect();
133                         OSSignalMsgQ(MSG_GOT_MACERR, (OStypeMsgP) &MACPacketRXBuf[MACPacketIX]);
134                     OSUnprotect();
135                     if( ++MACPacketIX > MAX_PRX_BUFZ ) {
136                         MACPacketIX=0;
137                     }
138                 }
139                 else {
140                     if( (s & 0x02) ) {                              // bit 2 is packet transmited with no error
141                         ISR_TX_Done=1;
142                     }
143                     if( (s & 0x01) ) {                              // bit 1 is packet received with no errors
144                         LED2_blink;
145                         OSProtect();                                            // Time Start
146                             OSSignalMsgQ(MSG_GOT_PAK_MAC, (OStypeMsgP) 1);
147                         OSUnprotect();                                          // Time Stop 15us
148                     }
149                 }
150             }
151         }
152         OSSched();
153     }
		

This is what it's all about. One month of hardcore programming, debugging and no sleep. Now, I am planning to send Andrew a thank you note, since he gave me a heads up on doing the NIC I/O in the main loop.

One very useful piece of equipment is a Time Interval Analyzer. I use it for timing code segments. I have an HP5370A and a HP5370B and they are both great for this sort of thing.

In order for this to work, I use I/O pins RA5 and RA6. To time a piece of code do:

RA6=0;RA5=0; RA5=1; RA5=0;
	mycode;
RA6=1; RA6=0;
		
I put the start channel on RA5 and the stop channel on RA6. The TI Analyzer will read out the time interval. This is great for checking if your code is doing what it's supposed to do. It is also very simple since you don't have to count cycles. Well worth the price!

March 2004 News