Пример #1
0
void ADCInit(void)
{
    int channel;

    /* Only init once */
    if (ADC_Buffer) return;

    /* Enable clock int PMC and reset ADC */
    outr(PMC_PCER, _BV(ADC_ID));              // Enable ADC clock in PMC
    outr(ADC_CR, ADC_SWRST);                  // Reset bus
    outr(ADC_CR, 0x00);

    /* Basic configuration: Disable all channels and set mode and prescaler */
    outr(ADC_CHDR, ADC_CH0 | ADC_CH1 | ADC_CH2 | ADC_CH3 | ADC_CH4 | ADC_CH5 | ADC_CH6 | ADC_CH7);
    ADCSetMode(AT91_ADC_INITIAL_MODE);
    ADCSetPrescale(AT91_ADC_INITIAL_PRESCALE);

    /* Init adc buffers. One for every channel as we can sample all by automatic sequence */
    ADC_Buffer = NutHeapAlloc(sizeof(uint16_t *) * ADC_MAX_CHANNEL);
    for (channel = 0; channel < ADC_MAX_CHANNEL; channel ++) {
        ADC_Buffer[channel] = NutHeapAlloc(sizeof(uint16_t) * AT91_ADC_BUF_SIZE + 2);
        ADC_Buffer[channel][_adc_buf_head] = 0;
        ADC_Buffer[channel][_adc_buf_tail] = 0;
    }

    if (NutRegisterIrqHandler(&sig_ADC, ADCInterrupt, NULL)) {
        // We do not free buffer as this would cost ROM and is not likely
        return;
    }
    NutIrqEnable(&sig_ADC);
}
Пример #2
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;
}
Пример #3
0
/*!
 * \brief Initialize TWI interface bus.
 *
 * The specified slave address is not used here as we don't support twi-slave
 * on the bitbanging interface
 *
 * \param sla Slave address, must be specified as a 7-bit address,
 *            always lower than 128.
 */
int NutRegisterTwiBus( NUTTWIBUS *bus, uint8_t sla )
{
    int rc = 0;
    NUTTWIICB *icb = NULL;

    /* Check if bus was already registered */
    if( bus->bus_icb) {
        return 0;
    }

    /* Allocate ICB for this bus */
    icb = NutHeapAlloc(sizeof(NUTTWIICB));
    if( icb == NULL) {
        return rc;
    }
    memset( icb, 0, sizeof(NUTTWIICB));

    /* Link bus and ICB */
    bus->bus_icb = icb;

    /* Initialize interface hardware */
    if (bus->bus_initbus) {
        rc = bus->bus_initbus();
    }

    /* Initialize mutex semaphores. */
    NutEventPost(&bus->bus_mutex);

    return rc;
}
static int NutNetBufAllocData(NBDATA * nbd, u_short size)
{
    if ((nbd->vp = NutHeapAlloc(size)) == 0) {
        nbd->sz = 0;
        return -1;
    }
    nbd->sz = size;
    return 0;
}
Пример #5
0
/*!
 * \brief Allocate memory.
 *
 * \param   unSize [in] Amount of memory to allocate.
 *
 * \return  pointer to the allocated memory.
 *          NULL if there is no memory left or you requested 0 size.
 */
void *MyMalloc(unsigned int unSize)
{
    void *pResult = NULL;

    if ((unSize != 0) &&
        ((pResult = NutHeapAlloc(unSize)) == NULL))
    {
        LogMsg_P(LOG_ERR, PSTR("No memory [%u]"), unSize);
    }
    return (pResult);
}
Пример #6
0
/*!
 * \brief Write argument list to a stream using a given format.
 *
 * Similar to vfprintf() except that the format string is located in
 * program memory.
 *
 * \param stream Pointer to a previously opened stream.
 * \param fmt    Format string in program space containing conversion 
 *               specifications.
 * \param ap     List of arguments.
 *
 * \return The number of characters written or a negative value to
 *         indicate an error.
 */
int vfprintf_P(FILE * stream, PGM_P fmt, va_list ap)
{
    int rc;
    char *rp;
    size_t rl;

    rl = strlen_P(fmt) + 1;
    if ((rp = NutHeapAlloc(rl)) == 0)
        return -1;
    memcpy_P(rp, fmt, rl);
    rc = _putf(_write, stream->iob_fd, rp, ap);
    NutHeapFree(rp);

    return rc;
}
Пример #7
0
/*!
 * \brief Initialize the segmented buffer.
 *
 * \param size Number of bytes to allocate for the global buffer.
 *             In systems with banked memory this parameter is 
 *             ignored and all banked memory is occupied for the
 *             global buffer. In systems without banked memory,
 *             the specified number of bytes is taken from heap
 *             memory.
 *
 * \return Pointer to the first buffer segment or null on failures.
 */
