IFI_Initialization

Inside the EDU Default Code, there is a call from main.c to a function called IFI_Initialization. I am unable to find the code for IFI_Initialization in any .c file, and I can’t find its declaration in any header file. Is there anyplace where it might be hidden, that I haven’t checked? I want to see how that chunk of code operates, especially the interfacing between the two microprocessors.

:]

The compiled code is hidden in ifi_library.lib. The linker includes the object code in the flash image and then inserts its address into the code that calls it.

-Kevin

Is it possible to extract code from the IFI Library file? I was going to try to find some tool which reversed “ar”, to get the .o files from the library, but I haven’t gotten around to looking for such a tool, and I don’t know where I might find one. The reason I want to read the code in the library is because I want to understand how the GetData and PutData routines work.

:]

*Originally posted by Venkatesh *
The reason I want to read the code in the library is because I want to understand how the GetData and PutData routines work.

You can disassemble their library, however what you’ll get will be assembly only, with no comments, no variable names, etc. That’d be pretty hard to read and make sense of, even if you are good with PIC assembly.

How would I disassemble the library file?

(I am asking for the actual procedure, not a general overview. I am new to C, and so I have lots of questions, and I don’t understand too much here.)

*Originally posted by Venkatesh *
How would I disassemble the library file?

You need a disassembler for that. Some quick googling turned up one for the PIC 18 series: http://www.ac.ugal.ro/staff/ckiku/software/picdisasm.htm

Okay, here is what our team decided about ifi_initialization does, and please anyone correct me if anything appears incorrect, because we were really just guessing.
We were under the impression that C will always start running at main(), though according to the comments, main() is called in ifi_startup.c . What we figured happened was that it DID start with main.c, when to ifi_initialization, which through it’s course undefined UNCHANGABLE_DEFINITION_WHATEVER or whatever it was called, then called ifi_startup . ifi_startup did it’s thing, and called main() again, which now skips ifi_init because #ifdef UNCHANGALBLE_BLAH_BLAH was false, and it then goes on with it’s business.

Is this correct?

We also figured that the only reason IFI would give us a preassembled library is that it does things internally between the processors in the EDU RC, which are things we could really not change, so therefore you really do not need to know what ifi_initialization does. It would be nice, however, to know what exact flow the program follows, rather than guessing like we did.

The first code to run at bootup in the new controller is the _entry() function in ifi_startup.c. _entry() then calls _startup() when power is applied to the PIC it begins running whatever code is located at _entry(). This allows the developer to add some code in _entry() that my only need to be done at powerup. _startup() in this case initializes the stack pointer, sets up RAM and FLASH memory, calls _do_cinit() which initializes the .cinit section. Then main() is called and your custom processing can begin. Look at pages 42 and 43 in the Microchip C18 compiler manual for more details.
Keep in mind that in C anything with a # in front of it like #define or #ifdef is only used at compile time not at runtime.

Please correct me if I am wrong with any of this.:]

*Originally posted by Skabana159 *
We were under the impression that C will always start running at main()

C programs don’t really “start” anywhere. Instead, your C program begins when something outside that program calls one of your functions. By convention, this is typically main(), but that’s really decided by the operating system. On a desktop machine, the OS will copy your program off of the disk into RAM and then jump to the address of the program’s entry point (i.e. main()). In an embedded system without an operating system, however, the processor simply starts executing code at a certain address when it’s turned on. This address is hard-coded and is known as the “reset vector”. Typically this reset vector is located near the end of the processor’s address space, which means there isn’t a lot of room for code. So, what usually happens is that the reset vector is just used to call some other function located somewhere else in memory with more room for code. In IFI’s case, the code for _entry() probably gets put at the reset vector, which then calls _startup() which allows IFI to do some housekeeping stuff before it calls main() - they didn’t have to use main() but they did just because everyone is used to main() being the entry point for user-supplied code. There’s no reason that code running on the PIC would have to have a function named main() at all.

Well this was a nice long winded message that probably isn’t all that clear. Let me know though if you’d like me to explain anything better or differently…

*Originally posted by Skabana159 *
**Okay, here is what our team decided about ifi_initialization does, and please anyone correct me if anything appears incorrect, because we were really just guessing.
We were under the impression that C will always start running at main(),

Is this correct?

It would be nice, however, to know what exact flow the program follows, rather than guessing like we did. **

If you look in ifi_startup.c, you will see a line:
#pragma code _entry_scn=RESET_VECTOR

This is defining the entry point for your code when the PIC resets. This is the start point for the code.

The code snippet which follows:
void _entry(void){_asm goto _startup _endasm}

calls the function _startup().

Next is the line:
#pragma code _startup_scn

which tells the compiler to put the next stuff in the “code” section at “_startup_scn”.

The following code:
void _startup(void){
_asm

_endasm
loop:

Clear_memory();
_do_cinit();
main();

goto loop:
}

starts your stuff executing.

In the file, main.c, you have your main() function, which calls IFI_Initialization() followed immediately by User_Initialization().

At this point, you can dump loop based routines into the while(1){…} loop, which is an infinite loop.

The functions Process_Data_From_Master_uP()
and
Process_Data_From_Local_IO()
run in a non-timed fashion in “the background”.

In user_fast_routines.c, there seems to be a timed loop. This would execute every “n” msec, regardless of what is going on in the while loop in main.

There also appears to be an interrupt service routine for the low priority interrupt and which can be executed using the 6 digital input pins on the front of the EDU-RC, labelled “Interrupt.”

This code would execute whenever a transition (low-to-high, I think) is initiated on one of those pins.

In embedded, interrupt driven code you have to give up the notion of step-by-step execution. Multiple programs can be running simultaneously and which interact with each other.

Be careful of the while(1) {…} loop. There is the timed stuff (17 or 26ms packet rate) and then the “high speed loop”. The problem is that if you do significant processing in the slow loop (say, reading a LEGO sensor using some delays & bit twiddling) and burn 2-3 ms, then all of a sudden your “fast” code has a big gap where it isn’t being called very fast.

Better is to set up a periodic timer interrupt, say at 4 khz, and put your fast code in there.

IFI probably kept their initialization code secret to maintain control over the user chip and to allow them the flexibility to change the interface to their radio system without impacting the users.

Just to clarify on the interrupts.

There are a total of 8 input pins on the pic that trigger interrupts. In the low priority int handler routine they give us, we only have access to 6 of them, and since there are only 6 pins, I’m assuming they use int0 and int1 for other purposes.

4 of the 8 interrupt pins (B0-B3) interrupt on either a rising edge or a falling edge (not both), and you can select between the two using the appropriate INTCON. The other 4 (B4-B7) trigger an interrupt on change, rising or falling (both). There is only 1 flag assossiated with all 4 pins, so if the interrupt triggers you need to compare the current state of all 4 pins to the state before the interrupt to figure out which one changed.

I’m pretty sure pin 1 of the interrupts is connected to port B pin 2, pin 2 to port B pin 3, etc down the line, so the last 4 are the interrupt on change pins.