mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #7806 from hasnainvirk/fix_for_cn470
LoRaWAN: Fixing Hard fault in CN470 PHY layerpull/7960/head
						commit
						c7d6560571
					
				| 
						 | 
				
			
			@ -1,35 +1,52 @@
 | 
			
		|||
Frequency sub-bands in US915/AU915:
 | 
			
		||||
 | 
			
		||||
 US915/AU915 PHYs define channel structures which can support up-to 72 channels for upstream.
 | 
			
		||||
 First 64 channels (0-63), occupy 125 kHz and the last 8 channels (64-71) occupy 500 kHz. 
 | 
			
		||||
 US915/AU915 PHYs define channel structures that can support up to 72 channels for upstream.
 | 
			
		||||
 The first 64 channels (0-63), occupy 125 kHz and the last 8 channels (64-71) occupy 500 kHz. 
 | 
			
		||||
 However, most of the base stations available in the market support 8 or 16 channels. 
 | 
			
		||||
 Network acquisition can become costly if the device have no prior knowledge of active channel plan and it enables 
 | 
			
		||||
 Network acquisition can become costly if the device has no prior knowledge of the active channel plan and it enables 
 | 
			
		||||
 all 72 channels to begin with. 
 | 
			
		||||
 
 | 
			
		||||
 LoRaWAN 1.0.2 Regional parameters specification refers to a strategy of probing a set of nine channels (8 + 1) for
 | 
			
		||||
 joining process. According to that strategy the device is supposed to alternatively select a channel from a set of 
 | 
			
		||||
 8, 125 kHz channels and a 500 kHz channel.
 | 
			
		||||
 For example send a join request alternatively on a randomly selected channel from a set of 0-7 channels and
 | 
			
		||||
 channel 64 which is the first 500 kHz channel.
 | 
			
		||||
 The LoRaWAN 1.0.2 Regional parameters specification refers to a strategy of probing a set of nine channels (8 + 1) for
 | 
			
		||||
 the joining process. According to that strategy, the device alternatively selects a channel from a set of 
 | 
			
		||||
 8 125 kHz channels and a 500 kHz channel.
 | 
			
		||||
 For example, send a join request alternatively on a randomly selected channel from a set of 0-7 channels and
 | 
			
		||||
 channel 64, which is the first 500 kHz channel.
 | 
			
		||||
 
 | 
			
		||||
 Once the device has joined the network (in case of OTAA) or have sent the first uplink (in case of ABP), the network
 | 
			
		||||
 may send a LinkAdrReq mac command to set the channel mask to be used. Please note that these PHY layers do not
 | 
			
		||||
 support CFList so LinkAdrReq is the way the network tells you what channel plan to use. 
 | 
			
		||||
 Once the device has joined the network (in case of OTAA) or has sent the first uplink (in the case of ABP), the network
 | 
			
		||||
 may send a LinkAdrReq MAC command to set the channel mask to be used. Please note that these PHY layers do not
 | 
			
		||||
 support CFList, so LinkAdrReq is the way the network tells you what channel plan to use. 
 | 
			
		||||
 
 | 
			
		||||
 Mbed LoRaWAN stack can be configured to use a particular frequency sub-band (FSB) which means that we don't have to
 | 
			
		||||
 probe all sets of channels. "fsb-mask" in lorawan/mbed_lib.json is the parameter which can be used to tell the 
 | 
			
		||||
 system which FSB or a set of FSBs to use. By default the "fsb-mask" is set to "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}" 
 | 
			
		||||
 that means all channels are active, i.e., 64 125 kHz channels and 8 500 kHz channels are active. If the user wishes
 | 
			
		||||
 to use a custom FSB, he/she needs to set appropriate mask as the value of "fsb-mask". For example:
 | 
			
		||||
 If the user wishes to use the first FSB, i.e., first 8 125 kHz channels (0-7) and the first 500 kHz channel:
 | 
			
		||||
 You can configure the Mbed LoRaWAN stack to use a particular frequency sub-band (FSB), which means that you don't have to
 | 
			
		||||
 probe all sets of channels. "fsb-mask" in lorawan/mbed_lib.json is the parameter that you can use to tell the 
 | 
			
		||||
 system which FSB or set of FSBs to use. By default, the "fsb-mask" is set to "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}". 
 | 
			
		||||
 That means all channels are active. In other words, 64 125 kHz channels and 8 500 kHz channels are active. If you wish
 | 
			
		||||
 to use a custom FSB, you need to set an appropriate mask as the value of "fsb-mask". For example, if you wish to use the 
 | 
			
		||||
 first FSB, in other words, the first 8 125 kHz channels (0-7) and the first 500 kHz channel:
 | 
			
		||||
    "fsb-mask" = "{0x00FF, 0x0000, 0x0000, 0x0000, 0x0001}" 
 | 
			
		||||
 Similarly, if the user wishes to use second FSB, i.e., 2nd set of 8 125 kHz channels (8-15) and the 2nd 500 kHz 
 | 
			
		||||
 Similarly, if you wish to use the second FSB, in other words, the second set of 8 125 kHz channels (8-15) and the 2nd 500 kHz 
 | 
			
		||||
 channel:
 | 
			
		||||
    "fsb-mask" = "{0xFF00, 0x0000, 0x0000, 0x0000, 0x0002}"
 | 
			
		||||
 
 | 
			
		||||
 You can also combine FSBs if your base station supports more than 8 channels. For example:
 | 
			
		||||
    "fsb-mask" = "{0x00FF, 0x0000, 0x0000, 0xFF00, 0x0081}"
 | 
			
		||||
 will mean use channels 0-7(125 kHz) + channel 64 (500 KHz) and channels 56-63 (125 kHz) + channel 71 (500 kHz).
 | 
			
		||||
 means use channels 0-7(125 kHz) + channel 64 (500 KHz) and channels 56-63 (125 kHz) + channel 71 (500 kHz).
 | 
			
		||||
 
 | 
			
		||||
 Please note that for Certification requirements, you need to alternate between 125 kHz and 500 kHz channels, so before joining, 
 | 
			
		||||
 do not set a mask that enables only 500 kHz or only 125 kHz channels.  
 | 
			
		||||
 
 | 
			
		||||
 Frequency sub-bands in CN470 PHY:
 | 
			
		||||
 
 | 
			
		||||
 The LoRaPHYCN470 class defines 96 channels in total, as per the LoRaWAN Regional Specification. These 96 channels
 | 
			
		||||
 are 125 kHz wide each and can be subdivided into 6 sub-bands containing 16 channels each. 
 | 
			
		||||
 "fsb-mask-china" is the parameter that lorawan/mbed_lib.json defines. It can be used to enforce an FSB. It is defined
 | 
			
		||||
 as a C-style array, and the first element of the array corresponds to first 8 channels (0-7) and so on. By default, all 
 | 
			
		||||
 96 channels are enabled, but there may be base stations that do not support all 96 channels. Therefore, network acquisition
 | 
			
		||||
 can become cumbersome if the device hops on random channels. The probability of finding a correct channel for a base station 
 | 
			
		||||
 that supports 8 channels would be 1/12. 
 | 
			
		||||
 
 | 
			
		||||
 For example, if your base station supports 16 channels (channels 0-15), set the "fsb-mask-china" as:
 | 
			
		||||
  "fsb-mask-china" = "{0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}" 
 | 
			
		||||
 
 | 
			
		||||
 Similarly, if your base station supports 8 channels (channels 0-7), set the "fsb-mask-china" as:
 | 
			
		||||
  "fsb-mask-china" = "{0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}" 
 | 
			
		||||
 
 | 
			
		||||
 Please note that for Certification requirements, you need to alternate between 125 kHz and 500 kHz channels and that's
 | 
			
		||||
 why before joining you should not set a mask that enables only 500 kHz or only 125 kHz channels.  
 | 
			
		||||
