uint32_t pstorage_store(pstorage_handle_t * p_dest, uint8_t * p_src, pstorage_size_t size, pstorage_size_t offset) { VERIFY_MODULE_INITIALIZED(); NULL_PARAM_CHECK(p_src); NULL_PARAM_CHECK(p_dest); MODULE_ID_RANGE_CHECK(p_dest); BLOCK_ID_RANGE_CHECK(p_dest); SIZE_CHECK(p_dest, size); OFFSET_CHECK(p_dest, offset,size); // Verify word alignment. if ((!is_word_aligned(p_src)) || (!is_word_aligned((void *)(uint32_t)offset))) { return NRF_ERROR_INVALID_ADDR; } if ((!is_word_aligned((uint32_t *)p_dest->block_id))) { return NRF_ERROR_INVALID_ADDR; } return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset); }
uint32_t pstorage_load(uint8_t * p_dest, pstorage_handle_t * p_src, pstorage_size_t size, pstorage_size_t offset) { VERIFY_MODULE_INITIALIZED(); NULL_PARAM_CHECK(p_src); NULL_PARAM_CHECK(p_dest); MODULE_ID_RANGE_CHECK (p_src); BLOCK_ID_RANGE_CHECK(p_src); SIZE_CHECK(p_src,size); OFFSET_CHECK(p_src,offset,size); // Verify word alignment. if ((!is_word_aligned(p_dest)) || (!is_word_aligned((void *)(uint32_t)offset))) { return NRF_ERROR_INVALID_ADDR; } memcpy(p_dest, (((uint8_t *)p_src->block_id) + offset), size); app_notify(p_src, p_dest, PSTORAGE_LOAD_OP_CODE, size, NRF_SUCCESS); return NRF_SUCCESS; }
uint32_t pstorage_store(pstorage_handle_t * p_dest, uint8_t * p_src, pstorage_size_t size, pstorage_size_t offset) { VERIFY_MODULE_INITIALIZED(); NULL_PARAM_CHECK(p_src); NULL_PARAM_CHECK(p_dest); MODULE_ID_RANGE_CHECK(p_dest); BLOCK_ID_RANGE_CHECK(p_dest); SIZE_CHECK(p_dest, size); OFFSET_CHECK(p_dest, offset, size); // Verify word alignment. if ((!is_word_aligned(p_src)) || (!is_word_aligned((void *)(uint32_t)offset))) { return NRF_ERROR_INVALID_ADDR; } uint32_t storage_addr = p_dest->block_id + offset; uint32_t retval = ble_flash_block_write((uint32_t *)storage_addr, (uint32_t *)p_src, (size /sizeof(uint32_t))); app_notify(p_dest, p_src, PSTORAGE_STORE_OP_CODE, size, retval); return retval; }
uint32_t pstorage_store(pstorage_handle_t * p_dest, uint8_t * p_src, pstorage_size_t size, pstorage_size_t offset) { // Verify word alignment. if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset))) { return NRF_ERROR_INVALID_ADDR; } return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset); }
uint32_t app_gpiote_init(uint8_t max_users, void * p_buffer) { if (p_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } // Check that buffer is correctly aligned. if (!is_word_aligned(p_buffer)) { return NRF_ERROR_INVALID_PARAM; } // Initialize file globals. mp_users = (gpiote_user_t *)p_buffer; m_user_array_size = max_users; m_user_count = 0; m_enabled_users_mask = 0; memset(mp_users, 0, m_user_array_size * sizeof(gpiote_user_t)); // Initialize GPIOTE interrupt (will not be enabled until app_gpiote_user_enable() is called). NRF_GPIOTE->INTENCLR = 0xFFFFFFFF; NVIC_ClearPendingIRQ(GPIOTE_IRQn); NVIC_SetPriority(GPIOTE_IRQn, APP_IRQ_PRIORITY_HIGH); NVIC_EnableIRQ(GPIOTE_IRQn); return NRF_SUCCESS; }
ret_code_t fs_store(fs_config_t const * p_config, uint32_t const * p_addr, uint32_t const * const p_data, fs_length_t length_words) { if ((m_flags & FS_FLAG_INIT) == 0) { return NRF_ERROR_INVALID_STATE; } if (!check_config(p_config)) { return NRF_ERROR_FORBIDDEN; } if (!is_word_aligned(p_addr)) { return NRF_ERROR_INVALID_ADDR; } // Check that the erase operation is on pages owned by this user (configuration). if ((p_addr < p_config->p_start_addr) || ((p_addr + length_words) > p_config->p_end_addr)) { return NRF_ERROR_INVALID_ADDR; } return cmd_enqueue(p_config, FS_OP_STORE, p_addr, p_data, length_words); }
uint32_t app_gpiote_init(uint8_t max_users, void * p_buffer) { if (p_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } //Check that buffer is correctly aligned. if (!is_word_aligned(p_buffer)) { return NRF_ERROR_INVALID_PARAM; } //Initialize file globals. mp_users = (gpiote_user_t *)p_buffer; m_user_array_size = max_users; m_user_count = 0; m_enabled_users_mask = 0; memset(mp_users, 0, m_user_array_size * sizeof (gpiote_user_t)); (void)app_gpiote_enable_interrupts(); return NRF_SUCCESS; }
uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size) { uint32_t retval; VERIFY_MODULE_INITIALIZED(); NULL_PARAM_CHECK(p_dest); MODULE_ID_RANGE_CHECK(p_dest); BLOCK_ID_RANGE_CHECK(p_dest); if ((!is_word_aligned((uint32_t *)p_dest->block_id))) { return NRF_ERROR_INVALID_ADDR; } if ( !( ((p_dest->block_id - m_app_table[p_dest->module_id].base_id) % m_app_table[p_dest->module_id].block_size) == 0 ) ) { return NRF_ERROR_INVALID_PARAM; } retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL, size, 0); return retval; }
uint32_t app_gpiote_init(uint8_t max_users, void * p_buffer) { uint32_t ret_code = NRF_SUCCESS; if (p_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } // Check that buffer is correctly aligned. if (!is_word_aligned(p_buffer)) { return NRF_ERROR_INVALID_PARAM; } // Initialize file globals. mp_users = (gpiote_user_t *)p_buffer; m_user_array_size = max_users; m_user_count = 0; m_pins = 0; memset(mp_users, 0, m_user_array_size * sizeof(gpiote_user_t)); if (nrf_drv_gpiote_is_init()==false) { ret_code = nrf_drv_gpiote_init(); } return ret_code; }
uint32_t app_timer_init(uint32_t prescaler, uint8_t op_queues_size, void * p_buffer, app_timer_evt_schedule_func_t evt_schedule_func) { int i; // Check that buffer is correctly aligned if (!is_word_aligned(p_buffer)) { return NRF_ERROR_INVALID_PARAM; } // Check for NULL buffer if (p_buffer == NULL) { mp_users = NULL; return NRF_ERROR_INVALID_PARAM; } // Stop RTC to prevent any running timers from expiring (in case of reinitialization) rtc1_stop(); m_evt_schedule_func = evt_schedule_func; // Initialize users array m_user_array_size = APP_TIMER_INT_LEVELS; mp_users = p_buffer; // Skip user array p_buffer = &((uint8_t *)p_buffer)[APP_TIMER_INT_LEVELS * sizeof(timer_user_t)]; // Initialize operation queues for (i = 0; i < APP_TIMER_INT_LEVELS; i++) { timer_user_t * p_user = &mp_users[i]; p_user->first = 0; p_user->last = 0; p_user->user_op_queue_size = op_queues_size; p_user->p_user_op_queue = p_buffer; // Skip operation queue p_buffer = &((uint8_t *)p_buffer)[op_queues_size * sizeof(timer_user_op_t)]; } mp_timer_id_head = NULL; m_ticks_elapsed_q_read_ind = 0; m_ticks_elapsed_q_write_ind = 0; NVIC_ClearPendingIRQ(SWI_IRQn); NVIC_SetPriority(SWI_IRQn, SWI_IRQ_PRI); NVIC_EnableIRQ(SWI_IRQn); rtc1_init(prescaler); m_ticks_latest = rtc1_counter_get(); return NRF_SUCCESS; }
/** * @brief API to store data persistently. */ uint32_t pstorage_raw_store(pstorage_handle_t * p_dest, uint8_t * p_src, uint32_t size, uint32_t offset) { VERIFY_MODULE_INITIALIZED(); NULL_PARAM_CHECK(p_src); NULL_PARAM_CHECK(p_dest); MODULE_RAW_ID_RANGE_CHECK(p_dest); // Verify word alignment. if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset))) { return NRF_ERROR_INVALID_ADDR; } return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset); }
uint32_t softdevice_handler_init(nrf_clock_lf_cfg_t * p_clock_lf_cfg, void * p_ble_evt_buffer, uint16_t ble_evt_buffer_size, softdevice_evt_schedule_func_t evt_schedule_func) { uint32_t err_code; SD_HANDLER_LOG_INIT(); // Save configuration. #if defined (BLE_STACK_SUPPORT_REQD) // Check that buffer is not NULL. if (p_ble_evt_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } // Check that buffer is correctly aligned. if (!is_word_aligned(p_ble_evt_buffer)) { return NRF_ERROR_INVALID_PARAM; } mp_ble_evt_buffer = (uint8_t *)p_ble_evt_buffer; m_ble_evt_buffer_size = ble_evt_buffer_size; #else // The variables p_ble_evt_buffer and ble_evt_buffer_size is not needed if BLE Stack support // is not required. UNUSED_PARAMETER(p_ble_evt_buffer); UNUSED_PARAMETER(ble_evt_buffer_size); #endif m_evt_schedule_func = evt_schedule_func; // Initialize SoftDevice. #if defined(S212) || defined(S332) err_code = sd_softdevice_enable(p_clock_lf_cfg, softdevice_fault_handler, ANT_LICENSE_KEY); #else err_code = sd_softdevice_enable(p_clock_lf_cfg, softdevice_fault_handler); #endif if (err_code != NRF_SUCCESS) { return err_code; } m_softdevice_enabled = true; // Enable BLE event interrupt (interrupt priority has already been set by the stack). #ifdef SOFTDEVICE_PRESENT return sd_nvic_EnableIRQ((IRQn_Type)SOFTDEVICE_EVT_IRQ); #else //In case of Serialization NVIC must be accessed directly. NVIC_EnableIRQ(SOFTDEVICE_EVT_IRQ); return NRF_SUCCESS; #endif }
uint32_t softdevice_handler_init(nrf_clock_lfclksrc_t clock_source, void * p_ble_evt_buffer, uint16_t ble_evt_buffer_size, softdevice_evt_schedule_func_t evt_schedule_func) { uint32_t err_code; // Save configuration. #if defined (BLE_STACK_SUPPORT_REQD) // Check that buffer is not NULL. if (p_ble_evt_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } // Check that buffer is correctly aligned. if (!is_word_aligned(p_ble_evt_buffer)) { return NRF_ERROR_INVALID_PARAM; } mp_ble_evt_buffer = (uint8_t *)p_ble_evt_buffer; m_ble_evt_buffer_size = ble_evt_buffer_size; #else // The variables p_ble_evt_buffer and ble_evt_buffer_size is not needed if BLE Stack support // is not required. UNUSED_PARAMETER(p_ble_evt_buffer); UNUSED_PARAMETER(ble_evt_buffer_size); #endif m_evt_schedule_func = evt_schedule_func; //Enabling FPU for SoftDevice #ifdef S132 SCB->CPACR |= (3UL << 20) | (3UL << 22); __DSB(); __ISB(); #endif // Initialize SoftDevice. err_code = sd_softdevice_enable(clock_source, softdevice_assertion_handler); if (err_code != NRF_SUCCESS) { return err_code; } #ifdef S132 SCB->CPACR = 0; __DSB(); __ISB(); #endif m_softdevice_enabled = true; // Enable BLE event interrupt (interrupt priority has already been set by the stack). return sd_nvic_EnableIRQ(SOFTDEVICE_EVT_IRQ); }
uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) { uint32_t err_code; uint32_t data_length; uint8_t * p_data; if (p_packet == NULL) { return NRF_ERROR_NULL; } // Check pointer alignment. if (!is_word_aligned(p_packet->p_data_packet)) { // The p_data_packet is not word aligned address. return NRF_ERROR_INVALID_ADDR; } switch (m_dfu_state) { case DFU_STATE_RDY: // Fall-through. case DFU_STATE_RX_INIT_PKT: m_dfu_state = DFU_STATE_RX_DATA_PKT; // Fall-through. case DFU_STATE_RX_DATA_PKT: data_length = p_packet->packet_length * sizeof(uint32_t); if ((uint32_t)(m_received_data + data_length) > m_image_size) { // The caller is trying to write more bytes into the flash than the size provided to // the dfu_image_size_set function. return NRF_ERROR_DATA_SIZE; } p_data = (uint8_t *)p_packet->p_data_packet; err_code = pstorage_raw_store(&m_storage_handle_app, p_data, data_length, m_received_data); if (err_code != NRF_SUCCESS) { return err_code; } m_received_data += data_length; break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) { assert(mr.word_size() > 0, "Error"); assert(_ct->is_aligned(mr.start()), "mr.start() should be card aligned"); // mr.end() may not necessarily be card aligned. jbyte* cur_entry = _ct->byte_for(mr.last()); const jbyte* limit = _ct->byte_for(mr.start()); HeapWord* end_of_non_clean = mr.end(); HeapWord* start_of_non_clean = end_of_non_clean; while (cur_entry >= limit) { HeapWord* cur_hw = _ct->addr_for(cur_entry); if ((*cur_entry != CardTableRS::clean_card_val()) && clear_card(cur_entry)) { // Continue the dirty range by opening the // dirty window one card to the left. start_of_non_clean = cur_hw; } else { // We hit a "clean" card; process any non-empty // "dirty" range accumulated so far. if (start_of_non_clean < end_of_non_clean) { const MemRegion mrd(start_of_non_clean, end_of_non_clean); _dirty_card_closure->do_MemRegion(mrd); } // fast forward through potential continuous whole-word range of clean cards beginning at a word-boundary if (is_word_aligned(cur_entry)) { jbyte* cur_row = cur_entry - BytesPerWord; while (cur_row >= limit && *((intptr_t*)cur_row) == CardTableRS::clean_card_row()) { cur_row -= BytesPerWord; } cur_entry = cur_row + BytesPerWord; cur_hw = _ct->addr_for(cur_entry); } // Reset the dirty window, while continuing to look // for the next dirty card that will start a // new dirty window. end_of_non_clean = cur_hw; start_of_non_clean = cur_hw; } // Note that "cur_entry" leads "start_of_non_clean" in // its leftward excursion after this point // in the loop and, when we hit the left end of "mr", // will point off of the left end of the card-table // for "mr". cur_entry--; } // If the first card of "mr" was dirty, we will have // been left with a dirty window, co-initial with "mr", // which we now process. if (start_of_non_clean < end_of_non_clean) { const MemRegion mrd(start_of_non_clean, end_of_non_clean); _dirty_card_closure->do_MemRegion(mrd); } }
uint32_t softdevice_handler_init(nrf_clock_lfclksrc_t clock_source, void * p_evt_buffer, uint16_t evt_buffer_size, softdevice_evt_schedule_func_t evt_schedule_func) { uint32_t err_code; // Save configuration. #if defined (BLE_STACK_SUPPORT_REQD) || defined (ANT_STACK_SUPPORT_REQD) // Check that buffer is not NULL. if (p_evt_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } // Check that buffer is correctly aligned. if (!is_word_aligned(p_evt_buffer)) { return NRF_ERROR_INVALID_PARAM; } m_evt_buffer = (uint8_t *)p_evt_buffer; #else // The variable p_evt_buffer is not needed if neither BLE Stack nor ANT stack support is // required. UNUSED_PARAMETER(p_evt_buffer); #endif #if defined (BLE_STACK_SUPPORT_REQD) m_ble_evt_buffer_size = evt_buffer_size; #else // The variable evt_buffer_size is not needed if BLE Stack support is NOT required. UNUSED_PARAMETER(evt_buffer_size); #endif m_evt_schedule_func = evt_schedule_func; // Initialize SoftDevice. err_code = sd_softdevice_enable(clock_source, softdevice_assertion_handler); if (err_code != NRF_SUCCESS) { return err_code; } m_softdevice_enabled = true; // Enable BLE event interrupt (interrupt priority has already been set by the stack). return sd_nvic_EnableIRQ(SWI2_IRQn); }
uint32_t app_timer_init(uint32_t prescaler, uint8_t op_queue_size, void * p_buffer, app_timer_evt_schedule_func_t evt_schedule_func) { // Check that buffer is correctly aligned if (!is_word_aligned(p_buffer)) { return NRF_ERROR_INVALID_PARAM; } // Check for NULL buffer if (p_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } // Stop RTC to prevent any running timers from expiring (in case of reinitialization) rtc1_stop(); m_evt_schedule_func = evt_schedule_func; // Initialize operation queue m_op_queue.first = 0; m_op_queue.last = 0; m_op_queue.size = op_queue_size; m_op_queue.p_user_op_queue = p_buffer; mp_timer_id_head = NULL; m_ticks_elapsed_q_read_ind = 0; m_ticks_elapsed_q_write_ind = 0; #if APP_TIMER_WITH_PROFILER m_max_user_op_queue_utilization = 0; #endif NVIC_ClearPendingIRQ(SWI_IRQn); NVIC_SetPriority(SWI_IRQn, SWI_IRQ_PRI); NVIC_EnableIRQ(SWI_IRQn); rtc1_init(prescaler); m_ticks_latest = rtc1_counter_get(); return NRF_SUCCESS; }
uint32_t app_sched_init(uint16_t event_size, uint16_t queue_size, void * p_event_buffer) { uint16_t data_start_index = (queue_size + 1) * sizeof(event_header_t); // Check that buffer is correctly aligned if (!is_word_aligned(p_event_buffer)) { return NRF_ERROR_INVALID_PARAM; } // Initialize event scheduler m_queue_event_headers = (event_header_t*)p_event_buffer; m_queue_event_data = &((uint8_t *)p_event_buffer)[data_start_index]; m_queue_end_index = 0; m_queue_start_index = 0; m_queue_event_size = event_size; m_queue_size = queue_size; return NRF_SUCCESS; }
uint32_t app_timer_init(uint32_t prescaler, uint8_t max_timers, uint8_t op_queues_size, void * p_buffer, app_timer_evt_schedule_func_t evt_schedule_func) { int i; // Check that buffer is correctly aligned if (!is_word_aligned(p_buffer)) { return NRF_ERROR_INVALID_PARAM; } // Check for NULL buffer if (p_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } // Stop RTC to prevent any running timers from expiring (in case of reinitialization) rtc1_stop(); m_evt_schedule_func = evt_schedule_func; // Initialize timer node array m_node_array_size = max_timers; mp_nodes = p_buffer; for (i = 0; i < max_timers; i++) { mp_nodes[i].state = STATE_FREE; mp_nodes[i].is_running = false; } // Skip timer node array p_buffer = &((uint8_t *)p_buffer)[max_timers * sizeof(timer_node_t)]; // Initialize users array m_user_array_size = APP_TIMER_INT_LEVELS; mp_users = p_buffer; // Skip user array p_buffer = &((uint8_t *)p_buffer)[APP_TIMER_INT_LEVELS * sizeof(timer_user_t)]; // Initialize operation queues for (i = 0; i < APP_TIMER_INT_LEVELS; i++) { timer_user_t * p_user = &mp_users[i]; p_user->first = 0; p_user->last = 0; p_user->user_op_queue_size = op_queues_size; p_user->p_user_op_queue = p_buffer; // Skip operation queue p_buffer = &((uint8_t *)p_buffer)[op_queues_size * sizeof(timer_user_op_t)]; } m_timer_id_head = TIMER_NULL; m_ticks_elapsed_q_read_ind = 0; m_ticks_elapsed_q_write_ind = 0; /* NVIC_ClearPendingIRQ(SWI0_IRQn); NVIC_SetPriority(SWI0_IRQn, SWI0_IRQ_PRI); NVIC_EnableIRQ(SWI0_IRQn); */ /*--khai-- : temporarily use SWI1 for app_timer so that conflict with event_handler won't occur*/ NVIC_ClearPendingIRQ(SWI1_IRQn); NVIC_SetPriority(SWI1_IRQn, SWI0_IRQ_PRI); NVIC_EnableIRQ(SWI1_IRQn); rtc1_init(prescaler); m_ticks_latest = rtc1_counter_get(); return NRF_SUCCESS; }
uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) { uint32_t data_length; uint32_t err_code; uint32_t * p_data; if (p_packet == NULL) { return NRF_ERROR_NULL; } // Check pointer alignment. if (!is_word_aligned(p_packet->params.data_packet.p_data_packet)) { // The p_data_packet is not word aligned address. return NRF_ERROR_INVALID_ADDR; } switch (m_dfu_state) { case DFU_STATE_RDY: case DFU_STATE_RX_INIT_PKT: return NRF_ERROR_INVALID_STATE; case DFU_STATE_RX_DATA_PKT: data_length = p_packet->params.data_packet.packet_length * sizeof(uint32_t); if ((m_data_received + data_length) > m_image_size) { // The caller is trying to write more bytes into the flash than the size provided to // the dfu_image_size_set function. This is treated as a serious error condition and // an unrecoverable one. Hence point the variable mp_app_write_address to the top of // the flash area. This will ensure that all future application data packet writes // will be blocked because of the above check. m_data_received = 0xFFFFFFFF; return NRF_ERROR_DATA_SIZE; } // Valid peer activity detected. Hence restart the DFU timer. err_code = dfu_timer_restart(); if (err_code != NRF_SUCCESS) { return err_code; } p_data = (uint32_t *)p_packet->params.data_packet.p_data_packet; err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received); if (err_code != NRF_SUCCESS) { return err_code; } m_data_received += data_length; if (m_data_received != m_image_size) { // The entire image is not received yet. More data is expected. err_code = NRF_ERROR_INVALID_LENGTH; } else { // The entire image has been received. Return NRF_SUCCESS. err_code = NRF_SUCCESS; } break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
uint32_t softdevice_handler_init(nrf_clock_lfclksrc_t clock_source, void * p_evt_buffer, uint16_t evt_buffer_size, softdevice_evt_schedule_func_t evt_schedule_func) { uint32_t err_code; // Save configuration. #if defined (BLE_STACK_SUPPORT_REQD) || defined (ANT_STACK_SUPPORT_REQD) // Check that buffer is not NULL. if (p_evt_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } // Check that buffer is correctly aligned. if (!is_word_aligned(p_evt_buffer)) { return NRF_ERROR_INVALID_PARAM; } m_evt_buffer = (uint8_t *)p_evt_buffer; #else // The variable p_evt_buffer is not needed if neither BLE Stack nor ANT stack support is // required. UNUSED_PARAMETER(p_evt_buffer); #endif #if defined (BLE_STACK_SUPPORT_REQD) m_ble_evt_buffer_size = evt_buffer_size; #else // The variable evt_buffer_size is not needed if BLE Stack support is NOT required. UNUSED_PARAMETER(evt_buffer_size); #endif m_evt_schedule_func = evt_schedule_func; // Initialize SoftDevice. err_code = sd_softdevice_enable(clock_source, softdevice_assertion_handler); if (err_code != NRF_SUCCESS) { return err_code; } /** * Using this call, the application can select whether to include the * Service Changed characteristic in the GATT Server. The default in all * previous releases has been to include the Service Changed characteristic, * but this affects how GATT clients behave. Specifically, it requires * clients to subscribe to this attribute and not to cache attribute handles * between connections unless the devices are bonded. If the application * does not need to change the structure of the GATT server attributes at * runtime this adds unnecessary complexity to the interaction with peer * clients. If the SoftDevice is enabled with the Service Changed * Characteristics turned off, then clients are allowed to cache attribute * handles making applications simpler on both sides. */ ble_enable_params_t enableParams = { .gatts_enable_params = { .service_changed = 0 } }; if ((err_code = sd_ble_enable(&enableParams)) != NRF_SUCCESS) { return err_code; } ble_gap_addr_t addr; if ((err_code = sd_ble_gap_address_get(&addr)) != NRF_SUCCESS) { return err_code; } if ((err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr)) != NRF_SUCCESS) { return err_code; } m_softdevice_enabled = true; // Enable BLE event interrupt (interrupt priority has already been set by the stack). return sd_nvic_EnableIRQ(SWI2_IRQn); }
uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) { uint32_t data_length; uint32_t err_code; uint32_t * p_data; VERIFY_PARAM_NOT_NULL(p_packet); // Check pointer alignment. if (!is_word_aligned(p_packet->params.data_packet.p_data_packet)) { // The p_data_packet is not word aligned address. return NRF_ERROR_INVALID_ADDR; } switch (m_dfu_state) { case DFU_STATE_RDY: case DFU_STATE_RX_INIT_PKT: return NRF_ERROR_INVALID_STATE; case DFU_STATE_RX_DATA_PKT: data_length = p_packet->params.data_packet.packet_length * sizeof(uint32_t); if ((m_data_received + data_length) > m_image_size) { // The caller is trying to write more bytes into the flash than the size provided to // the dfu_image_size_set function. This is treated as a serious error condition and // an unrecoverable one. Hence point the variable mp_app_write_address to the top of // the flash area. This will ensure that all future application data packet writes // will be blocked because of the above check. m_data_received = 0xFFFFFFFF; return NRF_ERROR_DATA_SIZE; } // Valid peer activity detected. Hence restart the DFU timer. err_code = dfu_timer_restart(); VERIFY_SUCCESS(err_code); p_data = (uint32_t *)p_packet->params.data_packet.p_data_packet; // Do AES Decrption. dfu_aes_128_ofb_decrypt(p_data, data_length/sizeof(uint32_t), m_data_received); // Check the protected data before copying it and make sure its retain or update the data. uint32_t bootloader_position = m_data_received - m_start_packet.sd_image_size; for (int w = 0; w < data_length/sizeof(uint32_t); w++) { bootloader_position = bootloader_position + 4; if(m_start_packet.bl_image_size > 0 && (m_data_received > m_start_packet.sd_image_size) && (bootloader_position >= ((uint32_t)(&__start_protected_data) - m_uicr_bootloader_start_address))) { if(p_data[w] == 0x00000000) { p_data[w] = 0xFFFFFFFF; } else if(p_data[w] == 0xFFFFFFFF) p_data[w] = (uint32_t)(*((uint32_t *)(bootloader_position - 4 + m_uicr_bootloader_start_address))); } } err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received); VERIFY_SUCCESS(err_code); m_data_received += data_length; if (m_data_received != m_image_size) { // The entire image is not received yet. More data is expected. err_code = NRF_ERROR_INVALID_LENGTH; } else { // The entire image has been received. Return NRF_SUCCESS. err_code = NRF_SUCCESS; } break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) { uint32_t err_code; uint32_t data_length; uint8_t * p_data; if (p_packet == NULL) { return NRF_ERROR_NULL; } // Check pointer alignment. if (!is_word_aligned(p_packet->p_data_packet)) { // The p_data_packet is not word aligned address. return NRF_ERROR_INVALID_ADDR; } switch (m_dfu_state) { case DFU_STATE_RDY: // Fall-through. case DFU_STATE_RX_INIT_PKT: m_dfu_state = DFU_STATE_RX_DATA_PKT; // Fall-through. case DFU_STATE_RX_DATA_PKT: data_length = p_packet->packet_length * sizeof(uint32_t); if ((uint32_t)(m_received_data + data_length) > m_image_size) { // The caller is trying to write more bytes into the flash than the size provided to // the dfu_image_size_set function. return NRF_ERROR_DATA_SIZE; } p_data = (uint8_t *)p_packet->p_data_packet; err_code = pstorage_raw_store(&m_storage_handle_app, p_data, data_length, m_received_data); if (err_code != NRF_SUCCESS) { return err_code; } m_received_data += data_length; // SINGLEBANK PATCH: added so that it will return NRF_ERROR_INVALID_LENGTH instead of NRF_SUCCESS if the full image is not received. if (m_received_data != m_image_size) { // The entire image is not received yet. More data is expected. err_code = NRF_ERROR_INVALID_LENGTH; } else { // The entire image has been received. Return NRF_SUCCESS. err_code = NRF_SUCCESS; } //PATCH END break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
uint32_t pstorage_update(pstorage_handle_t * p_dest, uint8_t * p_src, pstorage_size_t size, pstorage_size_t offset) { uint32_t *p_swap_addr = (uint32_t *)PSTORAGE_SWAP_ADDR; uint32_t *p_page_addr1 = (uint32_t *) PAGE_BASE_ADDR(p_dest->block_id + offset); #ifdef SUPPORT_MODULES_LARGER_THAN_PAGE uint32_t *p_page_addr2 = (uint32_t *) PAGE_BASE_ADDR(p_dest->block_id + offset + size-1); #endif uint16_t head_word_count = offset/sizeof(uint32_t); uint16_t body_word_count = size/sizeof(uint32_t); uint16_t tail_word_count; uint32_t retval; VERIFY_MODULE_INITIALIZED(); NULL_PARAM_CHECK(p_src); NULL_PARAM_CHECK(p_dest); MODULE_ID_RANGE_CHECK(p_dest); BLOCK_ID_RANGE_CHECK(p_dest); SIZE_CHECK(p_dest, size); OFFSET_CHECK(p_dest, offset, size); // Verify word alignment. if ((!is_word_aligned(p_src)) || (!is_word_aligned((void *)(uint32_t)offset))) { return NRF_ERROR_INVALID_ADDR; } // erase swap page (void) ble_flash_page_erase(PSTORAGE_SWAP_ADDR / BLE_FLASH_PAGE_SIZE); #ifdef SUPPORT_MODULES_LARGER_THAN_PAGE if (p_page_addr1 == p_page_addr2) { #endif // tail is in the same page as head tail_word_count = BLE_FLASH_PAGE_SIZE/sizeof(uint32_t) - head_word_count - body_word_count; // copy of the head if (head_word_count) { retval = ble_flash_block_write(p_swap_addr, p_page_addr1, head_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } } // copy of the body retval = ble_flash_block_write(p_swap_addr+head_word_count, (uint32_t *)p_src, body_word_count); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // copy of the tail if (tail_word_count) { retval = ble_flash_block_write(p_swap_addr+head_word_count+body_word_count, p_page_addr1+head_word_count+body_word_count, tail_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } } // erase active page (void) ble_flash_page_erase((uint32_t)p_page_addr1 / BLE_FLASH_PAGE_SIZE); // restore updated page retval = ble_flash_block_write(p_page_addr1, p_swap_addr, BLE_FLASH_PAGE_SIZE/sizeof(uint32_t)); #ifdef SUPPORT_MODULES_LARGER_THAN_PAGE } else { // tail is in NOT in the same page as head - need to swap twice uint16_t body1_word_count = BLE_FLASH_PAGE_SIZE/sizeof(uint32_t) - head_word_count; uint16_t body2_word_count = body_word_count - body1_word_count; tail_word_count = BLE_FLASH_PAGE_SIZE/sizeof(uint32_t) - body2_word_count; // copy head retval = ble_flash_block_write(p_swap_addr, p_page_addr1, head_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // copy body1 retval = ble_flash_block_write(p_swap_addr, (uint32_t *)p_src, body1_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // erase active page (void) ble_flash_page_erase((uint32_t)p_page_addr1 / BLE_FLASH_PAGE_SIZE); // restore updated page1 retval = ble_flash_block_write(p_page_addr1, p_swap_addr, BLE_FLASH_PAGE_SIZE/sizeof(uint32_t)); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // erase swap page (void) ble_flash_page_erase(PSTORAGE_SWAP_ADDR / BLE_FLASH_PAGE_SIZE); // copy body2 retval = ble_flash_block_write(p_swap_addr, (uint32_t *)p_src + body1_word_count, body2_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // copy tail retval = ble_flash_block_write(p_swap_addr, p_page_addr2+body2_word_count, tail_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // erase active page (void) ble_flash_page_erase((uint32_t)p_page_addr2 / BLE_FLASH_PAGE_SIZE); // restore updated page2 retval = ble_flash_block_write(p_page_addr2, p_swap_addr, BLE_FLASH_PAGE_SIZE/sizeof(uint32_t)); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } } #endif app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; }