/** * An internal method that either spin waits if mode is set to SYNC_SPINWAIT * or puts the fiber to sleep if the mode is set to SYNC_SLEEP * * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP */ void MicroBitSerial::send(MicroBitSerialMode mode) { if(mode == SYNC_SPINWAIT) while(txBufferedSize() > 0); if(mode == SYNC_SLEEP) fiber_sleep(0); }
static void tx_fiber(void) { BT_DBG(""); /* FIXME: make periodic sending */ h5_send(sync_req, HCI_3WIRE_LINK_PKT, sizeof(sync_req)); while (true) { struct net_buf *buf; uint8_t type; BT_DBG("link_state %u", h5.link_state); switch (h5.link_state) { case UNINIT: /* FIXME: send sync */ fiber_sleep(10); break; case INIT: /* FIXME: send conf */ fiber_sleep(10); break; case ACTIVE: buf = nano_fifo_get(&h5.tx_queue, TICKS_UNLIMITED); type = h5_get_type(buf); h5_send(buf->data, type, buf->len); /* buf is dequeued from tx_queue and queued to unack * queue. */ nano_fifo_put(&h5.unack_queue, buf); unack_queue_len++; if (h5.retx_to) { fiber_delayed_start_cancel(h5.retx_to); } h5.retx_to = fiber_delayed_start(retx_stack, sizeof(retx_stack), retx_fiber, 0, 0, 7, 0, H5_TX_ACK_TIMEOUT); break; } } }
int tcp_tx(struct net_context *ctx, uint8_t *buf, size_t size) { struct net_buf *nbuf = NULL; uint8_t *ptr; int rc = 0; nbuf = ip_buf_get_tx(ctx); if (nbuf == NULL) { printk("[%s:%d] Unable to get buffer\n", __func__, __LINE__); return -EINVAL; } ptr = net_buf_add(nbuf, size); memcpy(ptr, buf, size); ip_buf_appdatalen(nbuf) = size; do { rc = net_send(nbuf); if (rc >= 0) { ip_buf_unref(nbuf); return 0; } switch (rc) { case -EINPROGRESS: printk("%s: no connection yet, try again\n", __func__); fiber_sleep(TCP_RETRY_TIMEOUT); break; case -EAGAIN: case -ECONNRESET: printk("%s: no connection, try again later\n", __func__); fiber_sleep(TCP_RETRY_TIMEOUT); break; default: printk("%s: sending %d bytes failed\n", __func__, size); ip_buf_unref(nbuf); return -EIO; } } while (1); return 0; }
int test_reload(box_function_ctx_t *ctx, const char *args, const char *args_end) { fiber_sleep(0.001); char tuple_buf[64]; char *tuple_end = tuple_buf; tuple_end = mp_encode_array(tuple_end, 1); tuple_end = mp_encode_uint(tuple_end, 2); struct tuple *tuple = box_tuple_new(box_tuple_format_default(), tuple_buf, tuple_end); return box_return_tuple(ctx, tuple); }
/* a fiber sleeps and times out, then reports through a fifo */ static void test_fiber_sleep(int timeout, int arg2) { int64_t orig_ticks = sys_tick_get(); TC_PRINT(" fiber sleeping for %d ticks\n", timeout); fiber_sleep(timeout); TC_PRINT(" fiber back from sleep\n"); if (!is_timeout_in_range(orig_ticks, timeout)) { return; } nano_fiber_sem_give(&reply_timeout); }
static void fiber_cond_basic() { struct fiber_cond *cond = fiber_cond_new(); int check = 0; struct fiber *f1 = fiber_new("f1", fiber_cond_basic_f); assert(f1 != NULL); fiber_start(f1, cond, &check); fiber_set_joinable(f1, true); struct fiber *f2 = fiber_new("f2", fiber_cond_basic_f); assert(f2 != NULL); fiber_start(f2, cond, &check); fiber_set_joinable(f2, true); /* check timeout */ fiber_sleep(0.0); fiber_sleep(0.0); /* Wake up the first fiber */ fiber_cond_signal(cond); fiber_sleep(0.0); /* Wake ip the second fiber */ fiber_cond_signal(cond); fiber_sleep(0.0); /* Check that fiber scheduling is fair */ is(check, 2, "order"); fiber_cond_broadcast(cond); fiber_sleep(0.0); fiber_join(f1); fiber_join(f2); fiber_cond_delete(cond); }
//% help=basic/show-string //% weight=87 blockGap=8 //% block="show|string %text" icon="\uf031" //% async //% blockId=device_print_message void showString(StringData *text, int interval = 150) { if (interval < 0) return; ManagedString s(text); int l = s.length(); if (l == 0) { uBit.display.clear(); fiber_sleep(interval * 5); } else if (l > 1) { uBit.display.scroll(s, interval); } else { uBit.display.print(s.charAt(0), interval * 5); } }
static void errno_fiber(int n, int my_errno) { errno = my_errno; printk("fiber %d, errno before sleep: %x\n", n, errno); fiber_sleep(3 - n); if (errno == my_errno) { result[n].pass = 1; } printk("fiber %d, errno after sleep: %x\n", n, errno); nano_fiber_fifo_put(&fifo, &result[n]); }
//% help=pins/analog-pitch weight=14 async void analogPitch(int frequency, int ms) { if (pitchPin == NULL) return; if (frequency <= 0) { pitchPin->setAnalogValue(0); } else { pitchPin->setAnalogValue(512); pitchPin->setAnalogPeriodUs(1000000/frequency); } if (ms > 0) { fiber_sleep(ms); pitchPin->setAnalogValue(0); // TODO why do we use wait_ms() here? it's a busy wait I think wait_ms(5); } }
inline bool wait_for_data() { m_mutex.lock(); bool success = false; // Wait while the queue is empty and this queue is alive while(m_queue.empty() && m_alive) { sleeping++; fiber_sleep(); sleeping--; } // An element has been added or a signal was raised if(!m_queue.empty()) { success = true; } m_mutex.unlock(); return success; }
/** * Blocks until an element is available in the queue * or until stop_blocking() is called. * The return value is a pair of <T value, bool success> * If "success" if set, then "value" is valid and * is an element popped from the queue. * If "success" is false, stop_blocking() was called * and the queue has been destroyed. */ inline std::pair<T, bool> dequeue() { m_mutex.lock(); T elem = T(); bool success = false; // Wait while the queue is empty and this queue is alive while(m_queue.empty() && m_alive) { sleeping++; fiber_sleep(); sleeping--; } // An element has been added or a signal was raised if(!m_queue.empty()) { success = true; elem = m_queue.front(); m_queue.pop_front(); } m_mutex.unlock(); return std::make_pair(elem, success); }
static void test_fiber(int arg1, int arg2) { uint32_t start_tick; uint32_t end_tick; nano_fiber_sem_take(&test_fiber_sem, TICKS_UNLIMITED); TC_PRINT("Testing normal expiration of fiber_sleep()\n"); align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); end_tick = sys_tick_get_32(); if (end_tick != start_tick + ONE_SECOND) { TC_ERROR(" *** fiber_sleep() slept for %d ticks not %d.", end_tick - start_tick, ONE_SECOND); return; } TC_PRINT("Testing fiber_sleep() + fiber_fiber_wakeup()\n"); nano_fiber_sem_give(&helper_fiber_sem); /* Activate helper fiber */ align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); end_tick = sys_tick_get_32(); if (end_tick > start_tick) { TC_ERROR(" *** fiber_fiber_wakeup() took too long (%d ticks)\n", end_tick - start_tick); return; } TC_PRINT("Testing fiber_sleep() + isr_fiber_wakeup()\n"); nano_fiber_sem_give(&helper_fiber_sem); /* Activate helper fiber */ align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); end_tick = sys_tick_get_32(); if (end_tick > start_tick) { TC_ERROR(" *** isr_fiber_wakeup() took too long (%d ticks)\n", end_tick - start_tick); return; } TC_PRINT("Testing fiber_sleep() + task_fiber_wakeup()\n"); nano_task_sem_give(&task_sem); /* Activate task */ align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); /* Task will execute */ end_tick = sys_tick_get_32(); if (end_tick > start_tick) { TC_ERROR(" *** task_fiber_wakeup() took too long (%d ticks)\n", end_tick - start_tick); return; } test_failure = false; }
/* a fiber sleeps then puts data on the lifo */ static void test_fiber_put_timeout(int lifo, int timeout) { fiber_sleep((int32_t)timeout); nano_fiber_lifo_put((struct nano_lifo *)lifo, get_scratch_packet()); }
void forever_stub(void *a) { while (true) { runAction0((Action)a); fiber_sleep(20); } }
//% help=basic/pause weight=54 //% async block="pause (ms) %pause" //% blockId=device_pause icon="\uf110" void pause(int ms) { fiber_sleep(ms); }
int bt_enable(bt_ready_cb_t cb) { struct device *gpio; int ret; BT_DBG(""); gpio = device_get_binding(CONFIG_GPIO_DW_0_NAME); if (!gpio) { BT_ERR("Cannot find %s", CONFIG_GPIO_DW_0_NAME); return -ENODEV; } ret = gpio_pin_configure(gpio, NBLE_RESET_PIN, GPIO_DIR_OUT); if (ret) { BT_ERR("Error configuring pin %d", NBLE_RESET_PIN); return -ENODEV; } /* Reset hold time is 0.2us (normal) or 100us (SWD debug) */ ret = gpio_pin_write(gpio, NBLE_RESET_PIN, 0); if (ret) { BT_ERR("Error pin write %d", NBLE_RESET_PIN); return -EINVAL; } ret = gpio_pin_configure(gpio, NBLE_BTWAKE_PIN, GPIO_DIR_OUT); if (ret) { BT_ERR("Error configuring pin %d", NBLE_BTWAKE_PIN); return -ENODEV; } ret = gpio_pin_write(gpio, NBLE_BTWAKE_PIN, 1); if (ret) { BT_ERR("Error pin write %d", NBLE_BTWAKE_PIN); return -EINVAL; } /** * NBLE reset is achieved by asserting low the SWDIO pin. * However, the BLE Core chip can be in SWD debug mode, * and NRF_POWER->RESET = 0 due to, other constraints: therefore, * this reset might not work everytime, especially after * flashing or debugging. */ /* sleep 1ms depending on context */ switch (sys_execution_context_type_get()) { case NANO_CTX_FIBER: fiber_sleep(MSEC(1)); break; case NANO_CTX_TASK: task_sleep(MSEC(1)); break; default: BT_ERR("ISR context is not supported"); return -EINVAL; } ret = nble_open(); if (ret) { return ret; } ret = gpio_pin_write(gpio, NBLE_RESET_PIN, 1); if (ret) { BT_ERR("Error pin write %d", NBLE_RESET_PIN); return -EINVAL; } /* Set back GPIO to input to avoid interfering with external debugger */ ret = gpio_pin_configure(gpio, NBLE_RESET_PIN, GPIO_DIR_IN); if (ret) { BT_ERR("Error configuring pin %d", NBLE_RESET_PIN); return -ENODEV; } bt_ready_cb = cb; return 0; }
/** * Enter pairing mode. This is mode is called to initiate pairing, and to enable FOTA programming * of the micro:bit in cases where BLE is disabled during normal operation. * * @param display An instance of MicroBitDisplay used when displaying pairing information. * @param authorizationButton The button to use to authorise a pairing request. * * @code * // initiate pairing mode * bleManager.pairingMode(uBit.display, uBit.buttonA); * @endcode */ void MicroBitBLEManager::pairingMode(MicroBitDisplay& display, MicroBitButton& authorisationButton) { ManagedString namePrefix("BBC micro:bit ["); ManagedString namePostfix("]"); ManagedString BLEName = namePrefix + deviceName + namePostfix; ManagedString msg("PAIRING MODE!"); int timeInPairingMode = 0; int brightness = 255; int fadeDirection = 0; ble->gap().stopAdvertising(); // Clear the whitelist (if we have one), so that we're discoverable by all BLE devices. #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) BLEProtocol::Address_t addresses[MICROBIT_BLE_MAXIMUM_BONDS]; Gap::Whitelist_t whitelist; whitelist.addresses = addresses; whitelist.capacity = MICROBIT_BLE_MAXIMUM_BONDS; whitelist.size = 0; ble->gap().setWhitelist(whitelist); ble->gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST); #endif // Update the advertised name of this micro:bit to include the device name ble->clearAdvertisingPayload(); ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)BLEName.toCharArray(), BLEName.length()); ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble->setAdvertisingInterval(200); ble->gap().setAdvertisingTimeout(0); ble->gap().startAdvertising(); // Stop any running animations on the display display.stopAnimation(); display.scroll(msg); // Display our name, visualised as a histogram in the display to aid identification. showNameHistogram(display); while(1) { if (pairingStatus & MICROBIT_BLE_PAIR_REQUEST) { timeInPairingMode = 0; MicroBitImage arrow("0,0,255,0,0\n0,255,0,0,0\n255,255,255,255,255\n0,255,0,0,0\n0,0,255,0,0\n"); display.print(arrow,0,0,0); if (fadeDirection == 0) brightness -= MICROBIT_PAIRING_FADE_SPEED; else brightness += MICROBIT_PAIRING_FADE_SPEED; if (brightness <= 40) display.clear(); if (brightness <= 0) fadeDirection = 1; if (brightness >= 255) fadeDirection = 0; if (authorisationButton.isPressed()) { pairingStatus &= ~MICROBIT_BLE_PAIR_REQUEST; pairingStatus |= MICROBIT_BLE_PAIR_PASSCODE; } } if (pairingStatus & MICROBIT_BLE_PAIR_PASSCODE) { timeInPairingMode = 0; display.setBrightness(255); for (int i=0; i<passKey.length(); i++) { display.image.print(passKey.charAt(i),0,0); fiber_sleep(800); display.clear(); fiber_sleep(200); if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE) break; } fiber_sleep(1000); } if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE) { if (pairingStatus & MICROBIT_BLE_PAIR_SUCCESSFUL) { MicroBitImage tick("0,0,0,0,0\n0,0,0,0,255\n0,0,0,255,0\n255,0,255,0,0\n0,255,0,0,0\n"); display.print(tick,0,0,0); fiber_sleep(15000); timeInPairingMode = MICROBIT_BLE_PAIRING_TIMEOUT * 30; /* * Disabled, as the API to return the number of active bonds is not reliable at present... * display.clear(); ManagedString c(getBondCount()); ManagedString c2("/"); ManagedString c3(MICROBIT_BLE_MAXIMUM_BONDS); ManagedString c4("USED"); display.scroll(c+c2+c3+c4); * * */ } else { MicroBitImage cross("255,0,0,0,255\n0,255,0,255,0\n0,0,255,0,0\n0,255,0,255,0\n255,0,0,0,255\n"); display.print(cross,0,0,0); } } fiber_sleep(100); timeInPairingMode++; if (timeInPairingMode >= MICROBIT_BLE_PAIRING_TIMEOUT * 30) microbit_reset(); } }
/* a fiber sleeps then gives a semaphore */ static void test_fiber_give_timeout(int sem, int timeout) { fiber_sleep((int32_t)timeout); nano_fiber_sem_give((struct nano_sem *)sem); }
/** * @brief Summary data printer fiber * * @details Print the summary data of the context switch events * and the total dropped event ocurred. * * @return No return value. */ void summary_data_printer(void) { int i; while (1) { /* print task data */ PRINTF("\x1b[1;32HFork manager task"); if (forks_available) { PRINTF("\x1b[2;32HForks : free to use"); } else { PRINTF("\x1b[2;32HForks : all taken "); } #ifndef CONFIG_NANOKERNEL /* Due to fiber are not pre-emptive, the busy_task_entry thread won't * run as a fiber in nanokernel-only system, because it would affect * the visualization of the sample and the collection of the data * while running busy. */ PRINTF("\x1b[4;32HWorker task"); if (is_busy_task_awake) { PRINTF("\x1b[5;32HState : BUSY"); PRINTF("\x1b[6;32H(Prevent the system going idle)"); } else { PRINTF("\x1b[5;32HState : IDLE"); PRINTF("\x1b[6;32H "); } #endif /* print general data */ PRINTF("\x1b[8;1HGENERAL DATA"); PRINTF("\x1b[9;1H------------"); PRINTF("\x1b[10;1HSystem tick count : %d ", sys_tick_get_32()); /* print dropped event counter */ PRINTF("\x1b[11;1HDropped events # : %d ", total_dropped_counter); /* Print context switch event data */ PRINTF("\x1b[13;1HCONTEXT SWITCH EVENT DATA"); PRINTF("\x1b[14;1H-------------------------"); PRINTF("\x1b[15;1HThread ID Switches"); for (i = 0; i < MAX_BUFFER_CONTEXT_DATA; i++) { if (context_switch_summary_data[i].thread_id != 0) { print_context_data(context_switch_summary_data[i].thread_id, context_switch_summary_data[i].count, context_switch_summary_data[i].last_time_executed, i); } } /* Print sleep event data */ PRINTF("\x1b[8;32HSLEEP EVENT DATA"); PRINTF("\x1b[9;32H----------------"); PRINTF("\x1b[10;32HLast sleep event received"); if (sleep_event_data.last_time_slept > 0) { PRINTF("\x1b[11;32HExit cause : irq #%u ", sleep_event_data.awake_cause); PRINTF("\x1b[12;32HAt tick : %u ", sleep_event_data.last_time_slept); PRINTF("\x1b[13;32HDuration : %u ticks ", sleep_event_data.last_duration); } /* Print interrupt event data */ PRINTF("\x1b[15;32HINTERRUPT EVENT DATA"); PRINTF("\x1b[16;32H--------------------"); PRINTF("\x1b[17;32HInterrupt counters"); int line = 0; for (i = 0; i < 255; i++) { if (interrupt_counters[i] > 0) { PRINTF("\x1b[%d;%dHirq #%d : %d times", 18 + line, 32, i, interrupt_counters[i]); line++; } } #ifdef CONFIG_MICROKERNEL /* Print task monitor status data */ PRINTF("\x1b[1;64HTASK MONITOR STATUS DATA"); PRINTF("\x1b[2;64H-------------------------"); PRINTF("\x1b[3;64HEvento\tTimestamp\tTaskId\tData"); for (i = 0; i < MAX_BUFFER_CONTEXT_DATA; i++) { if (tmon_summary_data[i].timestamp != 0) { print_tmon_status_data(i); } } #endif /* Sleep */ fiber_sleep(50); } }