uint32_t mesh_flash_op_push(flash_op_type_t type, const flash_op_t* p_op) { if (mp_cb == NULL) { return NRF_ERROR_INVALID_STATE; } if (p_op == NULL) { return NRF_ERROR_NULL; } if (type == FLASH_OP_TYPE_WRITE) { if (!IS_WORD_ALIGNED(p_op->write.start_addr) || !IS_WORD_ALIGNED(p_op->write.p_data)) { return NRF_ERROR_INVALID_ADDR; } if (!IS_WORD_ALIGNED(p_op->write.length) || p_op->write.length == 0) { return NRF_ERROR_INVALID_LENGTH; } } else if (type == FLASH_OP_TYPE_ERASE) { if (!IS_PAGE_ALIGNED(p_op->erase.start_addr)) { return NRF_ERROR_INVALID_ADDR; } if (p_op->erase.length == 0) { return NRF_ERROR_INVALID_LENGTH; } } else { return NRF_ERROR_INVALID_PARAM; } operation_t op; op.type = type; memcpy(&op.operation, p_op, sizeof(flash_op_t)); return fifo_push(&m_flash_op_fifo, &op); }
void *memset(void *dest, int c, size_t n) { uint8_t *bdest = dest; if (n == 0) return dest; c &= 0xFF; while (n && !IS_WORD_ALIGNED(bdest)) { *bdest++ = c; --n; } if (n) return rflpc_memset_aligned_fast(bdest, c, n); return dest; }
void vexAllocSanityCheck ( void ) { vassert(temporary_first == &temporary[0]); vassert(temporary_last == &temporary[N_TEMPORARY_BYTES-1]); vassert(permanent_first == &permanent[0]); vassert(permanent_last == &permanent[N_PERMANENT_BYTES-1]); vassert(temporary_first <= temporary_curr); vassert(temporary_curr <= temporary_last); vassert(permanent_first <= permanent_curr); vassert(permanent_curr <= permanent_last); vassert(private_LibVEX_alloc_first <= private_LibVEX_alloc_curr); vassert(private_LibVEX_alloc_curr <= private_LibVEX_alloc_last); if (mode == VexAllocModeTEMP){ vassert(private_LibVEX_alloc_first == temporary_first); vassert(private_LibVEX_alloc_last == temporary_last); } else if (mode == VexAllocModePERM) { vassert(private_LibVEX_alloc_first == permanent_first); vassert(private_LibVEX_alloc_last == permanent_last); } else vassert(0); # define IS_WORD_ALIGNED(p) (0 == (((HWord)p) & (sizeof(HWord)-1))) vassert(sizeof(HWord) == 4 || sizeof(HWord) == 8); vassert(IS_WORD_ALIGNED(temporary_first)); vassert(IS_WORD_ALIGNED(temporary_curr)); vassert(IS_WORD_ALIGNED(temporary_last+1)); vassert(IS_WORD_ALIGNED(permanent_first)); vassert(IS_WORD_ALIGNED(permanent_curr)); vassert(IS_WORD_ALIGNED(permanent_last+1)); vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_first)); vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_curr)); vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_last+1)); # undef IS_WORD_ALIGNED }
static void ocamlpool_chunk_alloc(void) { ocamlpool_assert(ocamlpool_next_chunk_size > 1); void *block = caml_alloc_for_heap(ocamlpool_next_chunk_size * WORD_SIZE); abort_unless(block != NULL); size_t chunk_size = Chunk_size(block); ocamlpool_assert(IS_WORD_ALIGNED(chunk_size)); ocamlpool_color = caml_allocation_color(block); ocamlpool_allocated_chunks_counter += 1; size_t words = (chunk_size / WORD_SIZE); ocamlpool_root = (value)((value*)block + 1); /* Make it look like a well-formed string */ OCAMLPOOL_SET_HEADER(ocamlpool_root, words - 1, String_tag, ocamlpool_color); caml_add_to_heap(block); caml_allocated_words += words; }
CMemChunk* CMemChunk::New ( CChunkAllocator& aAllocator, RChunkPool& aChunkPool, TInt aNumBlocks , TInt aBlockSize ) { // allocates chunk on shared Heap using ::new operator // round of RMemCell & aBlockSize to the nearest word size. TInt memCellSize = WORD_ALIGN ( sizeof ( RMemCell ) ); TInt blockSize = WORD_ALIGN ( aBlockSize ); CMemChunk* chunk = new ( aNumBlocks * ( memCellSize + blockSize ), aAllocator ) CMemChunk ( aAllocator, aNumBlocks ); // In the complete memory allocated on shared heap; first bytes are of CMemChunk, // then start the memory required for RMemCell * NumBlocks and at the end contains // the actual data buffer. if ( chunk != NULL ) { // memory required for CMemChunk and for its parameters storage TUint8* chunkSize = ( ( TUint8* ) chunk ) + sizeof ( CMemChunk ); __ASSERT_DEBUG ( IS_WORD_ALIGNED ( chunkSize ), User::Invariant () ); // TODO Proper panic code // memory required for RMemCell and its parameters storage TUint8* dataBufStart = chunkSize + ( aNumBlocks * memCellSize ); // now place each RMemCell and its databuffer in the address specified for ( TInt i = 0; i < aNumBlocks ; i++ ) { // address assigned for RMemCell 'i' RMemCell* hdr = ( RMemCell* ) ( chunkSize + i * memCellSize ); // overloaded ::new, that makes in-place allocation of MemCell at specified address ( void ) new ( hdr ) RMemCell ( &aChunkPool, dataBufStart + ( i * aBlockSize ), aBlockSize ); // completed construction of a RMemCell. chunk->iQueue.Append ( hdr ); } } return chunk; }
static uint32_t bl_evt_handler(bl_evt_t* p_evt) { static bl_cmd_t rsp_cmd; bool respond = false; switch (p_evt->type) { case BL_EVT_TYPE_DFU_ABORT: bootloader_abort(p_evt->params.dfu.abort.reason); /* If bootloader abort returned, it means that the application * doesn't work, and we should return to the dfu operation. */ dfu_mesh_start(); break; case BL_EVT_TYPE_TX_RADIO: { mesh_packet_t* p_packet = NULL; if (!mesh_packet_acquire(&p_packet)) { return NRF_ERROR_NO_MEM; } mesh_packet_set_local_addr(p_packet); p_packet->header.type = BLE_PACKET_TYPE_ADV_NONCONN_IND; p_packet->header.length = DFU_PACKET_OVERHEAD + p_evt->params.tx.radio.length; ((ble_ad_t*) p_packet->payload)->adv_data_type = MESH_ADV_DATA_TYPE; ((ble_ad_t*) p_packet->payload)->data[0] = (MESH_UUID & 0xFF); ((ble_ad_t*) p_packet->payload)->data[1] = (MESH_UUID >> 8) & 0xFF; ((ble_ad_t*) p_packet->payload)->adv_data_length = DFU_PACKET_ADV_OVERHEAD + p_evt->params.tx.radio.length; memcpy(&p_packet->payload[4], p_evt->params.tx.radio.p_dfu_packet, p_evt->params.tx.radio.length); bool success = transport_tx(p_packet, p_evt->params.tx.radio.tx_slot, p_evt->params.tx.radio.tx_count, (tx_interval_type_t) p_evt->params.tx.radio.interval_type); mesh_packet_ref_count_dec(p_packet); if (!success) { return NRF_ERROR_INTERNAL; } break; } case BL_EVT_TYPE_TX_ABORT: transport_tx_abort(p_evt->params.tx.abort.tx_slot); break; case BL_EVT_TYPE_TX_SERIAL: { #ifdef RBC_MESH_SERIAL serial_evt_t serial_evt; serial_evt.opcode = SERIAL_EVT_OPCODE_DFU; memcpy(&serial_evt.params.dfu.packet, p_evt->params.tx.serial.p_dfu_packet, p_evt->params.tx.serial.length); serial_evt.length = SERIAL_PACKET_OVERHEAD + p_evt->params.tx.serial.length; if (!serial_handler_event_send(&serial_evt)) { return NRF_ERROR_INTERNAL; } break; #endif } case BL_EVT_TYPE_TIMER_SET: set_timeout(US_TO_RTC_TICKS(p_evt->params.timer.set.delay_us), TIMEOUT_ACTION_DFU_TIMEOUT); break; case BL_EVT_TYPE_DFU_NEW_FW: { stop_timeout(); __LOG("New FW event\n"); switch (p_evt->params.dfu.new_fw.fw_type) { case DFU_TYPE_APP: __LOG("\tAPP: %08x.%04x:%08x\n", (uint32_t) p_evt->params.dfu.new_fw.fwid.app.company_id, (uint32_t) p_evt->params.dfu.new_fw.fwid.app.app_id, (uint32_t) p_evt->params.dfu.new_fw.fwid.app.app_version); break; case DFU_TYPE_SD: __LOG("\tSD: %04x\n", (uint32_t) p_evt->params.dfu.new_fw.fwid.sd); break; case DFU_TYPE_BOOTLOADER: __LOG("\tBL: %02x:%02x\n", (uint32_t) p_evt->params.dfu.new_fw.fwid.bootloader.id, (uint32_t) p_evt->params.dfu.new_fw.fwid.bootloader.ver); break; default: break; } /* accept all new firmware, as the bootloader wouldn't run unless there's an actual reason for it. */ rsp_cmd.type = BL_CMD_TYPE_DFU_START_TARGET; rsp_cmd.params.dfu.start.target.p_bank_start = (uint32_t*) 0xFFFFFFFF; /* no banking */ rsp_cmd.params.dfu.start.target.type = p_evt->params.dfu.new_fw.fw_type; rsp_cmd.params.dfu.start.target.fwid = p_evt->params.dfu.new_fw.fwid; respond = true; } break; case BL_EVT_TYPE_BANK_AVAILABLE: __LOG("Bank:\n"); switch (p_evt->params.bank_available.bank_dfu_type) { case DFU_TYPE_APP: __LOG("\tAPP: %08x.%04x:%08x\n", (uint32_t) p_evt->params.bank_available.bank_fwid.app.company_id, (uint32_t) p_evt->params.bank_available.bank_fwid.app.app_id, (uint32_t) p_evt->params.bank_available.bank_fwid.app.app_version); break; case DFU_TYPE_SD: __LOG("\tSD: %04x\n", (uint32_t) p_evt->params.bank_available.bank_fwid.sd); break; case DFU_TYPE_BOOTLOADER: __LOG("\tBL: %02x:%02x\n", (uint32_t) p_evt->params.bank_available.bank_fwid.bootloader.id, (uint32_t) p_evt->params.bank_available.bank_fwid.bootloader.ver); break; default: break; } __LOG("\tLocation: 0x%x\n", p_evt->params.bank_available.p_bank_addr); __LOG("\tLength: 0x%x\n", p_evt->params.bank_available.bank_length); if (p_evt->params.bank_available.bank_dfu_type == DFU_TYPE_BOOTLOADER) { if (!dfu_mesh_app_is_valid()) { dfu_bank_flash(DFU_TYPE_BOOTLOADER); } } break; case BL_EVT_TYPE_DFU_REQ: { /* Always attempt to relay incoming transfers in BL mode. Will not abort ongoing transfers. */ if (p_evt->params.dfu.req.role == DFU_ROLE_RELAY) { stop_timeout(); bl_cmd_t relay_cmd; relay_cmd.type = BL_CMD_TYPE_DFU_START_RELAY; relay_cmd.params.dfu.start.relay.fwid = p_evt->params.dfu.req.fwid; relay_cmd.params.dfu.start.relay.type = p_evt->params.dfu.req.dfu_type; relay_cmd.params.dfu.start.relay.transaction_id = p_evt->params.dfu.req.transaction_id; bootloader_cmd_send(&relay_cmd); } } break; case BL_EVT_TYPE_DFU_START: set_timeout(TIMER_START_TIMEOUT, TIMEOUT_ACTION_DFU_ABORT); break; case BL_EVT_TYPE_DFU_DATA_SEGMENT_RX: __LOG("RX %u/%u\n", p_evt->params.dfu.data_segment.received_segment, p_evt->params.dfu.data_segment.total_segments); set_timeout(TIMER_DATA_TIMEOUT, TIMEOUT_ACTION_DFU_ABORT); break; case BL_EVT_TYPE_DFU_END: if (p_evt->params.dfu.end.dfu_type == DFU_TYPE_APP || p_evt->params.dfu.end.dfu_type == DFU_TYPE_SD) { /* attempt to reboot to app */ bootloader_abort(DFU_END_SUCCESS); } break; /* Defer the flash operations to an asynchronous handler. Doing it inline causes stack overflow, as the bootloader continues in the response callback. */ case BL_EVT_TYPE_FLASH_WRITE: { if (!IS_WORD_ALIGNED(p_evt->params.flash.write.start_addr) || !IS_WORD_ALIGNED(p_evt->params.flash.write.p_data)) { return NRF_ERROR_INVALID_ADDR; } if (!IS_WORD_ALIGNED(p_evt->params.flash.write.length)) { return NRF_ERROR_INVALID_LENGTH; } if ((p_evt->params.flash.write.start_addr + p_evt->params.flash.write.length) > NRF_UICR->BOOTLOADERADDR && p_evt->params.flash.write.start_addr < 0x3f800) { APP_ERROR_CHECK(NRF_ERROR_INVALID_ADDR); } flash_queue_entry_t queue_entry; queue_entry.type = FLASH_OP_TYPE_WRITE; memcpy(&queue_entry.op, &p_evt->params.flash, sizeof(flash_op_t)); if (fifo_push(&m_flash_fifo, &queue_entry) != NRF_SUCCESS) { __LOG(RTT_CTRL_TEXT_RED "FLASH FIFO FULL :( Increase the fifo size.\n"); return NRF_ERROR_NO_MEM; } NVIC_SetPendingIRQ(FLASH_HANDLER_IRQn); } break; case BL_EVT_TYPE_FLASH_ERASE: { flash_queue_entry_t queue_entry; queue_entry.type = FLASH_OP_TYPE_ERASE; memcpy(&queue_entry.op, &p_evt->params.flash, sizeof(flash_op_t)); if (fifo_push(&m_flash_fifo, &queue_entry) != NRF_SUCCESS) { __LOG(RTT_CTRL_TEXT_RED "FLASH FIFO FULL :( Increase the fifo size.\n"); return NRF_ERROR_NO_MEM; } NVIC_SetPendingIRQ(FLASH_HANDLER_IRQn); } break; default: return NRF_ERROR_NOT_SUPPORTED; } if (respond) { /* tail recursion */ return bl_cmd_handler(&rsp_cmd); } else { return NRF_SUCCESS; } }
/** Interrupt handling Flash operations. */ void FLASH_HANDLER_IRQHandler(void) { flash_queue_entry_t flash_entry; uint32_t op_count = 0; while (fifo_pop(&m_flash_fifo, &flash_entry) == NRF_SUCCESS) { op_count++; bl_cmd_t rsp_cmd; if (flash_entry.type == FLASH_OP_TYPE_WRITE) { APP_ERROR_CHECK_BOOL(IS_WORD_ALIGNED(flash_entry.op.write.start_addr)); APP_ERROR_CHECK_BOOL(IS_WORD_ALIGNED(flash_entry.op.write.length)); APP_ERROR_CHECK_BOOL(IS_WORD_ALIGNED(flash_entry.op.write.p_data)); __LOG("WRITING to 0x%x.(len %d)\n", flash_entry.op.write.start_addr, flash_entry.op.write.length); if (flash_entry.op.write.start_addr >= 0x20000000) { uint8_t* p_dst = ((uint8_t*) flash_entry.op.write.start_addr); for (uint32_t i = 0; i < flash_entry.op.write.length; ++i, p_dst++) { *p_dst = (*p_dst & flash_entry.op.write.p_data[i]); } } else { nrf_flash_store((uint32_t*) flash_entry.op.write.start_addr, flash_entry.op.write.p_data, flash_entry.op.write.length, 0); } rsp_cmd.type = BL_CMD_TYPE_FLASH_WRITE_COMPLETE; rsp_cmd.params.flash.write.p_data = flash_entry.op.write.p_data; } else { __LOG("ERASING 0x%x.\n", flash_entry.op.erase.start_addr); if (flash_entry.op.erase.start_addr >= 0x20000000) { memset((uint32_t*) flash_entry.op.erase.start_addr, 0xFF, flash_entry.op.erase.length); } else { nrf_flash_erase((uint32_t*) flash_entry.op.erase.start_addr, flash_entry.op.erase.length); } rsp_cmd.type = BL_CMD_TYPE_FLASH_ERASE_COMPLETE; rsp_cmd.params.flash.erase.p_dest = (uint32_t*) flash_entry.op.erase.start_addr; } bl_cmd_handler(&rsp_cmd); } if (op_count > 0) { bl_cmd_t idle_cmd; idle_cmd.type = BL_CMD_TYPE_FLASH_ALL_COMPLETE; bl_cmd_handler(&idle_cmd); } if (fifo_is_empty(&m_flash_fifo) && m_go_to_app) { bl_info_entry_t* p_segment_entry = bootloader_info_entry_get(BL_INFO_TYPE_SEGMENT_APP); bootloader_util_app_start(p_segment_entry->segment.start); } }
uint32_t dfu_evt_handler(bl_evt_t* p_evt) { __LOG("BL EVT (0x%x)\n", p_evt->type); switch (p_evt->type) { case BL_EVT_TYPE_ECHO: __LOG("\tEcho: %s\n", p_evt->params.echo.str); break; case BL_EVT_TYPE_DFU_ABORT: { __LOG("\tAbort event. Reason: 0x%x\n", p_evt->params.dfu.abort.reason); rbc_mesh_event_t evt; evt.type = RBC_MESH_EVENT_TYPE_DFU_END; evt.params.dfu.end.dfu_type = m_transfer_state.type; evt.params.dfu.end.role = m_transfer_state.role; evt.params.dfu.end.fwid = m_transfer_state.fwid; evt.params.dfu.end.end_reason = p_evt->params.dfu.abort.reason; memset(&m_transfer_state, 0, sizeof(dfu_transfer_state_t)); rbc_mesh_event_push(&evt); } break; case BL_EVT_TYPE_DFU_NEW_FW: { __LOG("\tNew firmware!\n"); rbc_mesh_event_t evt; evt.type = RBC_MESH_EVENT_TYPE_DFU_NEW_FW_AVAILABLE; evt.params.dfu.new_fw.dfu_type = p_evt->params.dfu.new_fw.fw_type; evt.params.dfu.new_fw.new_fwid = p_evt->params.dfu.new_fw.fwid; if (get_curr_fwid( p_evt->params.dfu.new_fw.fw_type, &evt.params.dfu.new_fw.current_fwid) == NRF_SUCCESS) { rbc_mesh_event_push(&evt); } } break; case BL_EVT_TYPE_DFU_REQ: { __LOG("\tSource/relay request!\n"); /* Forward to application */ rbc_mesh_event_t evt; switch (p_evt->params.dfu.req.role) { case DFU_ROLE_RELAY: evt.type = RBC_MESH_EVENT_TYPE_DFU_RELAY_REQ; evt.params.dfu.relay_req.dfu_type = p_evt->params.dfu.req.dfu_type; evt.params.dfu.relay_req.fwid = p_evt->params.dfu.req.fwid; evt.params.dfu.relay_req.authority = p_evt->params.dfu.req.dfu_type; break; case DFU_ROLE_SOURCE: evt.type = RBC_MESH_EVENT_TYPE_DFU_SOURCE_REQ; evt.params.dfu.source_req.dfu_type = p_evt->params.dfu.req.dfu_type; break; default: return NRF_ERROR_NOT_SUPPORTED; } rbc_mesh_event_push(&evt); } break; case BL_EVT_TYPE_DFU_START: { __LOG("\tDFU start\n"); if (p_evt->params.dfu.start.role == DFU_ROLE_TARGET) { m_transfer_state.state = DFU_STATE_TARGET; } else if (p_evt->params.dfu.start.role == DFU_ROLE_RELAY) { m_transfer_state.state = DFU_STATE_RELAY; } rbc_mesh_event_t evt; evt.type = RBC_MESH_EVENT_TYPE_DFU_START; evt.params.dfu.start.dfu_type = p_evt->params.dfu.start.dfu_type; evt.params.dfu.start.fwid = p_evt->params.dfu.start.fwid; evt.params.dfu.start.role = p_evt->params.dfu.start.role; rbc_mesh_event_push(&evt); m_timer_evt.cb = abort_timeout; return timer_sch_reschedule(&m_timer_evt, timer_now() + TIMER_START_TIMEOUT); } case BL_EVT_TYPE_DFU_DATA_SEGMENT_RX: m_transfer_state.data_progress = (uint8_t) ( ((uint32_t) p_evt->params.dfu.data_segment.received_segment * 100) / ((uint32_t) p_evt->params.dfu.data_segment.total_segments)); m_timer_evt.cb = abort_timeout; return timer_sch_reschedule(&m_timer_evt, timer_now() + TIMER_DATA_TIMEOUT); case BL_EVT_TYPE_DFU_END: { __LOG("\tDFU END!\n"); rbc_mesh_event_t evt; evt.type = RBC_MESH_EVENT_TYPE_DFU_END; evt.params.dfu.end.dfu_type = p_evt->params.dfu.end.dfu_type; evt.params.dfu.end.fwid = p_evt->params.dfu.end.fwid; evt.params.dfu.end.end_reason = DFU_END_SUCCESS; evt.params.dfu.end.role = p_evt->params.dfu.end.role; rbc_mesh_event_push(&evt); timer_sch_abort(&m_timer_evt); } break; case BL_EVT_TYPE_BANK_AVAILABLE: { __LOG("\tDFU BANK AVAILABLE\n"); rbc_mesh_event_t evt; evt.type = RBC_MESH_EVENT_TYPE_DFU_BANK_AVAILABLE; evt.params.dfu.bank.dfu_type = p_evt->params.bank_available.bank_dfu_type; evt.params.dfu.bank.fwid = p_evt->params.bank_available.bank_fwid; evt.params.dfu.bank.is_signed = p_evt->params.bank_available.is_signed; evt.params.dfu.bank.p_start_addr = p_evt->params.bank_available.p_bank_addr; rbc_mesh_event_push(&evt); } break; case BL_EVT_TYPE_FLASH_ERASE: { if (p_evt->params.flash.erase.start_addr & (NRF_FICR->CODEPAGESIZE - 1)) { return NRF_ERROR_INVALID_ADDR; } if (p_evt->params.flash.erase.length & (NRF_FICR->CODEPAGESIZE - 1)) { return NRF_ERROR_INVALID_LENGTH; } uint32_t error_code = mesh_flash_op_push(FLASH_OP_TYPE_ERASE, &p_evt->params.flash); if (error_code == NRF_SUCCESS) { __LOG("\tErase flash at: 0x%x (length %d)\n", p_evt->params.flash.erase.start_addr, p_evt->params.flash.erase.length); } return error_code; } case BL_EVT_TYPE_FLASH_WRITE: { if (!IS_WORD_ALIGNED(p_evt->params.flash.write.start_addr)) { return NRF_ERROR_INVALID_ADDR; } if (!IS_WORD_ALIGNED(p_evt->params.flash.write.length)) { return NRF_ERROR_INVALID_LENGTH; } uint32_t error_code = mesh_flash_op_push(FLASH_OP_TYPE_WRITE, &p_evt->params.flash); if (error_code == NRF_SUCCESS) { __LOG("\tWrite flash at: 0x%x (length %d)\n", p_evt->params.flash.write.start_addr, p_evt->params.flash.write.length); } return error_code; } case BL_EVT_TYPE_TX_RADIO: __LOG("\tRADIO TX! SLOT %d, count %d, interval: %s, handle: %x\n", p_evt->params.tx.radio.tx_slot, p_evt->params.tx.radio.tx_count, p_evt->params.tx.radio.interval_type == BL_RADIO_INTERVAL_TYPE_EXPONENTIAL ? "exponential" : "periodic", p_evt->params.tx.radio.p_dfu_packet->packet_type ); if (m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet) { mesh_packet_ref_count_dec(m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet); m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet = NULL; } if (mesh_packet_acquire(&m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet)) { uint32_t time_now = timer_now(); /* build packet */ mesh_packet_set_local_addr(m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet); m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->header.type = BLE_PACKET_TYPE_ADV_NONCONN_IND; m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->header.length = DFU_PACKET_OVERHEAD + p_evt->params.tx.radio.length; ((ble_ad_t*) m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->payload)->adv_data_type = MESH_ADV_DATA_TYPE; ((ble_ad_t*) m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->payload)->data[0] = (MESH_UUID & 0xFF); ((ble_ad_t*) m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->payload)->data[1] = (MESH_UUID >> 8) & 0xFF; ((ble_ad_t*) m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->payload)->adv_data_length = DFU_PACKET_ADV_OVERHEAD + p_evt->params.tx.radio.length; memcpy(&m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->payload[4], p_evt->params.tx.radio.p_dfu_packet, p_evt->params.tx.radio.length); /* fill other fields in the TX slot. */ m_tx_slots[p_evt->params.tx.radio.tx_slot].interval_type = p_evt->params.tx.radio.interval_type; m_tx_slots[p_evt->params.tx.radio.tx_slot].repeats = p_evt->params.tx.radio.tx_count; m_tx_slots[p_evt->params.tx.radio.tx_slot].tx_count = 0; m_tx_slots[p_evt->params.tx.radio.tx_slot].order_time = time_now + DFU_TX_TIMER_MARGIN_US + (rand_prng_get(&m_prng) & (DFU_TX_START_DELAY_MASK_US)); /* Fire away */ if (!m_tx_scheduled || TIMER_DIFF(m_tx_slots[p_evt->params.tx.radio.tx_slot].order_time, time_now) < TIMER_DIFF(m_tx_timer_evt.timestamp, time_now)) { m_tx_scheduled = true; timer_sch_reschedule(&m_tx_timer_evt, m_tx_slots[p_evt->params.tx.radio.tx_slot].order_time); } } else { return NRF_ERROR_NO_MEM;
void ocamlpool_set_next_chunk_size(size_t sz) { abort_unless(IS_WORD_ALIGNED(sz)); ocamlpool_next_chunk_size = sz; }