Proprietary Knowledge Base

    Publish
     
      • Minimal RAIL application

        andrasbiro | 08/237/2016 | 08:04 AM

        This article is mostly outdated with the release of Flex 1.1, but I keep it here for legacy usage.

        For Flex 1.1, the minimal RAIL application is the "Simple Sample Application without HAL", while the "Simple Sample Application" is a good starting point for generic application development (it uses HAL, but it's usually not an issue if you're not targeting minimal code space or power consumption, and it's easy to modify it later not to use HAL).

        Turning off printf float for GCC does still work and saves code space.

         

        Most of our demos use a lot of peripherals, and in a lot of projects, you barely need any peripherals. So the question arises: How an absolute minimum RAIL application would look like?

        Let's say, just initialize the radio, send a really small message, than do nothing.

         

        Generating the project

         

        Use the empty_rail example, since it's basically just the configurator, nothing else. We will use our own c code. Set up the RadioConfig to whatever you want, and only enable the RAIL Library plugin:

        2016-08-24_14h00_40.png

        We will use the RAILCb_RfReady callback, so enable that, but only that:

        2016-08-24_13h15_52.png

        On the other tab, add some include paths (directories) needed to use the kit. The last directory should represent the board you use.

        2016-08-24_13h17_17.png

        (The first one is in there by default, but it's not shown until you manually add some more)

         

        Adding drivers

         

        RAIL (or the peripherals needed by RAIL) needs a few emlib c files to work. Namely: em_cmu.c, em_emu.c em_int.c and em_system.c.

        So let's add them to the project. The simplest way to do it is to create a new folder in the project, than drag end drop the c files there from <RAILFolder>\submodules\emlib\src\. Studio will pop up a window there, it's a good idea to create a link, relative to STUDIO_SDK_LOC: since that points to the RAIL folder, the project should work, even if you move it to an other computer.

         2016-08-24_10h59_18.png

        In the end, the project should look something like this:

         

         2016-08-24_13h26_31.png

         

        Creating the main.c file

         

        Add a main.c file to the project, and for now, just create the simplest file that should compile:

         

        int main(void){
        while(1)
        ; return 0; } void RAILCb_RfReady(void) { }

         

        Initializing RAIL

         

        In our examples, RAIL initialization starts with halInit(). We won't use that call, since it starts up PTI, some timers, etc - a lot of things we want to avoid.

        Note: Most WirelessGecko boards have an onboard serial flash chip, which, at power on reset consumes quite a lot of power. We won't start that, so be aware that the current consumption will be significantly higher. See the boardDisableSpiFlash() function in hal_efr.c to see how to turn it off.

         

        RAIL actually only needs the following:

        • DCDC
        • HFXO
        • PA

        Note: Unless you want to use RFSense in EM2. That would need some LF oscillator

        So let's modify our very simple main.c which will start up those, than starts and configures RAIL:

         

        #include "rail.h"
        #include "rail_types.h"
        #include "rail_config.h"
        
        #include "em_chip.h"
        #include "em_emu.h"
        #include "em_cmu.h"
        #include "bsp.h"
        #include "pa.h"
        
        #define MAX_PACKET_SIZE  1
        
        RAIL_Init_t railInitParams = {
        		MAX_PACKET_SIZE,
        		RADIO_CONFIG_XTAL_FREQUENCY,
        		RAIL_CAL_ALL,
        };
        
        volatile bool initialized = false;
        
        int main(void){
        	CHIP_Init();
        	EMU_DCDCInit_TypeDef dcdcInit = EMU_DCDCINIT_WSTK_DEFAULT;
        	CMU_HFXOInit_TypeDef hfxoInit = CMU_HFXOINIT_WSTK_DEFAULT;
        	RADIO_PAInit_t paInit;
        
        	EMU_DCDCInit(&dcdcInit);
        	CMU_HFXOInit(&hfxoInit);
        
        	/* Switch HFCLK to HFXO and disable HFRCO */
        	CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO);
        	CMU_OscillatorEnable(cmuOsc_HFRCO, false, false);
        
        	// Initialize the PA now that the HFXO is up and the timing is correct
        	#if (RADIO_CONFIG_BASE_FREQUENCY < 1000000000UL)
        	paInit = (RADIO_PAInit_t) RADIO_PA_SUBGIG_INIT;
        	#else
        	paInit = (RADIO_PAInit_t) RADIO_PA_2P4_INIT;
        	#endif
        
        	RADIO_PA_Init(&paInit);
        	RAIL_RfInit(&railInitParams);
        	RAIL_RfIdle();
        
        	RAIL_PacketLengthConfigFrameType(frameTypeConfigList[0]);
        	if (RAIL_RadioConfig((void*)configList[0])) { while(1); }
        
        	RAIL_ChannelConfig(channelConfigs[0]);
        
        	while( !initialized )
        		;

        while(1)
        ; return 0; } void RAILCb_RfReady(void) { initialized = true; }

         

        Sending a packet

         

        To send a packet, we need to define its payload

         

        uint8_t txData[1];
        
        RAIL_TxData_t transmitPayload = {
        		(uint8_t*)(&txData),
        		sizeof(txData),
        };

        Then, after initialization, we set up the payload, load it to RAIL, then send it:

         

         

        txData[0] = 0x12;
        RAIL_RfIdle();
        RAIL_TxDataLoad(&transmitPayload);
        RAIL_TxStart(0, NULL, NULL);

        And that's it. You should have something similar to the attached code. This is a very minimal RAIL example which work.

         

         

        Reducing code size (GCC only)

         

         By defualt, GCC compiles in float support for printf, which uses a lot of code space.  You can turn that off in the project properties:

        2016-08-24_13h57_07.png

      • EZRadioPro properties sorted for RX and TX

        andrasbiro | 08/236/2016 | 05:34 AM

        There are a lot of protocols which require switching between multiple PHY configurations. Obviosuly, to support them, you have to reconfigure the radio to switch between them. However, reconfiguring the radio could take a long time, mostly because of the slow SPI communication between the MCU and the radio. So it's always a good idea to only upload the difference between the two configurations when switching PHYs.

         

        There's a special, but quite common case, where you can optimize this further: If PHY1 is only used for reception, and PHY2 for transmission, you can configure the reception related properties to PHY1, the transmission related properties to PHY2 during initialization, and only upload the difference of the common properties. For this, you can use the following list of all the properties of EZRadioPro (revC2A), sorted to four categories:

        • TX: Transmission only related properties
        • RX: Reception only related properties
        • Both: Properties used for both RX and TX
        • Neither: Not RF related properties

        There are some options appearing in two categories with a condition. There's probably more like these, I just listed some very obvious ones.

         

        Also, use your common sense: For example, WUT is listed under the neither category, but if you use it for setting up low duty cycle mode, it becomes an RX parameter.


        TX:

         

        PREAMBLE_TX_LENGTH
        PKT_TX_THRESHOLD
        PKT_FIELD_1_LENGTH             (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_1_CONFIG             (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_1_CRC_CONFIG         (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_2_LENGTH             (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_2_CONFIG             (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_2_CRC_CONFIG         (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_3_LENGTH             (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_3_CONFIG             (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_3_CRC_CONFIG         (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_4_LENGTH             (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_4_CONFIG             (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_4_CRC_CONFIG         (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_5_LENGTH             (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_5_CONFIG             (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        PKT_FIELD_5_CRC_CONFIG         (if PKT_CONFIG1:PH_FIELD_SPLIT == 1)
        MODEM_DATA_RATE
        MODEM_TX_NCO_MODE
        MODEM_FREQ_DEV
        MODEM_TX_FILTER_COEFF_8
        MODEM_TX_FILTER_COEFF_7
        MODEM_TX_FILTER_COEFF_6
        MODEM_TX_FILTER_COEFF_5
        MODEM_TX_FILTER_COEFF_4
        MODEM_TX_FILTER_COEFF_3
        MODEM_TX_FILTER_COEFF_2
        MODEM_TX_FILTER_COEFF_1
        MODEM_TX_FILTER_COEFF_0
        MODEM_TX_RAMP_DELAY
        PA_MODE
        PA_PWR_LVL
        PA_BIAS_CLKDUTY
        PA_TC
        PA_RAMP_EX
        PA_RAMP_DOWN_DELAY
        PA_DIG_PWR_SEQ_CONFIG

         

        RX:

         

        INT_CTL_MODEM_ENABLE
        PREAMBLE_CONFIG_STD_1
        PREAMBLE_CONFIG_STD_2
        PREAMBLE_POSTAMBLE_CONFIG
        PREAMBLE_POSTAMBLE_PATTERN
        PKT_LEN
        PKT_LEN_FIELD_SOURCE
        PKT_LEN_ADJUST
        PKT_RX_THRESHOLD
        PKT_RX_FIELD_1_LENGTH
        PKT_RX_FIELD_1_CONFIG
        PKT_RX_FIELD_1_CRC_CONFIG
        PKT_RX_FIELD_2_LENGTH
        PKT_RX_FIELD_2_CONFIG
        PKT_RX_FIELD_2_CRC_CONFIG
        PKT_RX_FIELD_3_LENGTH
        PKT_RX_FIELD_3_CONFIG
        PKT_RX_FIELD_3_CRC_CONFIG
        PKT_RX_FIELD_4_LENGTH
        PKT_RX_FIELD_4_CONFIG
        PKT_RX_FIELD_4_CRC_CONFIG
        PKT_RX_FIELD_5_LENGTH
        PKT_RX_FIELD_5_CONFIG
        PKT_RX_FIELD_5_CRC_CONFIG
        MODEM_FREQ_OFFSET		 (if PLL AFC is enabled)
        MODEM_MDM_CTRL
        MODEM_IF_CONTROL
        MODEM_IF_FREQ
        MODEM_DECIMATION_CFG1
        MODEM_DECIMATION_CFG0
        MODEM_DECIMATION_CFG2
        MODEM_IFPKD_THRESHOLDS
        MODEM_BCR_OSR
        MODEM_BCR_NCO_OFFSET
        MODEM_BCR_GAIN
        MODEM_BCR_GEAR
        MODEM_BCR_MISC1
        MODEM_BCR_MISC0
        MODEM_AFC_GEAR
        MODEM_AFC_WAIT
        MODEM_AFC_GAIN
        MODEM_AFC_LIMITER
        MODEM_AFC_MISC
        MODEM_AFC_ZIFOFF
        MODEM_ADC_CTRL
        MODEM_AGC_CONTROL
        MODEM_AGC_WINDOW_SIZE
        MODEM_AGC_RFPD_DECAY
        MODEM_AGC_IFPD_DECAY
        MODEM_FSK4_GAIN1
        MODEM_FSK4_GAIN0
        MODEM_FSK4_TH
        MODEM_OOK_PDTC
        MODEM_OOK_BLOPK
        MODEM_OOK_CNT1
        MODEM_OOK_MISC
        MODEM_RAW_CONTROL
        MODEM_RAW_EYE
        MODEM_ANT_DIV_MODE
        MODEM_RSSI_THRESH
        MODEM_RSSI_JUMP_THRESH
        MODEM_RSSI_CONTROL
        MODEM_RSSI_CONTROL2
        MODEM_RSSI_COMP
        MODEM_RAW_SEARCH2
        MODEM_SPIKE_DET
        MODEM_ONE_SHOT_AFC
        MODEM_RSSI_HYSTERESIS
        MODEM_RSSI_MUTE
        MODEM_FAST_RSSI_DELAY
        MODEM_PSM
        MODEM_DSA_CTRL1
        MODEM_DSA_CTRL2
        MODEM_DSA_QUAL
        MODEM_DSA_RSSI
        MODEM_DSA_MISC
        MODEM_CHFLT_RX1_CHFLT_COE
        MODEM_CHFLT_RX2_CHFLT_COE
        MATCH_VALUE_1
        MATCH_MASK_1
        MATCH_CTRL_1
        MATCH_VALUE_2
        MATCH_MASK_2
        MATCH_CTRL_2
        MATCH_VALUE_3
        MATCH_MASK_3
        MATCH_CTRL_3
        MATCH_VALUE_4
        MATCH_MASK_4
        MATCH_CTRL_4
        RX_HOP_CONTROL
        RX_HOP_TABLE_SIZE
        RX_HOP_TABLE_ENTRY[]

         

        Both:

         

        GLOBAL_XO_TUNE
        GLOBAL_CONFIG
        INT_CTL_ENABLE
        INT_CTL_PH_ENABLE
        PREAMBLE_CONFIG_NSTD
        PREAMBLE_CONFIG
        PREAMBLE_PATTERN
        SYNC_CONFIG
        SYNC_BITS
        SYNC_CONFIG2
        PKT_CRC_CONFIG
        PKT_WHT_POLY
        PKT_WHT_SEED
        PKT_WHT_BIT_NUM
        PKT_CONFIG1
        PKT_CONFIG2
        PKT_FIELD_1_LENGTH		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_1_CONFIG		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_1_CRC_CONFIG		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_2_LENGTH		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_2_CONFIG		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_2_CRC_CONFIG		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_3_LENGTH		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_3_CONFIG		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_3_CRC_CONFIG		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_4_LENGTH		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_4_CONFIG		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_4_CRC_CONFIG		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_5_LENGTH		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_5_CONFIG		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_FIELD_5_CRC_CONFIG		 (if PKT_CONFIG1:PH_FIELD_SPLIT == 0)
        PKT_CRC_SEED
        MODEM_MOD_TYPE
        MODEM_MAP_CONTROL
        MODEM_DSM_CTRL
        MODEM_FREQ_OFFSET		 (if PLL AFC is disabled)
        MODEM_FSK4_MAP
        MODEM_ANT_DIV_CONTROL MODEM_CLKGEN_BAND SYNTH_PFDCP_CPFF SYNTH_PFDCP_CPINT SYNTH_VCO_KV SYNTH_LPFILT3 SYNTH_LPFILT2 SYNTH_LPFILT1 SYNTH_LPFILT0 SYNTH_VCO_KVCAL FREQ_CONTROL_INTE FREQ_CONTROL_FRAC FREQ_CONTROL_CHANNEL_STEP_SIZE FREQ_CONTROL_W_SIZE FREQ_CONTROL_VCOCNT_RX_ADJ

         

        Neither:

         

        GLOBAL_CLK_CFG
        GLOBAL_LOW_BATT_THRESH
        GLOBAL_WUT_CONFIG
        GLOBAL_WUT_M
        GLOBAL_WUT_R
        GLOBAL_WUT_LDC
        GLOBAL_WUT_CAL
        INT_CTL_CHIP_ENABLE
        FRR_CTL_A_MODE
        FRR_CTL_B_MODE
        FRR_CTL_C_MODE
        FRR_CTL_D_MODE
        PTI_CTL
        PTI_BAUD
        PTI_LOG_EN



        Thanks for @zopapp for the initial sorted list
        This was the command used to get grep a property list from the api html:

        grep '<li><a href="#details_prop_' < index_all.html | sed 's/.*_prop_//g'|sed 's/">.*//g'

         

         

         

      • Connect: Basic Terms and addressing

        andrasbiro | 08/225/2016 | 10:06 AM

        There are some terms in Connect came up pretty often, but don't have an explanation in one location. Usually these came from IEEE 802.15.4, and most of them related to addressing. Here are a short explanation of some of these terms:

        Channel: Most PHYs available in Connect provide multiple channels to use. There's no communication between channels, so if you transmit on channel 2, only a receiver tuned to channel 2 can receive it.

        PAN: Personal Area Network. In this case, it's equivalent to a Connect network. Note, that there can be more than one PAN in the same physical area, using different PAN ID.

        PAN ID: Identifier of the PAN, uint16_t. Using different PAN IDs, multiple networks can coexists in the same area. Think of PANs as virtual or software implemented channels. In 802.15.4, it's possible to have the destination in different PAN than the source, but that's not allowed in Connect.

        Long address or EUI64: uint64_t address, globally unique. Follows the same format as the MAC address used in IPv6.

        Short address: uint16_t address, only valid inside the PAN. Since 802.15.4 frames have a limited length (to 127B), it's a good idea to not use 8B long addresses, especially in frames that require both source and destination address (usual for data frames). This is why the short address exists. The short address is assigned by the PAN coordinator, which is the coordinator in connect star topology networks.

        Special short address 0xFFFF: Broadcast address in the PAN

        Special short address 0xFFFE: No short address assigned yet (typically because not joined to any PAN yet)

        Special short address 0x0000: (this is not 802.15.4 related) Address of the coordinator in Connect star topology network

        Endpoint: (this is not 802.15.4 related) Similar to TCP/IP ports. Helps the application to assign different endpoints to different application usage. Type is uint8_t.

        802.15.4 allows multiple type of addressing, but connect applications for now only use intra-PAN messages. This means that you can only send application data inside a PAN, source and destination identified by the short address,  PAN ID in the message both the source and the destination's PAN. Other addressing methods are used when an end device joinins to a coordinator.