Silicon Laboratories Si4010 Series Operating instructions

Rev. 1.0 2/12 Copyright © 2012 by Silicon Laboratories AN370
AN370
Si4010 SOFTWARE PROGRAMMING GUIDE
1. Purpose
This document defines the application programming interface (API) for the Si4010 firmware. It is intended to serve
as a guide for application development.
The document is related to the device revision 0x02 as returned by bSys_GetRevId() function and Trim version
0x09 as returned by the Device Information in the NVM Programming Utility. It describes files needed to build
customer application and the details of the implemented API functions in ROM. There are also additional API
functions not present in ROM, provided in the form of a linkable library for the Keil toolchain. For a description of
this additional library, see “AN526: Si4010 API Additional Library Description”.
2. Known Issues
These are known issues related to the current version of the Si4010 device hardware revision 0x02 as returned by
bSys_GetRevId() function and Trim version 0x09 as returned by the Device Information in the NVM Programming
Utility.
There is an issue related to the LED driver, which demonstrates itself only under the following circumstances
when all three conditions are satisfied:
The device programming level is Factory or User. For those levels the C2 debugging interface is enabled after the boot by
a boot routine.
The device has been disconnected from the Silicon Labs IDE. The "disconnected" means in a software sense, not
physically, using the Connect/Disconnect buttons on IDE. Or, the device is running the User code automatically after the
boot without ever being connected to the IDE.
The device is running a code which turns the LED on and off.
If all the conditions are satisfied then after the first LED blink when the LED is turned off the GPIO4 stops working
and is no longer visible to the application.
If the device programming level is Run or the C2 debugging interface is internally disabled there is no issue. The
LED can be turned on and off without affecting the device GPIO4 functionality.
The issue can be summarized as follows: Whenever the C2 debugging interface is enabled, the device is not
connected to IDE, and the LED is turned on and off, then the GPIO4 will stop functioning. Since in Run mode the
C2 is disabled after the boot process finishes, the GPIO4 is not affected.
Therefore, this issue only effects software development process and inconveniences the developer. After the
application is finalized and the chip is programmed as Run there is no issue. See suggested solution scenarios and
workarounds in the section related to debugging with LED.

AN370
2 Rev. 1.0

AN370
Rev. 1.0 3
TABLE OF CONTENTS
Section Page
1. Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1
2. Known Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1
3. Memory Regions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4
3.1. 8051 Internal Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5
3.2. Memory Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5
3.3. CODE/XDATA RAM Reserved Area . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6
3.4. DATA/IDATA Internal Memory Reserved Area . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6
4. Building an Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8
4.1. Type Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8
4.2. Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8
4.3. Included Library Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10
4.4. Stack Size Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11
4.5. Hardware Thread Safety . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14
4.6. Non-ISR Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14
4.7. Function Calling Convention . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15
4.8. Files Needed for Building an Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16
4.9. Compiling an Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .18
5. User Application Required Interrupt Service Routines . . . . . . . . . . . . . . . . . . . . . . . . .20
6. Interrupt and System Impact of Some Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22
6.1. Interrupt Priorities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22
6.2. Interrupt Enable Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .23
6.3. System Clock Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24
6.4. Transmission Chain Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25
6.5. Infinite Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27
7. Module Descriptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28
7.1. AES Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28
7.2. Button Service Module and Master Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .31
7.3. Demodulator Temperature Sensor Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .42
7.4. Encoding Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .48
7.5. Frequency Counter Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .53
7.6. Frequency Casting Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .56
7.7. HVRAM Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .60
7.8. Multi-time Programmable (MTP) Memory Module . . . . . . . . . . . . . . . . . . . . . . . . . .61
7.9. Battery Voltage Measurement Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .67
7.10. Non-Volatile Memory (NVM) Copy Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69
7.11. Output Data Serializer (ODS) Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .74
7.12. Power Amplifier (PA) Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .77
7.13. Single Transmission Loop (STL) Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .80
7.14. System Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .85
7.15. Sleep Timer Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .95
8. Simple Application Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .98
Document Change List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .102
Contact Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .104