| 
						 | 
				
			
			@ -206,6 +206,8 @@ static const uint8_t max_payloads_with_repeater_CN470[] = {51, 51, 51, 115, 222,
 | 
			
		|||
 | 
			
		||||
LoRaPHYCN470::LoRaPHYCN470()
 | 
			
		||||
{
 | 
			
		||||
    static const uint16_t fsb_mask[] = MBED_CONF_LORA_FSB_MASK_CHINA;
 | 
			
		||||
 | 
			
		||||
    bands[0] = CN470_BAND0;
 | 
			
		||||
 | 
			
		||||
    // Channels
 | 
			
		||||
| 
						 | 
				
			
			@ -218,12 +220,9 @@ LoRaPHYCN470::LoRaPHYCN470()
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    // Initialize the channels default mask
 | 
			
		||||
    default_channel_mask[0] = 0xFFFF;
 | 
			
		||||
    default_channel_mask[1] = 0xFFFF;
 | 
			
		||||
    default_channel_mask[2] = 0xFFFF;
 | 
			
		||||
    default_channel_mask[3] = 0xFFFF;
 | 
			
		||||
    default_channel_mask[4] = 0xFFFF;
 | 
			
		||||
    default_channel_mask[5] = 0xFFFF;
 | 
			
		||||
    for (uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++) {
 | 
			
		||||
        default_channel_mask[i] = 0xFFFF & fsb_mask[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Update the channels mask
 | 
			
		||||
    copy_channel_mask(channel_mask, default_channel_mask, CN470_CHANNEL_MASK_SIZE);
 | 
			
		||||
| 
						 | 
				
			
			@ -302,6 +301,64 @@ LoRaPHYCN470::~LoRaPHYCN470()
 | 
			
		|||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
lorawan_status_t LoRaPHYCN470::set_next_channel(channel_selection_params_t *params,
 | 
			
		||||
                                                uint8_t *channel, lorawan_time_t *time,
 | 
			
		||||
                                                lorawan_time_t *aggregate_timeoff)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t channel_count = 0;
 | 
			
		||||
    uint8_t delay_tx = 0;
 | 
			
		||||
 | 
			
		||||
    uint8_t enabled_channels[CN470_MAX_NB_CHANNELS] = {0};
 | 
			
		||||
 | 
			
		||||
    lorawan_time_t next_tx_delay = 0;
 | 
			
		||||
    band_t *band_table = (band_t *) phy_params.bands.table;
 | 
			
		||||
 | 
			
		||||
    if (num_active_channels(phy_params.channels.mask, 0,
 | 
			
		||||
                            phy_params.channels.mask_size) == 0) {
 | 
			
		||||
 | 
			
		||||
        // Reactivate default channels
 | 
			
		||||
        copy_channel_mask(phy_params.channels.mask,
 | 
			
		||||
                          phy_params.channels.default_mask,
 | 
			
		||||
                          phy_params.channels.mask_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (params->aggregate_timeoff
 | 
			
		||||
            <= _lora_time->get_elapsed_time(params->last_aggregate_tx_time)) {
 | 
			
		||||
        // Reset Aggregated time off
 | 
			
		||||
        *aggregate_timeoff = 0;
 | 
			
		||||
 | 
			
		||||
        // Update bands Time OFF
 | 
			
		||||
        next_tx_delay = update_band_timeoff(params->joined,
 | 
			
		||||
                                            params->dc_enabled,
 | 
			
		||||
                                            band_table, phy_params.bands.size);
 | 
			
		||||
 | 
			
		||||
        // Search how many channels are enabled
 | 
			
		||||
        channel_count = enabled_channel_count(params->current_datarate,
 | 
			
		||||
                                              phy_params.channels.mask,
 | 
			
		||||
                                              enabled_channels, &delay_tx);
 | 
			
		||||
    } else {
 | 
			
		||||
        delay_tx++;
 | 
			
		||||
        next_tx_delay = params->aggregate_timeoff -
 | 
			
		||||
                        _lora_time->get_elapsed_time(params->last_aggregate_tx_time);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (channel_count > 0) {
 | 
			
		||||
        // We found a valid channel
 | 
			
		||||
        *channel = enabled_channels[get_random(0, channel_count - 1)];
 | 
			
		||||
        *time = 0;
 | 
			
		||||
        return LORAWAN_STATUS_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (delay_tx > 0) {
 | 
			
		||||
        // Delay transmission due to AggregatedTimeOff or to a band time off
 | 
			
		||||
        *time = next_tx_delay;
 | 
			
		||||
        return LORAWAN_STATUS_DUTYCYCLE_RESTRICTED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *time = 0;
 | 
			
		||||
    return LORAWAN_STATUS_NO_CHANNEL_FOUND;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool LoRaPHYCN470::rx_config(rx_config_params_t* config)
 | 
			
		||||
{
 | 
			
		||||
    int8_t dr = config->datarate;
 | 
			
		||||
| 
						 | 
				
			
			@ -332,7 +389,8 @@ bool LoRaPHYCN470::rx_config(rx_config_params_t* config)
 | 
			
		|||
    _radio->set_channel(frequency);
 | 
			
		||||
 | 
			
		||||
    // Radio configuration
 | 
			
		||||
    _radio->set_rx_config(MODEM_LORA, config->bandwidth, phy_dr, 1, 0, 8,
 | 
			
		||||
    _radio->set_rx_config(MODEM_LORA, config->bandwidth, phy_dr, 1, 0,
 | 
			
		||||
                          MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH,
 | 
			
		||||
                          config->window_timeout, false, 0, false, 0, 0, true,
 | 
			
		||||
                          config->is_rx_continuous);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -371,7 +429,8 @@ bool LoRaPHYCN470::tx_config(tx_config_params_t* config, int8_t* tx_power,
 | 
			
		|||
 | 
			
		||||
    _radio->set_channel(channels[config->channel].frequency);
 | 
			
		||||
 | 
			
		||||
   _radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, 0, phy_dr, 1, 8, false, true,
 | 
			
		||||
   _radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, 0, phy_dr, 1,
 | 
			
		||||
                         MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH, false, true,
 | 
			
		||||
                         0, 0, false, 3000);
 | 
			
		||||
    // Setup maximum payload lenght of the radio driver
 | 
			
		||||
    _radio->set_max_payload_length(MODEM_LORA, config->pkt_len);
 | 
			
		||||
| 
						 | 
				
			
			@ -421,12 +480,9 @@ uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t* params,
 | 
			
		|||
        if (adr_settings.ch_mask_ctrl == 6) {
 | 
			
		||||
 | 
			
		||||
            // Enable all 125 kHz channels
 | 
			
		||||
            temp_channel_masks[0] = 0xFFFF;
 | 
			
		||||
            temp_channel_masks[1] = 0xFFFF;
 | 
			
		||||
            temp_channel_masks[2] = 0xFFFF;
 | 
			
		||||
            temp_channel_masks[3] = 0xFFFF;
 | 
			
		||||
            temp_channel_masks[4] = 0xFFFF;
 | 
			
		||||
            temp_channel_masks[5] = 0xFFFF;
 | 
			
		||||
            for (uint8_t i = 0; i < CN470_CHANNEL_MASK_SIZE; i++) {
 | 
			
		||||
                temp_channel_masks[i] = 0xFFFF;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } else if( adr_settings.ch_mask_ctrl == 7 ) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,6 +56,10 @@ public:
 | 
			
		|||
    LoRaPHYCN470();
 | 
			
		||||
    virtual ~LoRaPHYCN470();
 | 
			
		||||
 | 
			
		||||
    virtual lorawan_status_t set_next_channel(channel_selection_params_t *params,
 | 
			
		||||
                                      uint8_t *channel, lorawan_time_t *time,
 | 
			
		||||
                                      lorawan_time_t *aggregate_timeoff);
 | 
			
		||||
 | 
			
		||||
    virtual bool rx_config(rx_config_params_t* config);
 | 
			
		||||
 | 
			
		||||
    virtual bool tx_config(tx_config_params_t* config, int8_t* tx_power,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,6 +84,10 @@
 | 
			
		|||
        "fsb-mask": {
 | 
			
		||||
        	"help": "FSB mask for upstream [Only for US915 & AU915] Check lorawan/FSB_Usage.txt for more details",
 | 
			
		||||
        	"value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}"
 | 
			
		||||
        },
 | 
			
		||||
        "fsb-mask-china": {
 | 
			
		||||
        	"help": "FSB mask for upstream [CN470 PHY] Check lorawan/FSB_Usage.txt for more details",
 | 
			
		||||
        	"value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue