Custom DPA handler is an optional user‑defined C language routine that can handle various events and thus implements user peripherals, handles embedded peripherals, provides peripheral virtualization, adds internal device logic, and much more. If the custom DPA handler is implemented it must be enabled in the TR Configuration to receive events.
If the Custom DPA handler is enabled in the TR Configuration but it was not detected (see point 2. below) then the device indicates an error by constant switching on the red LED and by returning the ERROR_MISSING_CUSTOM_DPA_HANDLER error code to every DPA Request (except to request to OS peripheral, to request Get information for more peripherals and to all DPA Requests at DPA service mode). In this case, the OS peripheral can be used to fix the problem (disable handler and restart the device or load missing handler already stored in the external EEPROM).
Please respect the following rules when implementing Custom DPA handler:
1. Custom DPA handler must be the first C routine declared as bit CustomDpaHandler() in your code. It must be located at the fixed address CUSTOM_HANDLER_ADDRESS = 0x3A20 of the MCU Flash memory.
2. The very first instruction of the handler must be CLRWDT to indicate its presence. To do it just insert clrwdt(); statement right after the handler header. This statement/instruction is thus executed at the beginning of every event (except the Interrupt event).
3. There is an 864 instruction long block in the MCU flash memory reserved for custom DPA handler in the current version of DPA. See CUSTOM_HANDLER_ADDRESS_END.
4. “cases:” for unhandled events do not have to be programmed to save memory space and make the code more readable. Please see Interrupt for an exception from this rule.
5. Variables, as well as function parameters, must be allocated in the standard RAM bank 11 only (48 bytes at range 0x5C0-0x5EF).
6. Variables can be also mapped to the RAM bank 12 that equals the peripheral RAM space (48 bytes at range 0x620 - 0x64F).
7. Do not use bufferRF, bufferCOM, and bufferAUX at all (except inside events Reset, Init, Idle, and DisableInterrupts). bufferAUX can be used at the FrcValue event.
8. bufferINFO can be used inside events but not to carry data between events as its content can change. bufferINFO cannot be used at all when an event is raised during processing IO Set, FRC Send, Get Peripheral Info, or FRC Extra result as these DPA Requests use bufferINFO internally.
9. Also, do not use userReg0 and userReg1 variables unless you do not call any DPA API function.
10.DPA uses bits 0-1 of the userStatus IQRF OS variable internally. Usage of other userStatus bits is reserved, therefore their future availability is not guaranteed.
11.Maintain the written code as much speed optimized as possible as the long time spent in the user code might negatively influence device behavior. Especially Interrupt and Idle events must be programmed extremely efficiently.
12.Special attention must be paid to the implementation of an Interrupt event. See details in the dedicated chapter.
13.Do not use timer TMR6 at [C]. Use DpaTicks being internally driven by TMR6 instead.
14.Do not use IQRF OS functions start[Long]Delay and waitDelay (except locally inside of Reset, Init, Idle, and DisableInterrupts event handlers). Use waitMS or TMR6 (but not at the [C] device) instead. Also, IQRF OS functions startCapture and captureTicks can be used for timing purposes. See IQRF OS documentation for existing side effects.
15.Sending and receiving packets by predefined DPA API functions are allowed only at events Reset, Init, Idle, DisableInterrupts, PeerToPeer, and AfterRouting. It is required to keep the same RF settings (see setRFpower, setRFchannel, set*mode, etc. IQRF OS functions) that were set at the beginning of the event upon the event exit.
16.Do not modify the content of IQRF OS variables within the event code. It is required to save their values and restore them at the event exit.
17.Starting from the Init event an MCU watchdog timer with a 4 s period is enabled. Do not change WDT settings. Also, make sure to call clrwdt() if needed to prevent WDT reset.
18.If possible, try to avoid executing MCU stack demanding complex requests (e.g. Discovery) from subroutines to prevent MCU stack overflow. Such overflow results in the HW device reset.
19.Both FSR0 and FSR1 point to the message PData at the Custom DPA Handler entry (except Interrupt event). This can be used for code optimization.
A Custom DPA handler can be optionally loaded “over the air” into the device. Please see LoadCode.