AN370
4 Rev. 1.0
3. Memory Regions
The following table lists some key terms for writing firmware for the Si4010:
Term Definition
8051 Internal
Memory 256 bytes of RAM internal to the 8051 MCU. Fastest for MCU to access. It is broken into
three categories, DATA, IDATA and SFR space. See below for a description of these.
DATA Portion of the internal memory at addresses 0x00 through 0x7F. This memory can be
accessed both directly and indirectly.
DATA is a recognized Keil compiler keyword.
IDATA Portion of the internal memory occupying addresses 0x80 through 0xFF. This memory can
only be accessed indirectly. IDATA is a recognized Keil compiler keyword.
SFR Space Special Function Register Space is located in internal memory at addresses 0x80 through
0xFF. This memory can only be accessed directly.
CODE
XDATA This is both user code memory (CODE) and external data memory (XDATA). Residing at
addresses 0x0000 through 0x11FF. In the Si4010 this space is equivalent to the 4.5 kB of
on chip RAM. CODE/XDATA RAM is where the user application is run from.
CODE and XDATA are recognized Keil compiler keywords.
XREG Refers to the set of hardware registers located in XDATA address space at addresses
0x4000 through 0x40FF. More information on XREGs can be found in the Si4010 data
sheet.
This is not a recognized Keil compiler keyword.
ROM Read only memory containing all the API functions. Residing at CODE addresses 0x8000
through 0xAFFF. The CPU executes ROM code directly. ROM is not readable by the user
application.
NVM Non-Volatile Memory. Each bit can only be written as 1 once (One Time Programmable,
OTP). Code stored in this memory is intended to be loaded into RAM upon boot. It is also
possible for the application to copy code from NVM using the NVM Copy Module. Virtually
mapped to addresses 0xE000 through 0xFFFF. Only accessible by using API functions.
Only formatted data programmed by the NVM composer/programmer are available to be
loaded at boot time or at runtime by bNvm_CopyBlock() function. There is not byte by byte
direct access to NVM.
MTP 128 bits of Multi-Time Programmable Memory (EEPROM). This memory is mapped as read
only at XDATA addresses 0x4040 to 0x404F. Writing to MTP can only be done through the
MTP API Module. User should use the MTP API for read access as well.
HVRAM HVRAM in the Si4010 consists of 64 bits (8 bytes) of battery backed RAM. As long as the
power is connected to the chip, the HVRAM keeps its content. The content of the HVRAM
is not affected by shutting down the chip by vSys_Shutdown() function. Only accessible by
using the HVRAM API module functions.

AN370
Rev. 1.0 5
3.1. 8051 Internal Memory
Figure 1 shows the Si4010 memory which is internal to the 8051 MCU.
Figure 1. CPU Internal Memory Organization
3.2. Memory Map
After the chip boots, the memory on the Si4010 is mapped as shown in Figure 2. The 4.5 kB RAM section is
accessible both as CODE and XDATA (MOVC and MOVX instructions). The XREG region is accessible only as
XDATA (MOVX). The ROM is not accessible as data, but the code residing in ROM can be executed. The NVM is
virtually mapped into this region, but is not directly accessible by CPU. The NVM API functions must be used to
access the NVM.
Figure 2. Si4010 Unified CODE/XDATA Memory Organization
Indirect addressing only
by @Ri pointers
DATA
IDATA
SFR
(DATA)
0x00
0x7F
0x80
0xFF
0x80
0xFF
MOV A, @Ri
Direct addressing only
MOV A, addr
Both direct and indirect addressing
Internal Memory
0x0000 RAM 4.5K
0xFFFF
CODE/
XDATA
0x8000
0x4000
64KB
16KB
ROM 12K
XREG
0xE000 NVM 8K
0x11FF
0x40FF
0xAFFF
Virtual mapping, not directly
accessible by CPU

AN370
6 Rev. 1.0
3.3. CODE/XDATA RAM Reserved Area
Part of CODE/XDATA space at the end of the RAM (highest addresses) is reserved for the ROM API. This area
must not be used by the application. The following diagram gives an outline of the used space. The area used by
the API and other factory settings may change dynamically per chip. The user should read (through Silicon Labs
IDE, for example) the value of the wBoot_DpramTrimBeg variable, which points to the first used address in the
CODE/XDATA RAM. Any location at lower address then the one pointed to by the content of the
wBoot_DpramTrimBeg variable is available for customer user. See the Boot section in the Si4010 data sheet.
Figure 3. CODE/XDTA RAM Organization
Important: The user application must not overwrite the Factory and Boot XDATA region during runtime. There is
no hardware protection of that region, so it is up to the customer discipline not to place any CODE nor XDATA
variables. If that happens, the behavior of the chip becomes unpredictable.
3.4. DATA/IDATA Internal Memory Reserved Area
Portions of the 8051 MCU internal memory are also used by ROM API code. The following diagram shows DATA
and IDATA used by ROM API code. The provided file si4010_link.c must be compiled and link with the
application. The file contains dummy arrays at fixed addresses to notify the linker not to put any data into the
reserved regions.
The user must set the stack pointer such that the stack will never overwrite the reserved regions.
Boot_AfterTrimExe
Boot_PatchExe
Reserved
Boot XDATA
0x0000
Factory
XDATA
bBoot_BootStat
wBoot_NvmCopyAddr
wBoot_NvmUserBeg
wBoot_DpramTrimBeg
User
CODE/
XDATA
0x11FF
0x11FD
0x11F3
0x11F5
CODE/XDATA
RAM 4.5KB
0x11F7

