标签:嵌入式系统开发,嵌入式开发,http://www.5idzw.com
Calling Utility ROM Functions,http://www.5idzw.com
With this information you can create a helper function that calls flashErasePage. Besides actually calling the Utility ROM function, this helper function needs to perform four additional steps:
Table 2. Scratch Registers1
The flashErasePage description lists APC as one of the registers destroyed, so you must make sure to save and restore that register before calling utilFlashErasePage. This task is also straightforward if you use IAR's asm() function. MAXQ assembly statements can be inserted directly into C code using this function. Since APC needs to be saved, you can just add asm("push APC") and asm("pop APC") statements around the call to utilFlashErasePage.
1At the time this application note was written, the MAXQ IAR C Compiler Reference Guide lists the DPC register as a scratch register. This is an error in the documentation and the DPC register should be considered one of the special registers.
With this information you can create a helper function that calls flashErasePage. Besides actually calling the Utility ROM function, this helper function needs to perform four additional steps:
- Configure the input to the ROM function.
- Save and restore any of the reserved registers that the ROM function destroys.
- Process the ROM function's output.
- Save, disable, and restore interrupts around the call to the ROM function.
Preparing the Inputs
This example ROM function accepts A[0] as its input, and setting A[0] is straightforward. We can declare a variable for any register in the MAXQ by using some IAR keywords and macros. To declare a variable for A[0], add the following statement:__no_init volatile __io unsigned int A0 @ _M(0x09,0x00);Pay special attention to the data type and inputs to the _M macro. This variable, A0, was declared as "unsigned int" because it is a 16-bit register. If it were an 8-bit register, we could have declared it as an "unsigned char." The inputs to the _M macro are the module number followed by offset of the A[0] register. Now you can simply set this variable to the value you want in A[0].
A0 = pageAddr;
Preserving Special Registers
You must be careful when using registers in the above manner because the compiler expects certain registers not to change from one function call to the next. The MAXQ IAR C Compiler Reference Guide lists the following registers (Table 2) as scratch registers. You can destroy these registers without disturbing the program flow. Also, the APC and DP[1] registers and bits 0, 1, and 3 of the DPC register should not be modified at any time. If any other registers are changed by a function, they should be restored before exiting that function.Table 2. Scratch Registers1
MAXQ10 Devices | MAXQ20 Devices |
A[0], A[1], A[2], A[3], GR, LC[0], LC[1], DP[0], BP, OFFS, AP | A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], GR, LC[0], LC[1], DP[0]. BP, OFFS, AP |
The flashErasePage description lists APC as one of the registers destroyed, so you must make sure to save and restore that register before calling utilFlashErasePage. This task is also straightforward if you use IAR's asm() function. MAXQ assembly statements can be inserted directly into C code using this function. Since APC needs to be saved, you can just add asm("push APC") and asm("pop APC") statements around the call to utilFlashErasePage.
Processing the ROM Function's Output
Handling the return from the ROM function is similar to handling the inputs. You can just read the appropriate registers directly. The flashErasePage function, for example, sets the carry bit on an error. You can access this bit directly using the PSF_bit structure declared in the iomaxq.h header file provided by IAR.return (PSF_bit.C == 0);
Saving, Disabling, and Restoring Interrupts
The last task to consider is whether interrupts need to be disabled. Most Utility ROM routines assume that they will not be interrupted. Therefore, if your application uses interrupts, it is wise to disable them before calling the Utility ROM functions. The easiest way to disable them is by using the IC_bit structure defined in the iomaxq.h header file and the __disable_interrupt() function defined in the intrinsics.h file.unsigned char origIGE = IC_bit.IGE; // Save current state. __disable_interrupt(); /* Add UROM call code here. */ IC_bit.IGE = origIGE; // Restore interrupt state.If you follow all of these steps, you will have code that looks similar to the following:
#include <intrinsics.h> #include <iomaxq.h> // Prototype for the real Utility ROM function. extern void utilFlashErasePage(void); // Define the register we need direct access to. __no_init volatile __io unsigned int A0 @ _M(0x09,0x00); unsigned char flashErasePage(unsigned int page) { unsigned int pageAddr; unsigned char origIGE; pageAddr = page << 8; // Change page # to an address. origIGE = IC_bit.IGE; // Save current state. __disable_interrupt(); A0 = pageAddr; // Set up input to UROM function. asm("push APC"); // UROM function destroys APC. utilFlashErasePage(); // Call actual UROM function. asm("pop APC"); // Restore APC. IC_bit.IGE = origIGE; // Restore interrupt state. return (PSF_bit.C == 0); // Check return code from UROM. }
Conclusion
Using the procedures outlined above, you can easily call the functions provided in the Utility ROM of each MAXQ microcontroller. You can create function wrappers that leverage the code in the MAXQ Utility ROM to access lookup tables, store data in program space, and other functions unique to each of the MAXQ family of devices.1At the time this application note was written, the MAXQ IAR C Compiler Reference Guide lists the DPC register as a scratch register. This is an error in the documentation and the DPC register should be considered one of the special registers.
IAR Embedded Workbench is a registered trademark of IAR Systems AB.
MAXQ is a registered trademark of Maxim Integrated Products, Inc.
<-- END: DB HTML -->