char *NutSegBufInit(size_t size)
{

#if NUTBANK_COUNT
    segbuf_start = (char *)(NUTBANK_START);
    segbuf_end = (char *)(NUTBANK_START) + NUTBANK_SIZE;
    segbuf_total = (uint32_t) NUTBANK_COUNT *(uint32_t) NUTBANK_SIZE;
#else
    if (size == 0)
        size = NutHeapAvailable() / 2;
    if (segbuf_start) {
        NutHeapFree(segbuf_start);
    }
    if ((segbuf_start = NutHeapAlloc(size)) != NULL)
        segbuf_end = segbuf_start + size;
    segbuf_total = size;
#endif

    return NutSegBufReset();
}
Пример #8
0
int WlanInit(NUTDEVICE * dev)
{
    int nError = ERROR;

    /*
     * Check if this is the first call. 
     * Only one init allowed.
     */
    if (dev->dev_dcb == NULL) {
        dev->dev_dcb = NutHeapAlloc(sizeof(WI_SOFTC));
        /*
         * Have we got the memory ?
         */
        if (dev->dev_dcb != NULL) {
            /*
             * Clear NICINFO structure.
             */
            memset(dev->dev_dcb, 0, sizeof(WI_SOFTC));

            /*
             * Check if a card is available
             */
            nError = wlandrv_ProbeDevice();
            if (nError == OK) {
                /*
                 * Check if we can attach the card
                 */
                if (wlandrv_Attach(dev) != OK) {
                    nError = ERROR;
                } else {
                    /*
                     * Now we have all the information,
                     * and can start the device.
                     */
                    wlandrv_Init(dev);
                }               /* endif wi_attach(dev->dev_dcb) != OK */
            }                   /* HardwareReset() */
        }                       /* endif dev->dev_dcb != NULL */
    }                           /* check first call, dev->dev_dcb == NULL */
    return (nError);
}
Пример #9
0
int NutTraceInit(int size, char mode)
{
    if (!trace_isinit) {
        // start timer1 at CPU frequency/8 and register interrupt service routine
        outb(TCCR1B, 2);
        NutRegisterIrqHandler(&sig_OVERFLOW1, NutTraceTimer1IRQ, 0);
        sbi(TIMSK, TOIE1);
        trace_isinit = 1;
    }
    if (size==0) {
        size = TRACE_SIZE_DEFAULT;
    }
    if (size != trace_size) {
        // current buffer is not of size that is wanted
        if (trace_items != 0) {
            // but memory is already allocated -> free old buffer
            NutHeapFree(trace_items);
        }
        // allocate buffer
        trace_items = (t_traceitem *)NutHeapAlloc(size * sizeof(t_traceitem));
        if (trace_items == 0) {
            // failed
            return trace_size = 0;
        }
        else {
            trace_size = size;
        }
    }

//  if (mode == TRACE_MODE_OFF) {
//      // if terminal-cmd "trace size <val>" is called trace is started in
//      // default mode
//      mode = TRACE_MODE_DEFAULT;
//  }
    trace_mode   = mode;
    NutTraceClear();
    return trace_size;
}
Пример #10
0
/*!
 * \brief Initialize TWI interface.
 *
 * The specified slave address is not used here as we don't support twi-slave
 * on this architecture for now.
 *
 * \param sla Slave address, must be specified as a 7-bit address,
 *            always lower than 128.
 */
int NutRegisterTwiBus( NUTTWIBUS *bus, uint8_t sla )
{
    int rc = -1;

    uint32_t speed = 80000; /* Errata Doc 14574 Rev. 9 Chapter 2.11: Avoid 88kHz to 100kHz */
//    uint16_t tmpreg = 0;
    I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base;
    NUTTWIICB *icb = NULL;

    DBGP1_INIT();
    DBGP2_INIT();

    /* Check if bus was already registered */
    if( bus->bus_icb) {
        return 0;
    }

    /* Allocate ICB for this bus */
    icb = NutHeapAlloc(sizeof(NUTTWIICB));
    if( icb == NULL) {
        return rc;
    }
    memset( icb, 0, sizeof(NUTTWIICB));

    /* Link bus and ICB */
    bus->bus_icb = icb;

    if( NutRegisterIrqHandler( bus->bus_sig_ev, TwEventIrq, bus ) ) {
        free( icb);
        return rc;
    }

    if( NutRegisterIrqHandler( bus->bus_sig_er, TwErrorIrq, bus ) ) {
        free( icb);
        return rc;
    }

    /* Initialize GPIO Hardware */
    if( bus->bus_initbus != NULL) {
        rc = bus->bus_initbus();
    }
    if( rc) {
        return rc;
    }

    /* Disable and reset this bus */
    I2Cx->CR1 &= ~I2C_CR1_PE;
    I2Cx->CR1 |= I2C_CR1_SWRST;
    I2Cx->CR1 &= ~I2C_CR1_SWRST;


#ifdef I2C_DEFAULT_SPEED
    if( bus->bus_base == I2C1_BASE)
        speed = I2CBUS1_DEFAULT_SPEED*1000UL;
#endif
#ifdef I2CBUS2_DEFAULT_SPEED
    if( bus->bus_base == I2C2_BASE)
        speed = I2CBUS2_DEFAULT_SPEED*1000UL;
#endif
    /* Set initial rate. */
    if( (rc = NutTwiSetSpeed( bus, speed))) {
        return rc;
    }

    /* Setup 7-Bit Addressing Mode not acknowledged */
    I2Cx->OAR1 = 0x4000; /* FIXME: OAR1 Bit 14 is reserved */

#if 0
    /* Setup CR1 */
    tmpreg = I2Cx->CR1;
    tmpreg &= ~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE|I2C_CR1_PEC);
    tmpreg |= I2C_CR1_ACK;
    // TODO: Set SMBTYPE and SMBUS bits
    I2Cx->CR1 = tmpreg;

    /* Setup Interrupts */
    tmpreg = I2Cx->CR2;
    tmpreg |= (I2C_CR2_ITBUFEN|I2C_CR2_ITEVTEN|I2C_CR2_ITERREN);
    I2Cx->CR2 = tmpreg;
#endif
    I2Cx->CR1 = I2C_CR1_PE;

    // TODO: Slave Address Setup

    NutIrqSetPriority(bus->bus_sig_ev, 0);
    rc = NutIrqEnable(bus->bus_sig_ev);
    if( rc) {
        return rc;
    }
    NutIrqSetPriority(bus->bus_sig_er, 1);
    rc = NutIrqEnable(bus->bus_sig_er);
    if( rc) {
        return rc;
    }

    /* Initialize mutex semaphores. */
    NutEventPost(&bus->bus_mutex);

    return rc;
}
/*! \fn AhdlcRx(void *arg)
 * \brief Asynchronous HDLC receiver thread.
 *
 *
 * Running at high priority.
 */
THREAD(AhdlcRx, arg)
{
    NUTDEVICE *dev = arg;
    NUTDEVICE *netdev;
    AHDLCDCB *dcb = dev->dev_dcb;
    IFNET *ifn;
    NETBUF *nb;
    uint8_t *rxbuf;
    uint8_t *rxptr;
    uint16_t rxcnt;
    uint8_t ch;
    uint16_t tbx;
    uint8_t inframe;
    uint8_t escaped;
    uint16_t rxfcs;

    NutThreadSetPriority(9);
    for (;;) {
        /*
         * Reset variables to their initial state
         */
        rxptr = 0;
        rxcnt = 0;
        escaped = 0;
        rxfcs = AHDLC_INITFCS;
        inframe = 0;

        for (;;) {
            /*
             * Wait until the network interface has been attached.
             * This will be initiated by the application calling
             * NutNetIfConfig(), which in turn calls a HDLC_SETIFNET
             * ioctl() to store the NUTDEVICE pointer of the network
             * device in dev_icb and trigger an event on dcb_mf_evt.
             */
            while ((netdev = dev->dev_icb) == 0) {
                if (NutEventWait(&dcb->dcb_mf_evt, 1000) == 0) {
                    NutSleep(100);
                }
            }
            ifn = netdev->dev_icb;
            dcb->dcb_rtimeout = 1000;
            inframe = 0;

            /*
             * Allocate the receive buffer, if this fails, we are in a
             * low memory situation. Take a nap and see, if the
             * situation improved.
             */
            if ((rxbuf = NutHeapAlloc(dcb->dcb_rx_mru)) != 0) {
                break;
            }
            NutSleep(1000);
        }

        /*
         * Signal the link driver that we are up.
         */
        ifn->if_send = AhdlcOutput;
        netdev->dev_ioctl(netdev, LCP_LOWERUP, 0);

        for (;;) {
            /*
             * If we are still connected to a network, fetch the next
             * character from the buffer.
             */
            while (dcb->dcb_rd_idx == dcb->dcb_rx_idx) {
                if (dev->dev_icb == 0)
                    break;
                // TODO: Check for idle timeout. 
                if (NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout)) {
                    continue;
                }
            }

            /*
             * Leave loop if network interface is detached
             */
            if (dev->dev_icb == 0)
                break;

            /*
             * If RAW mode is active, we are not allowing any data encapsulation
             * processing. So we just sleep for a while.
             */
            if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
                /*
                 * It is a must to sleep here, because if we just yield it could create
                 * too much processing in here and stall processing elsewhere. This gives
                 * opportunity to other threads to process incoming data from USART.
                 */
                NutSleep(100);
                continue;
            }

            /*
             * Read next character from input buffer
             */
            ch = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];

            if (inframe) {
                if (ch != AHDLC_FLAG) {
                    if (ch == AHDLC_ESCAPE) {
                        escaped = 1;
                        continue;
                    }
                    if (escaped) {
                        ch ^= AHDLC_TRANS;
                        escaped = 0;
                    }

                    /*
                     * Unless the peer lied to us about the negotiated MRU,
                     * we should never get a frame which is too long. If it
                     * happens, toss it away and grab the next incoming one.
                     */
                    if (rxcnt++ < dcb->dcb_rx_mru) {
                        /* Update calculated checksum and store character in buffer. */
                        tbx = (uint16_t) ((uint8_t) rxfcs ^ ch) << 1;
                        rxfcs >>= 8;
                        rxfcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
                        *rxptr++ = ch;
                    } else
                        inframe = 0;
                    continue;
                }

                if (rxcnt > 6 && rxfcs == AHDLC_GOODFCS) {
                    /*
                       * If the frame checksum is valid, create a NETBUF
                       * and pass it to the network specific receive handler.
                     */
                    rxcnt -= 2;
                    if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, rxcnt)) != 0) {
                        memcpy(nb->nb_dl.vp, rxbuf, rxcnt);
                        (*ifn->if_recv) (netdev, nb);
                    }
                }
            }

            /*
             * If frame flag is received, resync frame processing
             */
            if (ch == AHDLC_FLAG) {
                inframe = 1;
                escaped = 0;
                rxptr = rxbuf;
                rxcnt = 0;
                rxfcs = AHDLC_INITFCS;
            }
        }
Пример #12
0
/*
 * \brief Enable the link layer to come up.
 *
 * The underlying hardware driver should have established a physical 
 * connection before calling this function.
 *
 * \param name Physical device name optionally followed by username 
 *             and password, each separated by a slash.
 *
 */
static NUTFILE *NutPppOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
{
    NUTFILE *fp;
    uint8_t i;
    char *cp;
    char *sp;
    char pdn[9];
    PPPDCB *dcb = dev->dev_dcb;

    /* Clear our device control block. */
    memset(dcb, 0, sizeof(PPPDCB));

    /* Get the first part of the name, it specifies the physical device. */
    for (cp = (char *) name, i = 0; *cp && *cp != '/' && i < sizeof(pdn) - 1; i++) {
        pdn[i] = *cp++;
    }
    pdn[i] = 0;

    /* Open the pysical device. */
    if ((dcb->dcb_fd = _open(pdn, _O_RDWR | _O_BINARY)) == -1) {
        return NUTFILE_EOF;
    }

    /*
     * Allocate a file structure to return.
     */
    if ((fp = NutHeapAlloc(sizeof(NUTFILE))) == 0) {
        return NUTFILE_EOF;
    }
    fp->nf_next = 0;
    fp->nf_dev = dev;
    fp->nf_fcb = 0;

    /*
     * Extract user name and password and store it in our device control
     * block. It will be used later by the authentication layer.
     */
    if (*cp == '/') {
        for (sp = ++cp, i = 0; *sp && *sp != '/'; sp++, i++);
        if (i) {
            dcb->dcb_user = NutHeapAlloc(i + 1);
            for (sp = (char*)dcb->dcb_user; *cp && *cp != '/';)
                *sp++ = *cp++;
            *sp = 0;
        }
        if (*cp == '/') {
            for (sp = ++cp, i = 0; *sp && *sp != '/'; sp++, i++);
            if (i) {
                dcb->dcb_pass = NutHeapAlloc(i + 1);
                for (sp = (char*)dcb->dcb_pass; *cp && *cp != '/';)
                    *sp++ = *cp++;
                *sp = 0;
            }
        }
    }

    /* Enable all layers to come up. */
    IpcpOpen(dev);

    return fp;
}
/*!
 * \brief Mount a partition.
 *
 * Nut/OS doesn't provide specific routines for mounting. Instead routines
 * for opening files are used.
 *
 * Applications should not directly call this function, but use the high
 * level stdio routines for opening a file.
 *
 * \param dev  Pointer to the MMC device.
 * \param name Partition number followed by a slash followed by a name
 *             of the file system device. Both items are optional. If no 
 *             file system driver name is given, the first file system
 *             driver found in the list of registered devices will be 
 *             used. If no partition number is specified or if partition
 *             zero is given, the first active primary partition will be 
 *             used.
 * \param mode Opening mode. Currently ignored, but 
 *             \code _O_RDWR | _O_BINARY \endcode should be used for
 *             compatibility with future enhancements.
 * \param acc  File attributes, ignored.
 *
 * \return Pointer to a newly created file pointer to the mounted
 *         partition or NUTFILE_EOF in case of any error.
 */
static NUTFILE *At91MciMount(NUTDEVICE * dev, CONST char *name, int mode, int acc)
{
    int partno = 0;
    int i;
    NUTDEVICE *fsdev;
    NUTFILE *nfp;
    MCIFCB *fcb;
    DOSPART *part;
    MCIFC *ifc = (MCIFC *) dev->dev_icb;
    FSCP_VOL_MOUNT mparm;

    if (At91MciDiscover(ifc)) {
        errno = ENODEV;
        return NUTFILE_EOF;
    }

    /* Parse the name for a partition number and a file system driver. */
    if (*name) {
        partno = atoi(name);
        do {
            name++;
        } while (*name && *name != '/');
        if (*name == '/') {
            name++;
        }
    }
#ifdef NUTDEBUG
    printf("['%s'-PART%d]", name, partno);
#endif

    /*
     * Check the list of registered devices for the given name of the
     * files system driver. If none has been specified, get the first
     * file system driver in the list. Hopefully the application
     * registered one only.
     */
    for (fsdev = nutDeviceList; fsdev; fsdev = fsdev->dev_next) {
        if (*name == 0) {
            if (fsdev->dev_type == IFTYP_FS) {
                break;
            }
        } else if (strcmp(fsdev->dev_name, name) == 0) {
            break;
        }
    }

    if (fsdev == 0) {
#ifdef NUTDEBUG
        printf("[No FSDriver]");
#endif
        errno = ENODEV;
        return NUTFILE_EOF;
    }

    if ((fcb = NutHeapAllocClear(sizeof(MCIFCB))) == 0) {
        errno = ENOMEM;
        return NUTFILE_EOF;
    }
    fcb->fcb_fsdev = fsdev;

    /* Initialize MMC access mutex semaphore. */
    NutEventPost(&mutex);

    /* Read MBR. */
    if (At91MciReadSingle(ifc, 0, fcb->fcb_blkbuf)) {
        NutHeapFree(fcb);
        return NUTFILE_EOF;
    }

    /* Read partition table. */
    part = (DOSPART *) & fcb->fcb_blkbuf[DOSPART_SECTORPOS];
    for (i = 1; i <= 4; i++) {
        if (partno) {
            if (i == partno) {
                /* Found specified partition number. */
                fcb->fcb_part = *part;
                break;
            }
        } else if (part->part_state & 0x80) {
            /* Located first active partition. */
            fcb->fcb_part = *part;
            break;
        }
        part++;
    }

    if (fcb->fcb_part.part_type == PTYPE_EMPTY) {
        NutHeapFree(fcb);
        return NUTFILE_EOF;
    }

    if ((nfp = NutHeapAlloc(sizeof(NUTFILE))) == 0) {
        NutHeapFree(fcb);
        errno = ENOMEM;
        return NUTFILE_EOF;
    }
    nfp->nf_next = 0;
    nfp->nf_dev = dev;
    nfp->nf_fcb = fcb;

    /*
     * Mount the file system volume.
     */
    mparm.fscp_bmnt = nfp;
    mparm.fscp_part_type = fcb->fcb_part.part_type;
    if (fsdev->dev_ioctl(fsdev, FS_VOL_MOUNT, &mparm)) {
        At91MciUnmount(nfp);
        return NUTFILE_EOF;
    }
    return nfp;
}