AN370
Rev. 1.0 7
Figure 4. DATA/IDATA Reserved Spaces
Note that the region used by the ROM API is split in between the DATA and IDATA to allow the continuous region
of 128 bytes, split evenly in between DATA and IDATA regions. This will allow for a byte array of that size. The bit
addressable region of 16 bytes is not used by the API. All four register banks are shown as available. However, the
user should assume that the API functions destroy all the registers R0 .. R7 of the currently selected bank.
API functions use the register bank currently selected by the user application. The API functions do not access
RB0 directly. User is free to choose any register bank for main application and any register bank for interrupt
service routines.
API
Reserved
(16B)
0x20
Registers
RB1 .. RB3
Available
(24B)
Bit Addr
Available
(16B)
0x2F
0x30
0x3F
DATA/IDATA
MCU Internal RAM
DATA .. lower 128
RAM bytes, Direct
and Indirect
Addressing
Available
(64B)
0x40
0x7F
Available
(64B)
0x80
API
Reserved
(64B)
0xC0
0xFF
0xBF
0x08
0x1F
Reg RB0
Available
(8B)
0x00
0x07
IDATA ..
upper128 RAM
bytes, Indirect
Addressing only
DATA/IDATA ..continuous
128 RAM bytes user
region

AN370
8 Rev. 1.0
4. Building an Application
4.1. Type Definitions
The following table lists types that are defined or expected for use with the Si4010 API. The custom types are
defined in the header file si4010_types.h.
All variables are stored in big endian fashion, which means that the most significant byte is stored on the lowest
(smallest) address location.
4.2. Naming
Strict naming conventions are used for the API. Each function belonging to the same software module is prefixed
by the module name or module name abbreviation. Before the module name, the function name is prefixed by the
type of the return value.
All variables are prefixed by their type. Defined types, pointers, input and output variables, and pointers to input/
output function variables are also prefixed accordingly. In addition to the prefixes for the basic types in the table in
section 4.1, the following prefixes are used. The dot in the prefix specification means that the letter cannot stand on
its own and must be preceded or succeeded by another prefix letter or letters:
Type Bit Width Type Definition Prefix
unsigned char 8 BYTE b
unsigned int 16 WORD w
unsigned long int 32 LWORD l
signed char 8 CHAR c
int 16 i
long int 32 j
float 32 f
Prefix Description Example
t Type definition of a structure tBsr_Setup
r Structure variable definition rSetup
p. Pointer to prSetup
v Void vBsr_Setup()
.i Input function variable biTstCtrl
..o Output function variable. Make sense if used
as a pointer to output. The pointed content is
generated by the function.
*pboOutput
..io Input/output function variables. Make sense
if used as a pointer. The pointed content is
used as input and modified by a function.
*pbioState

AN370
Rev. 1.0 9
The module naming prefixes used are as follows:
Example:
void vAes_Cipher /* AES 128 bit key encryption .. works
on global IDATA State and RoundKey */
(
BYTE idata *pbioState,
BYTE idata *pbioRoundKey
);
The function returns void (v) and is a part of the AES (Aes) module. It has two input pointer variables (p), both
pointing into the DATA/IDATA internal memory at a BYTE (b). The area pointed to is both input to the function and
is modified by the function (io).
Module Prefix Module Name
Aes AES
Bsr Button service routine
DmdTs Temperature sensor and its demodulator
Enc Encoding of data for transmission
Fc Frequency counter
FCast Frequency casting and fine tuning
Hvram HVRAM
Mtp MTP (EEPROM) memory
MVdd Battery VDD measurement
Nvm NVM memory for copying data to RAM
Ods Output data serializer
Pa Power amplifier
Sys System functions
SleepTim Sleep timer
Stl Single Tx loop

