Example #1
0
/*!
 * \brief Create a new system timer.
 *
 * Applications should not call this function.
 *
 * \param ticks    Specifies the timer interval in system ticks.
 * \param callback Identifies the function to be called on each
 *                 timer interval.
 * \param arg      The argument passed to the callback function.
 * \param flags    If set to TM_ONESHOT, the timer will be stopped
 *                 after the first interval. Set to 0 for periodic
 *                 timers.
 *
 * \return Timer handle if successfull, 0 otherwise. The handle
 *         may be used to release the timer by calling TimerStop.
 *
 * \todo Make this local function static or directly integrate it into
 *       NutTimerStartTicks().
 */
NUTTIMERINFO * NutTimerCreate(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
{
    NUTTIMERINFO *tn;

    tn = NutHeapAlloc(sizeof(NUTTIMERINFO));
    if (tn) {
        tn->tn_ticks_left = ticks + NutGetTickCount() - nut_ticks_resume;

        /*
         * Periodic timers will reload the tick counter on each timer
         * intervall.
         */
        if (flags & TM_ONESHOT) {
            tn->tn_ticks = 0;
        } else {
            tn->tn_ticks = ticks;
        }

        /* Set callback and callback argument. */
        tn->tn_callback = callback;
        tn->tn_arg = arg;
    }
#ifdef NUTDEBUG
    if (__os_trf)
        fprintf(__os_trs, " TIM %p NutTimerCreate\n", tn);
#endif
    return tn;
}
Example #2
0
/*!
 * \brief Return the milliseconds counter value.
 *
 * This function returns the value of a counter, which is incremented
 * every system timer tick. During system start, the counter is cleared
 * to zero and will overflow with the 32 bit tick counter (4294967296).
 * With the default 1024 ticks/s this will happen after 49.71 days.
 * The resolution is also given by the system ticks.
 *
 * \note There is intentionally no provision to modify the seconds counter.
 *       Callers can rely on a continuous update and use this value for
 *       system tick independend timeout calculations.
 *       Depending on
 *
 * \return Value of the seconds counter.
 */
uint32_t NutGetMillis(void)
{
    // carefully stay within 32 bit values
    uint32_t ticks   = NutGetTickCount();
    uint32_t seconds = ticks / NutGetTickClock();
    ticks         -= seconds * NutGetTickClock();
    return seconds * 1000 + (ticks * 1000 ) / NutGetTickClock();
}
THREAD(DiscoveryResponder, arg)
{
    UDPSOCKET *sock;
    DISCOVERY_TELE *dist;
    u_long raddr;
    u_short rport;
    int len;

    /* Insist on allocating a datagram buffer. */
    while ((dist = malloc(sizeof(DISCOVERY_TELE))) == NULL) {
        NutSleep(1000);
    }

    /* Insist on creating a socket. */
    while ((sock = NutUdpCreateSocket(disopt.disopt_port)) == NULL) {
        NutSleep(1000);
    }

    /* Nut/Net doesn't provide UDP datagram buffering by default. */
    {
        u_short max_ms = sizeof(DISCOVERY_TELE) * 3;

        NutUdpSetSockOpt(sock, SO_RCVBUF, &max_ms, sizeof(max_ms));
    }

    /* Create a pseudo random telegram identifier. */
    memcpy(&xid, &confnet.cdn_mac[2], sizeof(xid));
    xid += NutGetTickCount();

    /* Optionally send initial announce datagram. */
    if (disopt.disopt_flags & DISF_INITAL_ANN) {
        /* Variable sleep avoids broadcast storms in large installations. */
        NutSleep(500 + (xid & 0x7FF));
        if ((len = NutDiscoveryAnnTele(dist)) > 0) {
            NutUdpSendTo(sock, INADDR_BROADCAST, disopt.disopt_port, dist, len);
        }
    }

    /* Handle discovery telegrams in an endless loop. */
    for (;;) {
        len = NutUdpReceiveFrom(sock, &raddr, &rport, dist, sizeof(DISCOVERY_TELE), 0);
        /* Updates may be filtered by an IP mask. */
        if ((raddr & disopt.disopt_ipmask) == raddr && len > 0 && discovery_callback) {
            if ((len = discovery_callback(raddr, rport, dist, len)) > 0) {
                /* Broadcast response if destination is unreachable. */
                if ((raddr & confnet.cdn_ip_mask) != (confnet.cdn_ip_addr & confnet.cdn_ip_mask)) {
                    raddr = INADDR_BROADCAST;
                }
                NutUdpSendTo(sock, raddr, disopt.disopt_port, dist, len);
            }
        }
        /* Avoid system blocking by datagram storms. */
        NutSleep(100);
    }
}
Example #4
0
/*!
 * \brief Process elapsed timers.
 *
 * This routine is called during context switch processing.
 * Applications should not use this function.
 */
void NutTimerProcessElapsed(void)
{
    NUTTIMERINFO *tn;
    uint32_t ticks;
    uint32_t ticks_new;

    // calculate ticks since last call
    ticks = NutGetTickCount();
    ticks_new = ticks - nut_ticks_resume;
    nut_ticks_resume = ticks;

    // process timers
    while (nutTimerList && ticks_new){

        tn = nutTimerList;

        // subtract time
        if (ticks_new < tn->tn_ticks_left) {
            tn->tn_ticks_left -= ticks_new;
            ticks_new = 0;
        } else {
            ticks_new -= tn->tn_ticks_left;
            tn->tn_ticks_left = 0;
        }

        // elapsed
        if (tn->tn_ticks_left == 0){

            // callback
            if (tn->tn_callback) {
                (*tn->tn_callback) (tn, (void *) tn->tn_arg);
            }
            // remove from list
            nutTimerList = nutTimerList->tn_next;
            if (nutTimerList) {
                nutTimerList->tn_prev = NULL;
            }
            if ((tn->tn_ticks_left = tn->tn_ticks) == 0) {
#ifdef NUTDEBUG
    if (__os_trf)
        fprintf(__os_trs, " TIM %p free NutTimerProcessElapsed\n", tn);
#endif
                NutHeapFree(tn);
            }
            else {
                // re-insert
#ifdef NUTDEBUG
    if (__os_trf)
        fprintf(__os_trs, " TIM %p reinsert NutTimerProcessElapsed\n", tn);
#endif
                NutTimerInsert(tn);
            }
        }
    }
}
Example #5
0
void NutTimerInit(void)
{
#ifdef __NUT_EMULATION__
    gettimeofday( &timeStart, NULL );
#else
    NutRegisterTimer(NutTimerIntr);
    NutEnableTimerIrq();
//Not Used     /* Remember the CPU clock for which the loop counter is valid. */
//Not Used     nut_delay_loops_clk = NutGetCpuClock();
#if !defined(NUT_DELAYLOOPS)
#ifndef NUT_TICK_FREQ
#define NUT_TICK_FREQ   1000UL
#endif
    {
        /* Wait for the next tick. */
        uint32_t cnt = NutGetTickCount();
        while (cnt == NutGetTickCount());
        /* Wait for the next tick, counting loops. */
        cnt = NutGetTickCount();
        while (cnt == NutGetTickCount()) {
            nut_delay_loops++;
        }
        /*
         * The loop above needs more cycles than the actual delay loop.
         * Apply the correction found by trial and error. Works acceptable
         * with GCC for Ethernut 1 and 3.
         */
#if defined(__AVR__)
        nut_delay_loops *= 103UL;
        nut_delay_loops /= 26UL;
#else
        //nut_delay_loops *= 137UL;
        //nut_delay_loops /= 25UL;
        //nut_delay_loops *= 190UL;
        //nut_delay_loops /= 25UL;
        nut_delay_loops *= 185UL;
        nut_delay_loops /= 24UL;
#endif
    }
#endif
#endif
}
/*
 * \brief Default discovery datagram handler.
 *
 * \param ip    Sender's IP address.
 * \param port  Sender's UDP port.
 * \param dtel  Pointer to the UDP telegram buffer.
 * \param len   UDP telegram size.
 */
static int NutDiscoveryHandler(u_long ip, u_short port, DISCOVERY_TELE * dist, int len)
{
    int rc = -1;

    /* Check minimum datagram length. */
    if (len >= sizeof(DISCOVERY_TELE) - sizeof(dist->dist_custom)) {
        if (dist->dist_type == DIST_REQUEST) {
            /* Respond to requests. */
            rc = NutDiscoveryAnnTele(dist);
        } else if (dist->dist_type == DIST_APPLY        /* Apply telegram. */
                   && dist->dist_xid == xid     /* Check exchange ID. */
                   && dist->dist_ver >= DISCOVERY_VERSION) {    /* Minimum version required. */
            xid += NutGetTickCount();
            /* Store configuration. */
            rc = NutDiscoveryAppConf(dist);
        }
    }
    return rc;
}
Example #7
0
/*!
 * \brief Return the seconds counter value.
 *
 * This function returns the value of a counter, which is incremented
 * every second. During system start, the counter is cleared to zero.
 *
 * \note There is intentionally no provision to modify the seconds counter.
 *       Callers can rely on a continuous update and use this value for
 *       system tick independend timeout calculations. Applications,
 *       which want to use this counter for date and time functions,
 *       should use an offset value.
 *
 * \return Value of the seconds counter.
 */
uint32_t NutGetSeconds(void)
{
    return NutGetTickCount() / NutGetTickClock();
}