void task_sleep(int32_t timeout_in_ticks) { int64_t cur_ticks, limit; int key; key = irq_lock(); cur_ticks = sys_tick_get(); limit = cur_ticks + timeout_in_ticks; while (cur_ticks < limit) { _NANO_TIMEOUT_SET_TASK_TIMEOUT(timeout_in_ticks); nano_cpu_atomic_idle(key); key = irq_lock(); cur_ticks = sys_tick_get(); } irq_unlock(key); }
/** * * @brief Starts a timer countdown by a timeeout in milliseconds; used by MQTT Client and this glue logic * * NOTE: The timers are implemented using the tick which typically runs at 10ms which cannot give a * millisecond resolution but is good enough for this MQTT implementation. To prevent a timer of * 10 ms or less from being expired from the getgo, a tick is added to ensure that * the routine timer runs for a least a tick meaning that the minimum timeout is greater than 0; * Greater timeouts will have a 10ms resolution. * * @param timer pointer to the timer to start. * @paraa timeout the timeout value in milliseconds. * * \NOMANUAL */ void countdown_ms(Timer* timer, unsigned int timeout) { uint64_t timeoutTick; uint64_t now = sys_tick_get(); timeoutTick = now + timeout*sys_clock_ticks_per_sec/1000; if (timeoutTick <= now) { timeoutTick += 1 ; } timer->timeout = timeoutTick; }
/* 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); }
void com_sta_handle(void) { u8 len; if(com_rx_cnt>(31)){ // putstring("UART About Full.\r\n"); len = com_getbuf(test_buf,32); if(len == CMD_LENGTH){ // puthex(len); // putstring("\r\n"); hal_nrf_send_pkt(test_buf, CMD_LENGTH/2); hal_nrf_send_pkt(test_buf+CMD_LENGTH/2, CMD_LENGTH-CMD_LENGTH/2); }else{ // puthex(len); // putstring("\r\n"); hal_nrf_send_pkt(test_buf, len); } } if(sys_tick_get(com_tick_num)>com_timeout){ // if(sys_tick_get(com_tick_num)>COM_TIMEOUT){ sys_tick_set(com_tick_num, OFF); // putstring("UART Timeout.\r\n"); len = com_getbuf(test_buf, 32); if(len == CMD_LENGTH){ // puthex(len); // putstring("\r\n"); hal_nrf_send_pkt(test_buf, CMD_LENGTH/2); hal_nrf_send_pkt(test_buf+CMD_LENGTH/2, CMD_LENGTH-CMD_LENGTH/2); }else if(len){ // puthex(len); // putstring("\r\n"); hal_nrf_send_pkt(test_buf, len); } } switch(com_rx_sta){ case COM_RX_STA_COM_ERROR: // putstring("UART Error.\r\n"); LED_A0_L(); break; case COM_RX_STA_BUF_OVF: // putstring("UART BUFOVF.\r\n"); LED_A1_L(); break; default: break; } com_rx_sta = COM_RX_STA_IDLE; }
/* a fiber pends on a lifo then times out */ static void test_fiber_pend_and_timeout(int data, int unused) { struct timeout_order_data *d = (void *)data; int32_t orig_ticks = sys_tick_get(); void *packet; ARG_UNUSED(unused); packet = nano_fiber_lifo_get(d->lifo, d->timeout); if (packet) { TC_ERROR(" *** timeout of %d did not time out.\n", d->timeout); return; } if (!is_timeout_in_range(orig_ticks, d->timeout)) { return; } nano_fiber_fifo_put(&timeout_order_fifo, d); }
/* a fiber pends on a semaphore then times out */ static void test_fiber_pend_and_timeout(int data, int unused) { struct timeout_order_data *the_data = (void *)data; int32_t orig_ticks = sys_tick_get(); int rv; ARG_UNUSED(unused); rv = nano_fiber_sem_take(the_data->sem, the_data->timeout); if (rv) { TC_ERROR(" *** timeout of %d did not time out.\n", the_data->timeout); return; } if (!is_timeout_in_range(orig_ticks, the_data->timeout)) { return; } nano_fiber_fifo_put(&timeout_order_fifo, the_data); }
/* the timeout test entry point */ static int test_timeout(void) { int64_t orig_ticks; int32_t timeout; int rv; void *packet, *scratch_packet; int test_data_size; int ii; struct reply_packet reply_packet; nano_lifo_init(&lifo_timeout[0]); nano_lifo_init(&lifo_timeout[1]); nano_fifo_init(&timeout_order_fifo); nano_fifo_init(&scratch_q_packets_fifo); for (ii = 0; ii < NUM_SCRATCH_Q_PACKETS; ii++) { scratch_q_packets[ii].data_if_needed = (void *)ii; nano_task_fifo_put(&scratch_q_packets_fifo, &scratch_q_packets[ii]); } /* test nano_task_lifo_get() with timeout */ timeout = 10; orig_ticks = sys_tick_get(); packet = nano_task_lifo_get(&lifo_timeout[0], timeout); if (packet) { TC_ERROR(" *** timeout of %d did not time out.\n", timeout); return TC_FAIL; } if ((sys_tick_get() - orig_ticks) < timeout) { TC_ERROR(" *** task did not wait long enough on timeout of %d.\n", timeout); return TC_FAIL; } /* test nano_task_lifo_get() with timeout of 0 */ packet = nano_task_lifo_get(&lifo_timeout[0], 0); if (packet) { TC_ERROR(" *** timeout of 0 did not time out.\n"); return TC_FAIL; } /* test nano_task_lifo_get() with timeout > 0 */ TC_PRINT("test nano_task_lifo_get() with timeout > 0\n"); timeout = 3; orig_ticks = sys_tick_get(); packet = nano_task_lifo_get(&lifo_timeout[0], timeout); if (packet) { TC_ERROR(" *** timeout of %d did not time out.\n", timeout); return TC_FAIL; } if (!is_timeout_in_range(orig_ticks, timeout)) { return TC_FAIL; } TC_PRINT("nano_task_lifo_get() timed out as expected\n"); /* * test nano_task_lifo_get() with a timeout and fiber that puts * data on the lifo on time */ timeout = 5; orig_ticks = sys_tick_get(); task_fiber_start(timeout_stacks[0], FIBER_STACKSIZE, test_fiber_put_timeout, (int)&lifo_timeout[0], timeout, FIBER_PRIORITY, 0); packet = nano_task_lifo_get(&lifo_timeout[0], (int)(timeout + 5)); if (!packet) { TC_ERROR(" *** data put in time did not return valid pointer.\n"); return TC_FAIL; } put_scratch_packet(packet); if (!is_timeout_in_range(orig_ticks, timeout)) { return TC_FAIL; } TC_PRINT("nano_task_lifo_get() got lifo in time, as expected\n"); /* * test nano_task_lifo_get() with TICKS_NONE and no data * unavailable. */ if (nano_task_lifo_get(&lifo_timeout[0], TICKS_NONE)) { TC_ERROR("task with TICKS_NONE got data, but shouldn't have\n"); return TC_FAIL; } TC_PRINT("task with TICKS_NONE did not get data, as expected\n"); /* * test nano_task_lifo_get() with TICKS_NONE and some data * available. */ scratch_packet = get_scratch_packet(); nano_task_lifo_put(&lifo_timeout[0], scratch_packet); if (!nano_task_lifo_get(&lifo_timeout[0], TICKS_NONE)) { TC_ERROR("task with TICKS_NONE did not get available data\n"); return TC_FAIL; } put_scratch_packet(scratch_packet); TC_PRINT("task with TICKS_NONE got available data, as expected\n"); /* * test nano_task_lifo_get() with TICKS_UNLIMITED and the * data available. */ TC_PRINT("Trying to take available data with TICKS_UNLIMITED:\n" " will hang the test if it fails.\n"); scratch_packet = get_scratch_packet(); nano_task_lifo_put(&lifo_timeout[0], scratch_packet); if (!nano_task_lifo_get(&lifo_timeout[0], TICKS_UNLIMITED)) { TC_ERROR(" *** This will never be hit!!! .\n"); return TC_FAIL; } put_scratch_packet(scratch_packet); TC_PRINT("task with TICKS_UNLIMITED got available data, as expected\n"); /* test fiber with timeout of TICKS_NONE not getting data on empty lifo */ task_fiber_start(timeout_stacks[0], FIBER_STACKSIZE, test_fiber_ticks_special_values, (int)&reply_packet, TICKS_NONE, FIBER_PRIORITY, 0); if (!nano_task_fifo_get(&timeout_order_fifo, TICKS_NONE)) { TC_ERROR(" *** fiber should have run and filled the fifo.\n"); return TC_FAIL; } if (reply_packet.reply != 0) { TC_ERROR(" *** fiber should not have obtained the data.\n"); return TC_FAIL; } TC_PRINT("fiber with TICKS_NONE did not get data, as expected\n"); /* test fiber with timeout of TICKS_NONE getting data when available */ scratch_packet = get_scratch_packet(); nano_task_lifo_put(&lifo_timeout[0], scratch_packet); task_fiber_start(timeout_stacks[0], FIBER_STACKSIZE, test_fiber_ticks_special_values, (int)&reply_packet, TICKS_NONE, FIBER_PRIORITY, 0); put_scratch_packet(scratch_packet); if (!nano_task_fifo_get(&timeout_order_fifo, TICKS_NONE)) { TC_ERROR(" *** fiber should have run and filled the fifo.\n"); return TC_FAIL; } if (reply_packet.reply != 1) { TC_ERROR(" *** fiber should have obtained the data.\n"); return TC_FAIL; } TC_PRINT("fiber with TICKS_NONE got available data, as expected\n"); /* test fiber with TICKS_UNLIMITED timeout getting data when availalble */ scratch_packet = get_scratch_packet(); nano_task_lifo_put(&lifo_timeout[0], scratch_packet); task_fiber_start(timeout_stacks[0], FIBER_STACKSIZE, test_fiber_ticks_special_values, (int)&reply_packet, TICKS_UNLIMITED, FIBER_PRIORITY, 0); put_scratch_packet(scratch_packet); if (!nano_task_fifo_get(&timeout_order_fifo, TICKS_NONE)) { TC_ERROR(" *** fiber should have run and filled the fifo.\n"); return TC_FAIL; } if (reply_packet.reply != 1) { TC_ERROR(" *** fiber should have obtained the data.\n"); return TC_FAIL; } TC_PRINT("fiber with TICKS_UNLIMITED got available data, as expected\n"); /* test multiple fibers pending on the same lifo with different timeouts */ test_data_size = ARRAY_SIZE(timeout_order_data); TC_PRINT("testing timeouts of %d fibers on same lifo\n", test_data_size); rv = test_multiple_fibers_pending(timeout_order_data, test_data_size); if (rv != TC_PASS) { TC_ERROR(" *** fibers did not time out in the right order\n"); return TC_FAIL; } /* test mult. fibers pending on different lifos with different timeouts */ test_data_size = ARRAY_SIZE(timeout_order_data_mult_lifo); TC_PRINT("testing timeouts of %d fibers on different lifos\n", test_data_size); rv = test_multiple_fibers_pending(timeout_order_data_mult_lifo, test_data_size); if (rv != TC_PASS) { TC_ERROR(" *** fibers did not time out in the right order\n"); return TC_FAIL; } /* * test multiple fibers pending on same lifo with different timeouts, but * getting the data in time, except the last one. */ test_data_size = ARRAY_SIZE(timeout_order_data); TC_PRINT("testing %d fibers timing out, but obtaining the data in time\n" "(except the last one, which times out)\n", test_data_size); rv = test_multiple_fibers_get_data(timeout_order_data, test_data_size); if (rv != TC_PASS) { TC_ERROR(" *** fibers did not get the data in the right order\n"); return TC_FAIL; } return TC_PASS; }
/** * Implementation of jerry_port_get_current_time. * * @return current timer's counter value in microseconds */ double jerry_port_get_current_time () { int64_t us = sys_tick_get() * sys_clock_us_per_tick; return (double) us / 1000; } /* jerry_port_get_current_time */
void hal_nrf_sta_handle(void) { u8 len=0; if(hal_nrf_rx_cnt){ /** turn on connect LED */ hal_nrf_cnt = 0; LED_A5_L(); #ifdef SLAVE_DEBUG len = hal_nrf_receive_pkt(hal_nrf_tmp); puthex_buf(hal_nrf_tmp, len); putstring("\r\n"); if(len == CMD_LENGTH){ putstring("CMD receive\r\n"); slave_parse_cmd(hal_nrf_tmp); } #else /** SLAVE_DEBUG */ len = hal_nrf_receive_pkt(hal_nrf_tmp); if(len == CMD_LENGTH){ // putbuf(hal_nrf_tmp, len); slave_parse_cmd(hal_nrf_tmp); }else{ putbuf(hal_nrf_tmp, len); } #endif /** SLAVE_DEBUG */ } if(hal_nrf_timeout){ hal_nrf_timeout = 0; if(hal_nrf_tx_cmd_flag == 1){ LED_D4_L(); }else if(hal_nrf_tx_cmd_flag == 2){ LED_D5_L(); }else{ LED_D6_L(); } hal_nrf_tx_cmd_flag = 0; // putstring("TX TIMEOUT\r\n"); } switch(hal_nrf_rx_sta){ case HAL_NRF_RX_STA_BUF_OVF: // putstring("NRF_RX_BUF_OVF\r\n"); LED_D7_L(); hal_nrf_rx_sta = HAL_NRF_RX_STA_IDLE; break; case HAL_NRF_RX_STA_COM_ERROR: // putstring("HAL_NRF_RX_STA_COM_ERROR\r\n"); LED_D8_L(); hal_nrf_rx_sta = HAL_NRF_RX_STA_IDLE; break; } switch(hal_nrf_sta){ case HAL_NRF_STA_RX: break; case HAL_NRF_STA_TX: break; case HAL_NRF_STA_TX_CMD: break; } if(sys_tick_get(hal_nrf_tick_num)>HAL_NRF_TICK){ sys_tick_clear(hal_nrf_tick_num); hal_nrf_cnt++; if(hal_nrf_cnt == HAL_NRF_TIMEOUT){ /** turn off connectted led */ hal_nrf_cnt = 0; LED_A5_H(); } } }
/* the timeout test entry point */ static int test_timeout(void) { int64_t orig_ticks; int32_t timeout; int rv; int test_data_size; struct reply_packet reply_packet; nano_sem_init(&sem_timeout[0]); nano_sem_init(&sem_timeout[1]); nano_fifo_init(&timeout_order_fifo); /* test nano_task_sem_take() with timeout */ timeout = 10; orig_ticks = sys_tick_get(); rv = nano_task_sem_take(&sem_timeout[0], timeout); if (rv) { TC_ERROR(" *** timeout of %d did not time out.\n", timeout); return TC_FAIL; } if ((sys_tick_get() - orig_ticks) < timeout) { TC_ERROR(" *** task did not wait long enough on timeout of %d.\n", timeout); return TC_FAIL; } /* test nano_task_sem_take() with timeout of 0 */ rv = nano_task_sem_take(&sem_timeout[0], 0); if (rv) { TC_ERROR(" *** timeout of 0 did not time out.\n"); return TC_FAIL; } /* test nano_task_sem_take() with timeout > 0 */ TC_PRINT("test nano_task_sem_take() with timeout > 0\n"); timeout = 3; orig_ticks = sys_tick_get(); rv = nano_task_sem_take(&sem_timeout[0], timeout); if (rv) { TC_ERROR(" *** timeout of %d did not time out.\n", timeout); return TC_FAIL; } if (!is_timeout_in_range(orig_ticks, timeout)) { return TC_FAIL; } TC_PRINT("nano_task_sem_take() timed out as expected\n"); /* * test nano_task_sem_take() with a timeout and fiber that gives * the semaphore on time */ timeout = 5; orig_ticks = sys_tick_get(); task_fiber_start(timeout_stacks[0], FIBER_STACKSIZE, test_fiber_give_timeout, (int)&sem_timeout[0], timeout, FIBER_PRIORITY, 0); rv = nano_task_sem_take(&sem_timeout[0], (int)(timeout + 5)); if (!rv) { TC_ERROR(" *** timed out even if semaphore was given in time.\n"); return TC_FAIL; } if (!is_timeout_in_range(orig_ticks, timeout)) { return TC_FAIL; } TC_PRINT("nano_task_sem_take() got sem in time, as expected\n"); /* * test nano_task_sem_take() with TICKS_NONE and the * semaphore unavailable. */ if (nano_task_sem_take(&sem_timeout[0], TICKS_NONE)) { TC_ERROR("task with TICKS_NONE got sem, but shouldn't have\n"); return TC_FAIL; } TC_PRINT("task with TICKS_NONE did not get sem, as expected\n"); /* * test nano_task_sem_take() with TICKS_NONE and the * semaphore available. */ nano_task_sem_give(&sem_timeout[0]); if (!nano_task_sem_take(&sem_timeout[0], TICKS_NONE)) { TC_ERROR("task with TICKS_NONE did not get available sem\n"); return TC_FAIL; } TC_PRINT("task with TICKS_NONE got available sem, as expected\n"); /* * test nano_task_sem_take() with TICKS_UNLIMITED and the * semaphore available. */ TC_PRINT("Trying to take available sem with TICKS_UNLIMITED:\n" " will hang the test if it fails.\n"); nano_task_sem_give(&sem_timeout[0]); if (!nano_task_sem_take(&sem_timeout[0], TICKS_UNLIMITED)) { TC_ERROR(" *** This will never be hit!!! .\n"); return TC_FAIL; } TC_PRINT("task with TICKS_UNLIMITED got available sem, as expected\n"); /* test fiber with timeout of TICKS_NONE not getting empty semaphore */ task_fiber_start(timeout_stacks[0], FIBER_STACKSIZE, test_fiber_ticks_special_values, (int)&reply_packet, TICKS_NONE, FIBER_PRIORITY, 0); if (!nano_task_fifo_get(&timeout_order_fifo, TICKS_NONE)) { TC_ERROR(" *** fiber should have run and filled the fifo.\n"); return TC_FAIL; } if (reply_packet.reply != 0) { TC_ERROR(" *** fiber should not have obtained the semaphore.\n"); return TC_FAIL; } TC_PRINT("fiber with TICKS_NONE did not get sem, as expected\n"); /* test fiber with timeout of TICKS_NONE getting full semaphore */ nano_task_sem_give(&sem_timeout[0]); task_fiber_start(timeout_stacks[0], FIBER_STACKSIZE, test_fiber_ticks_special_values, (int)&reply_packet, TICKS_NONE, FIBER_PRIORITY, 0); if (!nano_task_fifo_get(&timeout_order_fifo, TICKS_NONE)) { TC_ERROR(" *** fiber should have run and filled the fifo.\n"); return TC_FAIL; } if (reply_packet.reply != 1) { TC_ERROR(" *** fiber should have obtained the semaphore.\n"); return TC_FAIL; } TC_PRINT("fiber with TICKS_NONE got available sem, as expected\n"); /* test fiber with timeout of TICKS_UNLIMITED getting full semaphore */ nano_task_sem_give(&sem_timeout[0]); task_fiber_start(timeout_stacks[0], FIBER_STACKSIZE, test_fiber_ticks_special_values, (int)&reply_packet, TICKS_UNLIMITED, FIBER_PRIORITY, 0); if (!nano_task_fifo_get(&timeout_order_fifo, TICKS_NONE)) { TC_ERROR(" *** fiber should have run and filled the fifo.\n"); return TC_FAIL; } if (reply_packet.reply != 1) { TC_ERROR(" *** fiber should have obtained the semaphore.\n"); return TC_FAIL; } TC_PRINT("fiber with TICKS_UNLIMITED got available sem, as expected\n"); /* test multiple fibers pending on the same sem with different timeouts */ test_data_size = ARRAY_SIZE(timeout_order_data); TC_PRINT("testing timeouts of %d fibers on same sem\n", test_data_size); rv = test_multiple_fibers_pending(timeout_order_data, test_data_size); if (rv != TC_PASS) { TC_ERROR(" *** fibers did not time out in the right order\n"); return TC_FAIL; } /* test multiple fibers pending on different sems with different timeouts */ test_data_size = ARRAY_SIZE(timeout_order_data_mult_sem); TC_PRINT("testing timeouts of %d fibers on different sems\n", test_data_size); rv = test_multiple_fibers_pending(timeout_order_data_mult_sem, test_data_size); if (rv != TC_PASS) { TC_ERROR(" *** fibers did not time out in the right order\n"); return TC_FAIL; } /* * test multiple fibers pending on same sem with different timeouts, but * getting the semaphore in time, except the last one. */ test_data_size = ARRAY_SIZE(timeout_order_data); TC_PRINT("testing %d fibers timing out, but obtaining the sem in time\n" "(except the last one, which times out)\n", test_data_size); rv = test_multiple_fibers_get_sem(timeout_order_data, test_data_size); if (rv != TC_PASS) { TC_ERROR(" *** fibers did not get the sem in the right order\n"); return TC_FAIL; } return TC_PASS; }
/** * * @brief Determine how many milliseconds to go in the timer ; used by MQTT Client and this glue logic * * @param timer pointer to the timer to start. * * @return Number of milliseconds left. * * \NOMANUAL */ int left_ms(Timer* timer) { uint64_t delta = (int)(timer->timeout - sys_tick_get())*1000/sys_clock_ticks_per_sec; return ((delta > 0) ? delta : 0); }