AN370
10 Rev. 1.0
4.3. Included Library Routines
Following is a list of all Keil library routines included in ROM. They are available for use by the application via the
ROM symbol map file for Keil toolchain (si4010_rom_keil.a51).
The library routines cannot be used with other toolchains. If the user does not desire to link these library routines to
the application (they take precedence over the actual library provided by the toolchain), then it is necessary to use
si4010_rom_all.a51 instead of the Keil specific toolchain during the application building.
?C?ULSHR
?C?LSHL
?C?OFFXADD
?C?FPSUB
?C?FPADD
?C?FPMUL
?C?FCASTL
?C?FCASTC
?C?FCASTI
?C?CASTF
?C?FPGETOPN2
?C?FPNANRESULT
?C?FPOVERFLOW
?C?FPRESULT
?C?FPRESULT2
?C?FPUNDERFLOW
?C?LNEG
?C?LLDIDATA
?C?LLDXDATA
?C?LLDIDATA0
?C?LLDXDATA0
?C?LSTIDATA
?C?LSTXDATA
?C?LMUL
?C?ULCMP
?C?LOR
?C?LADD
?C?IMUL
?C?LSUB
?C?LXOR
?C?FPDIV
?C?ULDIV
?C?SIDIV
?C?PCMP3
?C?FPCMP
?C?UIDIV
?C?SLDIV
_ABS
?C?ICALL
?C?ICALL2
?C?IILDX

AN370
Rev. 1.0 11
4.4. Stack Size Requirements
Table 1 shows the additional stack requirements when the user code is calling an API function. The number of
bytes in the table is in addition to the 2 bytes return address storage requirements for the return address to be
stored on top of the stack when the function is called. For example, if the function is not using any additional stack
storage (not calling any other function, and not using PUSH/POP instructions), then the function internal stack
requirement is listed as 0.
The maximum stack size requirement is determined by the interrupt service routines and if the application is using
one or two interrupt priorities. The worst case stack requirement would come from the application using two levels
of interrupt levels and lower priority ISR was interrupted by the higher priority ISR.
The user is required to leave at least additional 4 bytes of stack space, 2 bytes as a guard and 2 bytes for possible
Silicon Labs use in the future.
Table 1. Additional Stack Requirements
Function Internal stack use
[bytes]
vAes_Cipher 3
vAes_InvCipher 3
vAes_InvGenKey 3
wBsr_Pop —
vBsr_Setup 4
vBsr_InitPts 2
bBsr_GetPtsItemCnt —
vBsr_Service 4
wBsr_GetCurrentButton —
bBsr_GetTimestamp 2
vDmdTs_Setup —
iDmdTs_GetData —
iDmdTs_GetLatestDmdSample —
iDmdTs_GetLatestTemp 2
vDmdTs_ClearDmd —
vDmdTs_ClearDmdIntFlag —
vDmdTs_IsrCall 2
bDmdTs_GetSamplesTaken —
vDmdTs_Enable —
vDmdTs_RunForTemp 2
vDmdTs_ResetCounts —
bEnc_4b5bEncode —
vEnc_Set4b5bLastBit —
bEnc_ManchesterEncode —
vFCast_Setup —
vFCast_XoSetup 4
vFCast_Tune 8
vFCast_FskAdj 4
vFCast_FineTune 4
vFc_Setup —
vFc_StartCount —
vFc_PollDone —
lFc_StartPollGetCount 2
lFc_GetCount —

AN370
12 Rev. 1.0
Based on Table 1 the minimum recommended stack size is as follows:
bHvram_Read —
vHvram_Write —
lMtp_GetDecCount 2
vMtp_SetDecCount 6
vMtp_IncCount 2
bMtp_Write 2
pbMtp_Read 2
vMtp_Strobe —
iMVdd_Measure 6
vNvm_SetAddr —
wNvm_GetAddr —
bNvm_CopyBlock —
vNvm_McEnableRead 2
vNvm_McDisableRead —
vOds_Setup —
vOds_Enable —
vOds_WriteData —
vPa_Setup 2
vPa_Tune 4
lSleepTim_GetCount 2
vSleepTim_SetCount 2
bSleepTim_CheckDutyCycle 4
vSleepTim_AddTxTimeToCounter 4
lSleepTim_GetOneHourValue —
vStl_EncodeSetup —
vStl_SingleTxLoop 6
vStl_PreLoop 6
vStl_PostLoop 2
bStl_EncodeByte 2
vSys_BandGapLdo 2
bSys_GetRevId —
lSys_GetProdId —
bSys_GetBootStatus —
vSys_SetClkSys —
vSys_Setup —
lSys_GetMasterTime 2
vSys_IncMasterTime 2
vSys_SetMasterTime —
vSys_LedIntensity —
vSys_Shutdown 2
vSys_16BitDecLoop —
vSys_8BitDecLoop —
vSys_FirstPowerUp 4
wSys_GetKeilVer —
vSys_ForceLc 2
vSys_LpOscAdj 4
Table 1. Additional Stack Requirements (Continued)

