Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo by
thread_tasklet.c
00001 /* 00002 * Copyright (c) 2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include <string.h> //memset 00018 #include "eventOS_event_timer.h" 00019 #include "common_functions.h" 00020 #include "net_interface.h" 00021 #include "ip6string.h" //ip6tos 00022 #include "nsdynmemLIB.h" 00023 #include "thread_management_if.h" 00024 #include "net_polling_api.h" 00025 #include "include/thread_tasklet.h" 00026 #include "include/static_config.h" 00027 #include "include/mesh_system.h" 00028 #ifndef YOTTA_CFG 00029 #include "ns_event_loop.h" 00030 #endif 00031 // For tracing we need to define flag, have include and define group 00032 #define HAVE_DEBUG 1 00033 #include "ns_trace.h" 00034 #define TRACE_GROUP "m6Thread" 00035 00036 #include "mac_api.h" 00037 #include "sw_mac.h" 00038 00039 #define DETAILED_TRACES 00040 #ifdef DETAILED_TRACES 00041 #define TRACE_DETAIL tr_debug 00042 #else 00043 #define TRACE_DETAIL(...) 00044 #endif 00045 00046 #define INTERFACE_NAME "6L-THREAD" 00047 00048 // Tasklet timer events 00049 #define TIMER_EVENT_START_BOOTSTRAP 1 00050 00051 #define INVALID_INTERFACE_ID (-1) 00052 00053 /* 00054 * Thread tasklet states. 00055 */ 00056 typedef enum { 00057 TASKLET_STATE_CREATED = 0, 00058 TASKLET_STATE_INITIALIZED, 00059 TASKLET_STATE_BOOTSTRAP_STARTED, 00060 TASKLET_STATE_BOOTSTRAP_FAILED, 00061 TASKLET_STATE_BOOTSTRAP_READY 00062 } tasklet_state_t; 00063 00064 /* 00065 * Mesh tasklet data structure. 00066 */ 00067 typedef struct { 00068 void (*mesh_api_cb)(mesh_connection_status_t nwk_status); 00069 channel_list_s channel_list; 00070 tasklet_state_t tasklet_state; 00071 int8_t tasklet; 00072 00073 net_6lowpan_mode_e operating_mode; 00074 int8_t nwk_if_id; 00075 link_configuration_s link_config; 00076 00077 /** Default network ID*/ 00078 uint8_t networkid[16]; 00079 uint8_t extented_panid[8]; 00080 uint32_t pan_id; 00081 uint32_t rfChannel; 00082 uint8_t scan_time; 00083 net_6lowpan_gp_address_mode_e address_mode; 00084 } thread_tasklet_data_str_t; 00085 00086 00087 /* Tasklet data */ 00088 static thread_tasklet_data_str_t *thread_tasklet_data_ptr = NULL; 00089 static device_configuration_s device_configuration; 00090 00091 /* private function prototypes */ 00092 void thread_tasklet_main(arm_event_s *event); 00093 void thread_tasklet_network_state_changed(mesh_connection_status_t status); 00094 void thread_tasklet_parse_network_event(arm_event_s *event); 00095 void thread_tasklet_configure_and_connect_to_network(void); 00096 #define TRACE_THREAD_TASKLET 00097 #ifndef TRACE_THREAD_TASKLET 00098 #define thread_tasklet_trace_bootstrap_info() ((void) 0) 00099 #else 00100 void thread_tasklet_trace_bootstrap_info(void); 00101 #endif 00102 00103 /* 00104 * \brief A function which will be eventually called by NanoStack OS when ever the OS has an event to deliver. 00105 * @param event, describes the sender, receiver and event type. 00106 * 00107 * NOTE: Interrupts requested by HW are possible during this function! 00108 */ 00109 void thread_tasklet_main(arm_event_s *event) 00110 { 00111 arm_library_event_type_e event_type; 00112 event_type = (arm_library_event_type_e) event->event_type; 00113 00114 switch (event_type) { 00115 case ARM_LIB_NWK_INTERFACE_EVENT: 00116 /* This event is delivered every and each time when there is new 00117 * information of network connectivity. 00118 */ 00119 thread_tasklet_parse_network_event(event); 00120 break; 00121 00122 case ARM_LIB_TASKLET_INIT_EVENT: 00123 /* Event with type EV_INIT is an initializer event of NanoStack OS. 00124 * The event is delivered when the NanoStack OS is running fine. 00125 * This event should be delivered ONLY ONCE. 00126 */ 00127 mesh_system_send_connect_event(thread_tasklet_data_ptr->tasklet); 00128 break; 00129 00130 case ARM_LIB_SYSTEM_TIMER_EVENT: 00131 eventOS_event_timer_cancel(event->event_id, 00132 thread_tasklet_data_ptr->tasklet); 00133 00134 if (event->event_id == TIMER_EVENT_START_BOOTSTRAP) { 00135 tr_debug("Restart bootstrap"); 00136 arm_nwk_interface_up(thread_tasklet_data_ptr->nwk_if_id); 00137 } 00138 break; 00139 00140 case APPLICATION_EVENT: 00141 if (event->event_id == APPL_EVENT_CONNECT) { 00142 thread_tasklet_configure_and_connect_to_network(); 00143 } 00144 break; 00145 00146 default: 00147 break; 00148 } // switch(event_type) 00149 } 00150 00151 /** 00152 * \brief Network state event handler. 00153 * \param event show network start response or current network state. 00154 * 00155 * - ARM_NWK_BOOTSTRAP_READY: Save NVK persistent data to NVM and Net role 00156 * - ARM_NWK_NWK_SCAN_FAIL: Link Layer Active Scan Fail, Stack is Already at Idle state 00157 * - ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: No ND Router at current Channel Stack is Already at Idle state 00158 * - ARM_NWK_NWK_CONNECTION_DOWN: Connection to Access point is lost wait for Scan Result 00159 * - ARM_NWK_NWK_PARENT_POLL_FAIL: Host should run net start without any PAN-id filter and all channels 00160 * - ARM_NWK_AUHTENTICATION_FAIL: Pana Authentication fail, Stack is Already at Idle state 00161 */ 00162 void thread_tasklet_parse_network_event(arm_event_s *event) 00163 { 00164 arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e) event->event_data; 00165 tr_debug("app_parse_network_event() %d", status); 00166 switch (status) { 00167 case ARM_NWK_BOOTSTRAP_READY: 00168 /* Network is ready and node is connected to Access Point */ 00169 if (thread_tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) { 00170 tr_info("Thread bootstrap ready"); 00171 thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_READY; 00172 thread_tasklet_trace_bootstrap_info(); 00173 thread_tasklet_network_state_changed(MESH_CONNECTED); 00174 } 00175 break; 00176 case ARM_NWK_NWK_SCAN_FAIL: 00177 /* Link Layer Active Scan Fail, Stack is Already at Idle state */ 00178 tr_debug("Link Layer Scan Fail: No Beacons"); 00179 thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00180 break; 00181 case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: 00182 /* No ND Router at current Channel Stack is Already at Idle state */ 00183 tr_debug("ND Scan/ GP REG fail"); 00184 thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00185 break; 00186 case ARM_NWK_NWK_CONNECTION_DOWN: 00187 /* Connection to Access point is lost wait for Scan Result */ 00188 tr_debug("ND/RPL scan new network"); 00189 thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00190 break; 00191 case ARM_NWK_NWK_PARENT_POLL_FAIL: 00192 thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00193 break; 00194 case ARM_NWK_AUHTENTICATION_FAIL: 00195 tr_debug("Network authentication fail"); 00196 thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00197 break; 00198 default: 00199 tr_warn("Unknown event %d", status); 00200 break; 00201 } 00202 00203 if (thread_tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) { 00204 // Set 5s timer for a new network scan 00205 eventOS_event_timer_request(TIMER_EVENT_START_BOOTSTRAP, 00206 ARM_LIB_SYSTEM_TIMER_EVENT, 00207 thread_tasklet_data_ptr->tasklet, 00208 5000); 00209 } 00210 } 00211 00212 /* 00213 * \brief Configure mesh network 00214 * 00215 */ 00216 void thread_tasklet_configure_and_connect_to_network(void) 00217 { 00218 int8_t status; 00219 00220 if (MBED_MESH_API_THREAD_DEVICE_TYPE == MESH_DEVICE_TYPE_THREAD_SLEEPY_END_DEVICE) { 00221 thread_tasklet_data_ptr->operating_mode = NET_6LOWPAN_SLEEPY_HOST; 00222 } else { 00223 thread_tasklet_data_ptr->operating_mode = NET_6LOWPAN_ROUTER; 00224 } 00225 00226 arm_nwk_interface_configure_6lowpan_bootstrap_set( 00227 thread_tasklet_data_ptr->nwk_if_id, 00228 thread_tasklet_data_ptr->operating_mode, 00229 NET_6LOWPAN_THREAD); 00230 00231 // Link configuration 00232 memcpy(thread_tasklet_data_ptr->link_config.name, "Arm Powered Core", 16); 00233 00234 thread_tasklet_data_ptr->link_config.panId = MBED_MESH_API_THREAD_CONFIG_PANID; 00235 TRACE_DETAIL("PANID %x", thread_tasklet_data_ptr->link_config.panId); 00236 00237 // channel 00238 if (MBED_MESH_API_THREAD_CONFIG_CHANNEL > 27) { 00239 tr_error("Bad channel %d", MBED_MESH_API_THREAD_CONFIG_CHANNEL); 00240 return; 00241 } 00242 00243 thread_tasklet_data_ptr->link_config.rfChannel = MBED_MESH_API_THREAD_CONFIG_CHANNEL; 00244 thread_tasklet_data_ptr->channel_list.channel_page = (channel_page_e)MBED_MESH_API_THREAD_CONFIG_CHANNEL_PAGE; 00245 thread_tasklet_data_ptr->channel_list.channel_mask[0] = MBED_MESH_API_THREAD_CONFIG_CHANNEL_MASK; 00246 TRACE_DETAIL("channel: %d", thread_tasklet_data_ptr->link_config.rfChannel); 00247 TRACE_DETAIL("channel page: %d", thread_tasklet_data_ptr->channel_list.channel_page); 00248 TRACE_DETAIL("channel mask: %d", (int)thread_tasklet_data_ptr->channel_list.channel_mask[0]); 00249 00250 00251 // Beacon data setting 00252 thread_tasklet_data_ptr->link_config.Protocol_id = 0x03; 00253 thread_tasklet_data_ptr->link_config.version = 1; 00254 memcpy(thread_tasklet_data_ptr->link_config.extended_random_mac, device_configuration.eui64, 8); 00255 thread_tasklet_data_ptr->link_config.extended_random_mac[0] |= 0x02; 00256 00257 // Mesh prefix 00258 const uint8_t mesh_local_prefix[] = MBED_MESH_API_THREAD_CONFIG_ML_PREFIX; 00259 if (sizeof(mesh_local_prefix) == 8) { 00260 memcpy(thread_tasklet_data_ptr->link_config.mesh_local_ula_prefix, mesh_local_prefix, 8); 00261 TRACE_DETAIL("Mesh prefix: %s", trace_array(mesh_local_prefix, 8)); 00262 } else { 00263 tr_error("Mesh prefix, must be 8 hex chars: %s", mesh_local_prefix); 00264 return; 00265 } 00266 00267 // Master Key 00268 const uint8_t master_key[] = MBED_MESH_API_THREAD_MASTER_KEY; 00269 if (sizeof(master_key) == 16) { 00270 memcpy(thread_tasklet_data_ptr->link_config.master_key, master_key, 16); 00271 TRACE_DETAIL("Master key: %s", trace_array(master_key, 16)); 00272 } else { 00273 tr_error("Master key must be 16 hex chars: %s", master_key); 00274 return; 00275 } 00276 00277 // PSKc 00278 const uint8_t PSKc[] = MBED_MESH_API_THREAD_CONFIG_PSKC; 00279 if (sizeof(PSKc) == 16) { 00280 memcpy(thread_tasklet_data_ptr->link_config.PSKc, PSKc, 16); 00281 TRACE_DETAIL("PSKc: %s", trace_array(PSKc, 16)); 00282 } else { 00283 tr_error("PSKc must be 16 hex chars: %s", PSKc); 00284 return; 00285 } 00286 00287 // PSKd 00288 const char PSKd[] = MBED_MESH_API_THREAD_PSKD; 00289 if (sizeof(PSKd) < 7) { 00290 tr_error("PSKd length must be > 6: %s", PSKd); 00291 return; 00292 } 00293 00294 char *dyn_buf = ns_dyn_mem_alloc(sizeof(PSKd)); 00295 strcpy(dyn_buf, PSKd); 00296 ns_dyn_mem_free(device_configuration.PSKd_ptr); 00297 device_configuration.PSKd_ptr = (uint8_t*)dyn_buf; 00298 device_configuration.PSKd_len = sizeof(PSKd) - 1; 00299 TRACE_DETAIL("PSKd: %s", device_configuration.PSKd_ptr); 00300 00301 thread_tasklet_data_ptr->link_config.key_rotation = 3600; 00302 thread_tasklet_data_ptr->link_config.key_sequence = 0; 00303 00304 thread_management_node_init(thread_tasklet_data_ptr->nwk_if_id, 00305 &thread_tasklet_data_ptr->channel_list, 00306 &device_configuration, 00307 &thread_tasklet_data_ptr->link_config); 00308 00309 status = arm_nwk_interface_up(thread_tasklet_data_ptr->nwk_if_id); 00310 00311 if (status >= 0) { 00312 thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED; 00313 tr_info("Start Thread bootstrap (%s mode)", thread_tasklet_data_ptr->operating_mode == NET_6LOWPAN_SLEEPY_HOST ? "SED" : "Router"); 00314 } else { 00315 thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00316 tr_err("Bootstrap start failed, %d", status); 00317 thread_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED); 00318 } 00319 } 00320 00321 /* 00322 * Inform application about network state change 00323 */ 00324 void thread_tasklet_network_state_changed(mesh_connection_status_t status) 00325 { 00326 if (thread_tasklet_data_ptr->mesh_api_cb) { 00327 (thread_tasklet_data_ptr->mesh_api_cb)(status); 00328 } 00329 } 00330 00331 /* 00332 * Trace bootstrap information. 00333 */ 00334 #ifdef TRACE_THREAD_TASKLET 00335 void thread_tasklet_trace_bootstrap_info() 00336 { 00337 link_layer_address_s app_link_address_info; 00338 uint8_t temp_ipv6[16]; 00339 if (arm_net_address_get(thread_tasklet_data_ptr->nwk_if_id, 00340 ADDR_IPV6_GP, temp_ipv6) == 0) { 00341 tr_debug("GP IPv6: %s", trace_ipv6(temp_ipv6)); 00342 } 00343 00344 if (arm_nwk_mac_address_read(thread_tasklet_data_ptr->nwk_if_id, 00345 &app_link_address_info) != 0) { 00346 tr_error("MAC Address read fail\n"); 00347 } else { 00348 uint8_t temp[2]; 00349 common_write_16_bit(app_link_address_info.mac_short,temp); 00350 tr_debug("MAC 16-bit: %s", trace_array(temp, 2)); 00351 common_write_16_bit(app_link_address_info.PANId, temp); 00352 tr_debug("PAN ID: %s", trace_array(temp, 2)); 00353 tr_debug("MAC 64-bit: %s", trace_array(app_link_address_info.mac_long, 8)); 00354 tr_debug("IID (Based on MAC 64-bit address): %s", trace_array(app_link_address_info.iid_eui64, 8)); 00355 } 00356 } 00357 #endif /* #define TRACE_THREAD_TASKLET */ 00358 00359 int8_t thread_tasklet_get_ip_address(char *address, int8_t len) 00360 { 00361 uint8_t binary_ipv6[16]; 00362 00363 if ((len >= 40) && (0 == arm_net_address_get( 00364 thread_tasklet_data_ptr->nwk_if_id, ADDR_IPV6_GP, binary_ipv6))) { 00365 ip6tos(binary_ipv6, address); 00366 //tr_debug("IP address: %s", address); 00367 return 0; 00368 } else { 00369 return -1; 00370 } 00371 } 00372 00373 int8_t thread_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_id) 00374 { 00375 int8_t re_connecting = true; 00376 int8_t tasklet = thread_tasklet_data_ptr->tasklet; 00377 00378 if (thread_tasklet_data_ptr->nwk_if_id != INVALID_INTERFACE_ID) { 00379 return -3; // already connected to network 00380 } 00381 00382 if (thread_tasklet_data_ptr->tasklet_state == TASKLET_STATE_CREATED) { 00383 re_connecting = false; 00384 } 00385 00386 memset(thread_tasklet_data_ptr, 0, sizeof(thread_tasklet_data_str_t)); 00387 thread_tasklet_data_ptr->mesh_api_cb = callback; 00388 thread_tasklet_data_ptr->nwk_if_id = nwk_interface_id; 00389 thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_INITIALIZED; 00390 00391 if (re_connecting == false) { 00392 thread_tasklet_data_ptr->tasklet = eventOS_event_handler_create(&thread_tasklet_main, 00393 ARM_LIB_TASKLET_INIT_EVENT); 00394 if (thread_tasklet_data_ptr->tasklet < 0) { 00395 // -1 handler already used by other tasklet 00396 // -2 memory allocation failure 00397 return thread_tasklet_data_ptr->tasklet; 00398 } 00399 #ifndef YOTTA_CFG 00400 ns_event_loop_thread_start(); 00401 #endif 00402 } else { 00403 thread_tasklet_data_ptr->tasklet = tasklet; 00404 mesh_system_send_connect_event(thread_tasklet_data_ptr->tasklet); 00405 } 00406 00407 return thread_tasklet_data_ptr->tasklet; 00408 } 00409 00410 int8_t thread_tasklet_disconnect(bool send_cb) 00411 { 00412 int8_t status = -1; 00413 // check that module is initialized 00414 if (thread_tasklet_data_ptr != NULL) { 00415 if (thread_tasklet_data_ptr->nwk_if_id != INVALID_INTERFACE_ID) { 00416 status = arm_nwk_interface_down(thread_tasklet_data_ptr->nwk_if_id); 00417 thread_tasklet_data_ptr->nwk_if_id = INVALID_INTERFACE_ID; 00418 if (send_cb == true) { 00419 thread_tasklet_network_state_changed(MESH_DISCONNECTED); 00420 } 00421 } 00422 00423 // Clear callback, it will be set again in next connect 00424 thread_tasklet_data_ptr->mesh_api_cb = NULL; 00425 } 00426 return status; 00427 } 00428 00429 void thread_tasklet_init(void) 00430 { 00431 if (thread_tasklet_data_ptr == NULL) { 00432 thread_tasklet_data_ptr = ns_dyn_mem_alloc(sizeof(thread_tasklet_data_str_t)); 00433 thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_CREATED; 00434 thread_tasklet_data_ptr->nwk_if_id = INVALID_INTERFACE_ID; 00435 } 00436 } 00437 00438 int8_t thread_tasklet_network_init(int8_t device_id) 00439 { 00440 // TODO, read interface name from configuration 00441 mac_description_storage_size_t storage_sizes; 00442 storage_sizes.device_decription_table_size = 32; 00443 storage_sizes.key_description_table_size = 6; 00444 storage_sizes.key_lookup_size = 1; 00445 storage_sizes.key_usage_size = 3; 00446 mac_api_t *api = ns_sw_mac_create(device_id, &storage_sizes); 00447 return arm_nwk_interface_lowpan_init(api, INTERFACE_NAME); 00448 } 00449 00450 void thread_tasklet_device_config_set(uint8_t *eui64, char *pskd) 00451 { 00452 (void) pskd; // this parameter is delivered via yotta configuration 00453 memcpy(device_configuration.eui64, eui64, 8); 00454 } 00455 00456 int8_t thread_tasklet_data_poll_rate_set(uint32_t timeout) 00457 { 00458 int8_t status = -1; 00459 if (thread_tasklet_data_ptr) { 00460 if (timeout != 0) { 00461 status = arm_nwk_host_mode_set(thread_tasklet_data_ptr->nwk_if_id, NET_HOST_SLOW_POLL_MODE, timeout); 00462 } else { 00463 status = arm_nwk_host_mode_set(thread_tasklet_data_ptr->nwk_if_id, NET_HOST_RX_ON_IDLE, timeout); 00464 } 00465 } 00466 00467 return status; 00468 } 00469
Generated on Tue Jul 12 2022 12:28:56 by