AN370
Rev. 1.0 13
Using only single interrupt priority level. The main application function can be interrupted by single ISR and any
ISR will not get interrupted any further. It also assumes that the user is compiling the ISR routine with using
directive.2 call to ROM function
+ 8 API worst case above
+ 2 interrupt return address
+ 5 for ISR routine storage of A, DPH etc. while compiling with using 1 directive
+ 2 call to ROM function from ISR
+ 6 API worst case for function callable from ISR
+ 4 required spares
= 29 bytes
Recommended stack size is 30 + whatever the user application calling depth is.
Using two interrupt priority levels. The main application function can be interrupted by single ISR and any ISR
can get interrupted by higher priority interrupt. It also assumes that the user is compiling the ISR routine with
using directive. The calculation assumes that the vFCast_Tune() is called either from the main application or
from ISR, but not both.
2 call to ROM function
+ 8 API worst case above
+ 2 interrupt return address
+ 5 for ISR routine storage of A, DPH etc. while compiling with using 1 directive
+ 2 call to ROM function from ISR
+ 6 API worst case for function callable from ISR
+ 2 interrupt return address
+ 5 for ISR routine storage of A, DPH etc. while compiling with using 2 directive
+ 2 call to ROM function from ISR
+ 6 API worst case for function callable from ISR
+ 4 required spares
= 44 bytes
Recommended stack size is 44 + whatever the user application calling depth is.

AN370
14 Rev. 1.0
It is up to the user to adjust the recommended sizes above according to the application true needs.
It is recommended to reserve the stack size by modifying the line defining the reserved size of the stack in
startup.a51 (in the published examples the <example>_startup.a51 is distributed) to the proper value. By doing that
the linker will notify the user when the reserved stack area is encroaching on other DATA/IDATA variables:
;---------------------------------------------------------------------------
;
; CODE:
;
NAME ?C_STARTUP
?C_C51STARTUP SEGMENT CODE
?STACK SEGMENT IDATA
; -- Nominally the DS 1 is used for the STACK segment. However, if we want
; to reserve a desired space and make sure that we are not overflowing
; sizes we should allocated desired amount here.
RSEG ?STACK
DS 32 ; Reserve 32 bytes of the stack
The user is responsible of setting the beginning of the STACK segment on the linker command line as explained in
application software building section. Any change of the stack size requires the linker command line to reflect the
change.
4.5. Hardware Thread Safety
Almost all of the API functions access hardware. If the function accessing the same hardware is going to be used
in the main application and in the interrupt service routine (ISR) then there is a conflict. There are no semaphores
nor any hardware access protections implemented in the API routines. From hardware point of view, the API
functions should be treated as not thread safe.
4.6. Non-ISR Functions
Certain functions in the ROM are not allowed to be called from an interrupt service routine (ISR). This is because
they share memory space (DATA, IDATA, XDATA) with other functions in the form of their local variables. Sharing
variables is a way to reduce the use of memory. The reason that calls from an interrupt service routine are not
allowed is because of the possibility of two functions running at the same time which are relying on the same
memory space. Following is a list of functions which may not be called from within any interrupt service routine.
vAes_Cipher()
vAes_InvCipher()
vAes_InvGenKey()
wBsr_Pop()
wBsr_GetCurrentButton()
lMtp_DecToGray()
lMtp_GetDecCount()
vMtp_IncCount()
vSleepTim_GetCount()
vSleepTim_SetCount()

AN370
Rev. 1.0 15
4.7. Function Calling Convention
All input and output function variables are passed in registers. The function calling convention and parameter
passing is a Keil convention. It is also used by Raisonance toolchain. Maximum 3 parameters can be passed to
functions in registers. When more input data is needed within the function, a data structure is used and only a
pointer to the structure is passed to the function.
Generic pointers (3 byte pointer) are not used in the API and if the pointer is passed as an input to a function, the
storage location where it points to is always specified. The table below shows the order of the function parameter
and what registers store them. Note that unsigned types are passed the same way as signed (char and
unsigned char, for example).
If the registers required by subsequent parameters are taken by the previous arguments, then the subsequent
arguments cannot be passed in the registers. For example, passing two long variables in registers is not possible.
Similarly, passing long first and int second is not possible, while passing int first and int second is possible.
Function return values are always passed in registers. Note that unsigned types are passed the same way as
signed (char and unsigned char, for example).
The user should also assume that all the functions are modifying all the registers in the current register bank.
Argument
Order
Number
Argument Type and Passing Registers
char or
1-byte pointer (*DATA,
*IDATA)
int or
2-byte pointer
(*XDATA)
long or
float
1. R7 R6 .. MSB
R7 .. LSB R4-R7
(R4 .. MSB)
2. R5 R4 .. MSB
R5 .. LSB R4-R7
(R4 .. MSB)
3. R3 R2 .. MSB
R3 .. LSB N/A
Return Type Passing Registers
bit CY .. carry flag
char or
1-byte pointer (*DATA, *IDATA) R7
int or
2-byte pointer
(*XDATA)
R6 .. MSB
R7 .. LSB
long or
float R4–R7 (R4 .. MSB)

AN370
16 Rev. 1.0
4.8. Files Needed for Building an Application
When building an application which will use ROM based API functions, there are several files needed. The
following table lists these files along with their descriptions.
These files are in the directory:
…\common\src\
in the Si4010 installation tree.
4.8.1. Device si4010.h and si4010.inc Headers
The C device header si4010.h and assembly si4010.inc header define the hardware registers in the device. They
File Name Description
si4010_types.h Header file that declares type definitions used in the API. See Type Defi-
nitions section for more information.
si4010.h Device header file that declares all SFR and XREG registers. It also
defines masks and bit indices which are to be used when accessing fields
within registers. This is a C header file. Must be included in all C files
using the Si4010.
si4010.inc Same as si4010.h, but for use with an assembler. This file should be
included in all assembly source files while using Si4010.
si4010_api_rom.h C header declaring all the API functions. Must be included to the applica-
tion which uses the API.
startup.a51 Simplified assembly startup file for Keil and Raisonance toolchains. Cus-
tomer may want to modify this file. It must be included in the application
build.
si4010_rom_keil.a51 Assembly ROM symbol map that must be assembled and linked into the
application build if the API functions are being used. It tells the linker the
API functions are located in ROM. This file is tailored to Keil toolchain.
It also includes references to some of the Keil library functions.
si4010_rom_all.a51 Same as above, but for any other toolchain. It can also be used with Keil
toolchain if the user does not desire to use Keil library functions in ROM.
With Keil toolchain use either this one or the one above, but not both.
si4010_data.c Data file related to the si4010.h defining the XREG register in XDATA
area. This file must be included in the application build.
si4010_link.c File with dummy array variables to force linker to avoid DATA and IDATA
spaces used and reserved by ROM API. If this file is not used the linker
area avoidance directive must be used. User may want to augment this
file to notify the linker that the end of CODE/XDATA RAM is also reserved
for API use. A commented section showing how to achieve that is
included at the end of the file.
If the Si4010 revision B silicon (Si4010-B1-GS or Si4010-B1-GT) is used, then the following file is also
required:
si4010_fix_rom_keil.lib This file is needed only for Rev B. Keil library file containing fixed
vFCast_FskAdj function. Without it the frequency modulation will not
work.This file must be included in the application build if FSK modulation
is used (i.e., vFCast_FskAdj function is called). In that case, only the Keil
toolchain is supported.

AN370
Rev. 1.0 17
define all the SFR, XDATA mapped XREG registers, boot status variables, and interrupt priority numbers. Same
items are defined in both the C and assembly headers, so only the C header is used to describe what is present
there. The same applies to the assembly device header.
For each of the fields in each of the SFR or XREG registers there is a register address defined. However, if the byte
wide register consists of more than one field which has a width less than 8 bits, there are two additional items
defined for each field, mask and bit location. The mask field name has M_ prefix, while the bit index name has B_
prefix:
1. The bit mask for the field. The mask contains 1 at the bit positions within a byte occupied by the field:
#define M_<FIELD NAME> <field bit mask>
2. The bit index number within the byte where the field begins. In other words, the base bit index of the field within
a byte:
#define B_<FIELD NAME> <field low significant bit index>
For example:
/* -- ODS_TIMING .. 0xaa */
#define M_ODS_CK_DIV 0x07 .. field mask defines
#define M_ODS_EDGE_TIME 0x18
#define M_ODS_GROUP_WIDTH 0xe0
#define B_ODS_CK_DIV 0 .. base bit index defines
#define B_ODS_EDGE_TIME 3
#define B_ODS_GROUP_WIDTH 5
The #define statements were added for convenience to initialize or modify the single and multi-bit fields inside of
the registers. For example if the user desires to initialize fields ODC_CK_DIV to 5, ODS_EDGE_TIME to 2, and
ODS_GROUP_WIDTH to 6 in the ODS_TIMING register then in the usual manner the user would have to define
the masks himself or use direct constants in the code:
ODS_TIMING = 5 | (2 << 3) | (6 << 5);
Hard to read what the intent was. Suggested way using the provided base bit constants is as follows:
ODS_TIMING = (5 << B_ODS_CK_DIV)
| (2 << B_ODS_EDGE_TIME)
| (6 << B_ODS_GROUP_WIDTH);
To use this naming to clear the Matrix and Roff mode bits at the beginning of the user application, the code can be
made very readable:
/* Disable the Matrix and Roff modes on GPIO[3:1] */
PORT_CTRL &= ~(M_PORT_MATRIX | M_PORT_ROFF | M_PORT_STROBE);
PORT_CTRL |= M_PORT_STROBE;
PORT_CTRL &= (~M_PORT_STROBE);

AN370
18 Rev. 1.0
4.9. Compiling an Application
To use the Si4010 API to build a user application in C, the user must do the following:
1. To be able to use the Silicon Laboratories IDE for debugging, the user must use the Keil BL51 linker or toolchain
with the standard OMF-51 output file format. The user cannot use the LX51 linker, since the Keil proprietary
output format, OMF-2, is not understood by the Silicon Laboratories IDE.
2. Add the path …\common\src\ to the C compiler and include directive. This is where the Si4010 files are
installed.
3. Include si4010.h and si4010_api_rom.h headers in every C source file of the application. These files
include the si4010_types.h header automatically:
#include "si4010.h"
#include "si4010_api_rom.h"
4. Add the following files, which have to be assembled or compiled, into the application build, and/or those files
must be linked with the user application:
si4010_rom_keil.a51 or for non-Keil compilers si4010_rom_all.a51
si4010_data.c
si4010_link.c
startup.a51
si4010_fix_rom_keil.lib only for Rev B.
For Keil toolchain, if the user does not desire to use some of the Keil library functions in the ROM, then the file
si4010_rom_all.a51 must be used with the Keil toolchain instead.
5. The user must use the stack pointer setting directive manually on a linker command line or from the compilation
IDE. Since the end of the IDATA memory is reserved and used by the API, the stack segment for stack pointer
setting as defined in startup.a51 must be done manually.
Optionally, the startup.a51 can be modified not to include stack pointer setting using a stack segment.
Then the user will have to set the stack pointer manually to a fixed location in startup.a51 or at the
beginning of the application.
The following shows linker command line directives to place a stack manually using the address 0x80 as an
example:
For Keil BL51: STACK(?STACK(0x80))
For Keil LX51: SEGMENTS(?STACK(I:0x80))
For Raisonance:IDATA(?STACK(0x80)) .. while using the supplied startup.a51
6. The user must make sure that the application is not using the CODE/XDATA reserved area of RAM as
described above. To achieve this, the user may either control the XDATA reserved area directly on a linker
command line, or edit the si4010_link.c file to add the reserved XDATA area there (preferred solution,
since the file contains a commented section at its end explaining how to do that), or create additional file with
dummy fixed address XDATA byte array.
7. The user must make sure that the CODE and XDATA areas as provided to the linker are not overlapping since
the CODE and XDATA share the same physical RAM. For example, the CODE and XDATA linker directives
should set as shown below. In this example, the code size is limited to 0x0D00 length, followed by XDATA
variable area:
For Keil BL51: CO(0x0000-0x0CFF) XD(0x0D00-0x107F)
For Keil LX51: CLASSES(CODE(C:0X0-C:0XCFF), CONST(C:0X0-C:0XCFF),
XDATA (X:0XD00-X:0X107F), … )
8. The API uses part of both DATA/IDATA and XDATA memories for data storage and the user application code
must not change content of those areas. Those areas must be completely avoided by the user application. The
provided file si4010_link.c reserves API space in DATA/IDATA memories as used by API, since the API regions

AN370
Rev. 1.0 19
in DATA/IDATA memories are fixed.
However, the API routines occupy XDATA area towards the end of the XDATA space. The size of the API
occupied region depends on the trim value and may change from chip to chip, but usually the value will be fixed
for all production parts of the same revision.
At the end of the si4010_link.c file there is a commented out section how to tell the linker that the end of the
CODE/XDATA memory is reserved for API use. The user should read the wBoot_DpramTrimBeg variable to get
the first address of the API occupied location. Anything below that (towards 0x0000) is available for user CODE/
XDATA to use. The user has to look at the content of wBoot_DpramTrimBeg residing at the address 0x11F3.
The variable content is directly accessible from the Silicon Labs IDE:
View Debug Windows Si4010 System Vars
It is critical that neither user CODE nor user XDATA will encroach on that space.
For example, the currently shipped version of the chip has the value:
wBoot_DpramTrimBeg = 0x1080
Therefore, as an example, that user needs to reserve 64 bytes (0x40) of the XDATA space for his application
and the rest of the CODE/XDATA memory will be reserved for code. It is recommended to keep the user XDATA
after the CODE as shown in this example:
CODE: 0x0000 .. 0x103F
XDATA: 0x1040 .. 0x107F … 64 bytes of XDATA just before the API XDATA
The linker directives as in the item 7 above would be as follows:
For Keil BL51: CO(0x0-0x103F) XD(0x1040-0x107F)
For Keil LX51: CLASSES(CODE(C:0x0-C:0x103F), CONST(C:0x0-C:0x103F),
XDATA (X:0x1040-X:0x107F), … )

AN370
20 Rev. 1.0
5. User Application Required Interrupt Service Routines
The device API and user application cannot function without the temperature sensor demodulator module running
behind the scenes and measuring temperature. The same module is used when measuring battery voltage.
For the system to be functional the user must include a temperature sensor demodulator interrupt service routine
(DMD ISR) in the main application code. At least two DMD TS module calls must be included in the DMD ISR as
shown in the example below.
Listed below are API functions relying on the DMD ISR to be present and running, meaning that DMD ISR must be
actively invoked and interrupting the functions listed:
vFCast_Tune()
vSys_LpOscAdj()
vStl_PreLoop()
vStl_SingleTxLoop()
iMVdd_Measure()
The following construct also relies on the DMD ISR running and interrupting the function the construct is in. The
construct is a wait the first valid DMD ISR sample to be generated by the DMD ISR:
while ( 0 == bDmdTx_GetSamplesTaken() ) {}
All functions from the DMD TS module with module prefix
DmdTs_*
also require the DMD ISR to be present in the system.
The user is free to use the using directive when defining ISR functions. The downside of not using the using
directive when defining an ISR is that when the ISR is invoked the system needs to store 13 bytes of data on the
stack, on top of 2 bytes of the return address. Therefore, stack requirements are more pronounced if the using
directive is not used.
If the user is using two interrupt priorities it is recommended that the register bank 2 (RB2) is used for the DMD
ISR. The example show the RB2 used since that choice would be universal for single or dual priority levels. If the
user system uses only single ISR priority level in the whole system then the RB1 can be used in the DMD ISR.
Required DMD ISR. The ISR must call two DMD TS functions as shown.
/*
*------------------------------------------------------------------------------
*
* INCLUDES:
*/
#include "si4010.h"
#include "si4010_api_rom.h"
/*
*==============================================================================
*
* VISIBLE FUNCTIONS:
*/
void vIsr_Dmd
(
void
Other manuals for Si4010 Series
3
Table of contents
Other Silicon Laboratories Transmitter manuals

Silicon Laboratories
Silicon Laboratories Si47 Series Operating instructions

Silicon Laboratories
Silicon Laboratories Si4704 Series Operating instructions

Silicon Laboratories
Silicon Laboratories Si4012 Operating instructions

Silicon Laboratories
Silicon Laboratories Si4010-C2 User manual

Silicon Laboratories
Silicon Laboratories Si4010 Series User manual