Esempio n. 1
0
/*!
 * \brief Configure the I2C bus controller (GPIO TWI implementation).
 *
 * This function is called by the platform independent code via the
 * NUTI2C_BUS::bus_conf function pointer. Most implementations will
 * also call this function during initialization to set the
 * default configuration.
 *
 * Right now only the bus clock rate is configurable.
 */
static int TwiBusConf(NUTI2C_BUS *bus)
{
    GPIO_TWICB *icb;
    long rate;

    /* Check parameters. */
    NUTASSERT(bus != NULL);
    NUTASSERT(bus->bus_icb != NULL);
    icb = (GPIO_TWICB *) bus->bus_icb;

    /* Get requested rate or use the default. */
    rate = bus->bus_rate;
    if (rate == 0) {
        rate = 100000L;
    }
    if (rate > 400000) {
        /* Speed out of range */
        return -1;
    }
    icb->delay_unit = 250000/rate;
    if (icb->delay_unit == 0)
        icb->delay_unit = 1;

    return 0;
}
Esempio n. 2
0
/*! 
 * \brief Transfer data on the SPI bus.
 *
 * A device must have been selected by calling GpioSpi0Select().
 *
 * \param node  Specifies the SPI bus node.
 * \param txbuf Pointer to the transmit buffer. If NULL, undetermined
 *              byte values are transmitted.
 * \param rxbuf Pointer to the receive buffer. If NULL, then incoming
 *              data is discarded.
 * \param xlen  Number of bytes to transfer.
 *
 * \return Always 0.
 */
int GpioSpiBus0Transfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
{
    GSPIREG *gspi;

    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_stat != NULL);
    gspi = (GSPIREG *)node->node_stat;

    /* We use dedicated static routines for each mode in the hope that 
    ** this improves the compiler's optimization for the inner loop. */
    switch (node->node_mode & SPI_MODE_3) {
    case SPI_MODE_0:
        SpiMode0Transfer(gspi, txbuf, rxbuf, xlen);
        break;
    case SPI_MODE_1:
        SpiMode1Transfer(gspi, txbuf, rxbuf, xlen);
        break;
    case SPI_MODE_2:
        SpiMode2Transfer(gspi, txbuf, rxbuf, xlen);
        break;
    case SPI_MODE_3:
        SpiMode3Transfer(gspi, txbuf, rxbuf, xlen);
        break;
    }
    return 0;
}
Esempio n. 3
0
/*! 
 * \brief Transfer data on the SPI bus in polling mode.
 *
 * A device must have been selected by calling At91SpiSelect().
 *
 * \param node Specifies the SPI bus node.
 * \param txbuf Pointer to the transmit buffer. If NULL, undetermined
 *              byte values are transmitted.
 * \param rxbuf Pointer to the receive buffer. If NULL, then incoming
 *              data is discarded.
 * \param xlen  Number of bytes to transfer.
 *
 * \return Always 0.
 */
int At91SpiBusPollTransfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
{
    uint8_t b = 0xff;
    uint8_t *txp = (uint8_t *) txbuf;
    uint8_t *rxp = (uint8_t *) rxbuf;
    uintptr_t base;

    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_bus != NULL);
    NUTASSERT(node->node_bus->bus_base != 0);
    base = node->node_bus->bus_base;

    while (xlen--) {
        if (txp) {
            b = *txp++;
        }
        /* Transmission starts by writing the transmit data. */
        outr(base + SPI_TDR_OFF, b);
        /* Wait for receiver data register full. */
        while((inr(base + SPI_SR_OFF) & SPI_RDRF) == 0);
        /* Read incoming data. */
        b = (uint8_t)inr(base + SPI_RDR_OFF);
        if (rxp) {
            *rxp++ = b;
        }
    }
    return 0;
}
Esempio n. 4
0
/*!
 * \brief File system specific functions.
 *
 * \param dev  Identifies the file system device that receives the
 *             control function.
 * \param req  Requested control function. May be set to one of the
 *             following constants:
 *             - FS_FILE_SEEK
 *             - FS_VOL_MOUNT, conf points to an FSCP_VOL_MOUNT structure.
 *             - FS_VOL_UNMOUNT, conf should be a NULL pointer.
 * \param conf Points to a buffer that contains any data required for
 *             the given control function or receives data from that
 *             function.
 *
 * \return 0 on success, -1 otherwise.
 */
static int RawFsIOCtl(NUTDEVICE * dev, int req, void *conf)
{
    int rc = -1;

    switch (req) {
    case FS_FILE_SEEK:
        NUTASSERT(conf != NULL);
        RawFsFileSeek((NUTFILE *) ((IOCTL_ARG3 *) conf)->arg1,  /* */
                      (long *) ((IOCTL_ARG3 *) conf)->arg2,     /* */
                      (int) ((IOCTL_ARG3 *) conf)->arg3);
        break;
    case FS_VOL_MOUNT:
        {
            /* Mount a volume. */
            FSCP_VOL_MOUNT *par = (FSCP_VOL_MOUNT *) conf;

            NUTASSERT(par != NULL);
            NUTASSERT(dev != NULL);
            rc = RawFsMount(dev, par->fscp_bmnt, par->fscp_part_type);
            if (rc) {
                /* Release resources on failures. */
                RawFsUnmount(dev);
            }
        }
        break;
    case FS_VOL_UNMOUNT:
        /* Unmount a volume. */
        NUTASSERT(dev != NULL);
        rc = RawFsUnmount(dev);
        break;
    }
    return rc;
}
Esempio n. 5
0
/*! \brief Select a device on the first SPI bus.
 *
 * Locks and activates the bus for the specified node.
 *
 * \param node Specifies the SPI bus node.
 * \param tmo  Timeout in milliseconds. To disable timeout, set this
 *             parameter to NUT_WAIT_INFINITE.
 *
 * \return 0 on success. In case of an error, -1 is returned and the bus 
 *         is not locked.
 */
int NplSpiBusSelect(NUTSPINODE * node, uint32_t tmo)
{
    int rc;

    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_bus != NULL);

    /* Allocate the bus. */
    rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
    if (rc) {
        errno = EIO;
    } else {
        /* If the mode update bit is set, then update our shadow registers. */
        if (node->node_mode & SPI_MODE_UPDATE) {
            NplSpiSetup(node);
        }

        /* Finally activate the node's chip select. */
        rc = NplSpiChipSelect(node->node_cs, 0);
        if (rc) {
            /* Release the bus in case of an error. */
            NutEventPost(&node->node_bus->bus_mutex);
        }
    }
    return rc;
}
Esempio n. 6
0
/*!
 * \brief Retrieve the size of a previously opened file.
 *
 * This function is called by the low level size routine of the C runtime 
 * library, using the _NUTDEVICE::dev_size entry.
 *
 * \param nfp Pointer to a \ref _NUTFILE structure, obtained by a 
 *            previous call to RawFsFileOpen().
 *
 * \return Size of the file.
 */
static long RawFsFileSize(NUTFILE * nfp)
{
    RAWVOLUME *vol;

    NUTASSERT(nfp != NULL);
    NUTASSERT(nfp->nf_dev != NULL);
    vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;

    return vol->vol_sect_cnt * vol->vol_sect_len;
}
Esempio n. 7
0
/*! 
 * \brief Transfer data on the SPI bus using double buffered PDC.
 *
 * A device must have been selected by calling At91SpiSelect().
 *
 * \todo Not yet done. Given up after SAM7SE SDRAM problems.
 *       Currently working fine on SAM7X platform
 * \todo Is this working asynchronously? Old comments mentioned that 
 *       the transfer might be still active when function returns.
 *
 * \param node Specifies the SPI bus node.
 * \param txbuf Pointer to the transmit buffer. If NULL, undetermined
 *              byte values are transmitted.
 * \param rxbuf Pointer to the receive buffer. If NULL, then incoming
 *              data is discarded.
 * \param xlen  Number of bytes to transfer.
 *
 * \return Always 0.
 */
int At91SpiBusDblBufTransfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
{
    uintptr_t base;
    uint32_t cr;
    uint32_t ir = 0;

#if defined(SPIBUS0_DOUBLE_BUFFER_HEURISTIC) || defined(SPIBUS1_DOUBLE_BUFFER_HEURISTIC)
    if (xlen < SPI_DOUBLE_BUFFER_MIN_TRANSFER_SIZE) {
        return At91SpiBusPollTransfer(node, txbuf, rxbuf, xlen);
    }
#endif

    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_bus != NULL);
    NUTASSERT(node->node_bus->bus_base != 0);
    base = node->node_bus->bus_base;

    outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);

    if (xlen) {
        /* Set first transmit pointer and counter. */
        if (txbuf) {
            outr(base + PERIPH_TPR_OFF, (uint32_t)txbuf);
        } else {
            outr(base + PERIPH_TPR_OFF, (uint32_t)rxbuf);
        }
        cr = PDC_TXTEN;
        outr(base + PERIPH_TCR_OFF, xlen);
        /* Set first receive pointer and counter. */
        if (rxbuf) {
            outr(base + PERIPH_RPR_OFF, (uint32_t)rxbuf);
            outr(base + PERIPH_RCR_OFF, xlen);
            cr |= PDC_RXTEN;
            ir = SPI_RXBUFF;
        } else {
            cr |= PDC_RXTDIS;
            ir = SPI_TXBUFE;
            outr(base + PERIPH_RPR_OFF, 0);
            outr(base + PERIPH_RCR_OFF, 0);
        }
        outr(base + PERIPH_TNPR_OFF, 0);
        outr(base + PERIPH_TNCR_OFF, 0);
        outr(base + PERIPH_RNPR_OFF, 0);
        outr(base + PERIPH_RNCR_OFF, 0);

        outr(base + SPI_IDR_OFF, (unsigned int) - 1);
        outr(base + SPI_IER_OFF, ir);
        outr(base + PERIPH_PTCR_OFF, cr);
        
        NutEventWait(&node->node_bus->bus_ready, NUT_WAIT_INFINITE);
        outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
    }
    return 0;
}
Esempio n. 8
0
/*!
 * \brief Update SPI shadow registers.
 *
 * \param node Specifies the SPI bus node.
 *
 * \return Always 0.
 */
int At91SpiSetup(NUTSPINODE * node)
{
    uint32_t clk;
    uint32_t clkdiv;
    AT91SPIREG *spireg;

    NUTASSERT(node != NULL);
    NUTASSERT(node->node_stat != NULL);
    NUTASSERT(node->node_bus != NULL);
    NUTASSERT(node->node_bus->bus_base != 0);
    spireg = node->node_stat;

    spireg->at91spi_mr &= ~(SPI_MODFDIS | SPI_LLB);
    if ((node->node_mode & SPI_MODE_FAULT) == 0) {
        spireg->at91spi_mr |= SPI_MODFDIS;
    }
    if (node->node_mode & SPI_MODE_LOOPBACK) {
        spireg->at91spi_mr |= SPI_LLB;
    }

    spireg->at91spi_csr &= ~(SPI_BITS | SPI_CPOL | SPI_NCPHA | SPI_CSAAT | SPI_SCBR);
    if (node->node_bits) {
        spireg->at91spi_csr |= ((uint32_t)(node->node_bits - 8) << SPI_BITS_LSB) & SPI_BITS;
    }
    if (node->node_mode & SPI_MODE_CPOL) {
        spireg->at91spi_csr |= SPI_CPOL;
    }
    if ((node->node_mode & SPI_MODE_CPHA) == 0) {
        spireg->at91spi_csr |= SPI_NCPHA;
    }
    if (node->node_mode & SPI_MODE_CSKEEP) {
        spireg->at91spi_csr |= SPI_CSAAT;
    }

    /* Query peripheral clock. */
    clk = NutClockGet(NUT_HWCLK_PERIPHERAL);
    /* Calculate the SPI clock divider. Avoid rounding errors. */
    clkdiv = (clk + node->node_rate - 1) / node->node_rate;
    /* The divider value minimum is 1. */
    if (clkdiv < 1) {
        clkdiv++;
    }
    /* The divider value maximum is 255. */
    else if (clkdiv > 255) {
        clkdiv = 255;
    }
    spireg->at91spi_csr |= clkdiv << SPI_SCBR_LSB;

    /* Update interface parameters. */
    node->node_rate = clk / clkdiv;
    node->node_mode &= ~SPI_MODE_UPDATE;

    return 0;
}
Esempio n. 9
0
/*!
 * \brief Transfer data on the SPI bus using single buffered interrupt mode.
 *
 * A device must have been selected by calling At91SpiSelect().
 *
 * \param node  Specifies the SPI bus node.
 * \param txbuf Pointer to the transmit buffer. If NULL, undetermined
 *              byte values are transmitted.
 * \param rxbuf Pointer to the receive buffer. If NULL, then incoming
 *              data is discarded.
 * \param xlen  Number of bytes to transfer.
 *
 * \return Always 0.
 */
static int Stm32SpiBusTransfer(NUTSPINODE * node, const void *txbuf, void *rxbuf, int xlen)
{
    SPI_TypeDef* base;
  //  DMA_Channel_TypeDef* channel_rx,*channel_tx;


    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_bus != NULL);
    NUTASSERT(node->node_bus->bus_base != 0);
    base = (SPI_TypeDef*)node->node_bus->bus_base;

   /* if(base == SPI1_BASE){
        channel_rx=DMA1_Channel2;
        channel_tx=DMA1_Channel3;
    }else if(base == SPI2_BASE){
        channel_rx=DMA1_Channel4;
        channel_tx=DMA1_Channel5;
    }else if(base == SPI3_BASE){
        channel_rx=DMA2_Channel1;
        channel_tx=DMA2_Channel2;
    };*/
//    DMA_Setup(channel_rx,(void*)rxbuf,(void*)(&(base->DR)),xlen,DMA_DIR_PeripheralSRC|DMA_MemoryDataSize_Byte|DMA_PeripheralDataSize_Byte|DMA_Priority_VeryHigh|DMA_IT_TC);//rx
//    DMA_Setup(channel_tx,(void*)txbuf,(void*)(&(base->DR)),xlen,DMA_DIR_PeripheralDST|DMA_MemoryDataSize_Byte|DMA_PeripheralDataSize_Byte|DMA_Priority_VeryHigh|DMA_IT_TC);//tx
//    DMA_Enable(channel_rx);DMA_Enable(channel_tx);

//    DMA_Register_Interrupt(channel_rx,&SPI_QUE);

    Stm32SpiEnable(base);

    unsigned char * tx = (unsigned char*)txbuf;
    unsigned char * rx = (unsigned char*)rxbuf;

    while( xlen-- > 0){
        unsigned char b = tx ? (* tx ++) : 0xff;

        base->DR = b;
        /* wait until receive buffer no longer empty */
        while ( ( base->SR & SPI_SR_RXNE ) == 0 ) {
    }

    b = base->DR;

    if( rx ) {
      * rx ++ = b;
    }
  }

//    NutEventWait(&SPI_QUE,0);
    Stm32SpiDisable(base);
    return 0;

}
Esempio n. 10
0
/*!
 * \brief Write data to a file.
 *
 * \param nfp    Pointer to a \ref NUTFILE structure, obtained by a previous 
 *               call to RawFsFileOpen().
 * \param buffer Pointer to the data to be written. If zero, then the
 *               output buffer will be flushed.
 * \param len    Number of bytes to write.
 *
 * \return The number of bytes written. A return value of -1 indicates an 
 *         error.
 */
int RawFsFileWrite(NUTFILE * nfp, CONST void *buffer, int len)
{
    int rc;
    int step;
    uint8_t *buf;
    RAWFILE *fcb;
    RAWVOLUME *vol;

    NUTASSERT(nfp != NULL);

    /* Flush file if buffer is a NULL pointer. */
    if (buffer == NULL || len == 0) {
        return RawFsFileFlush(nfp);
    }

    /* Sanity check. */
    NUTASSERT(nfp->nf_fcb != NULL);
    NUTASSERT(nfp->nf_dev != NULL);
    NUTASSERT(nfp->nf_dev->dev_dcb != NULL);

    fcb = (RAWFILE *) nfp->nf_fcb;
    vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;

    /*
     * Write the data.
     */
    buf = (uint8_t *) buffer;
    for (rc = 0, step = 0; rc < len; rc += step) {
        /* Did we reach the end of a sector? */
        if (fcb->f_sect_pos >= vol->vol_sect_len) {
            /* Yes, move to the next sector. */
            fcb->f_sect_num++;
            fcb->f_sect_pos -= vol->vol_sect_len;
        }
        /* Load the sector we want to write to. */
        if (RawFsSectorLoad(nfp->nf_dev, fcb->f_sect_num)) {
            rc = -1;
            break;
        }
        /* The number of bytes we write to this sector. */
        step = (int) (vol->vol_sect_len - fcb->f_sect_pos);
        if (step > len - rc) {
            step = len - rc;
        }
        /* Copy data to this sector. */
        memcpy(&vol->vol_sect_buf[fcb->f_sect_pos], &buf[rc], step);
        vol->vol_sect_dirty = 1;
        /* Advance file pointers. */
        fcb->f_pos += step;
        fcb->f_sect_pos += step;
    }
    return rc;
}
Esempio n. 11
0
/*!
 * \brief Save Nut/OS configuration in non-volatile memory.
 *
 * Since Nut/OS version 4.7.5, this routine is no longer called automatically 
 * during system initialization. Thus, if NutLoadConfig() fails, then the 
 * non-volatile memory remains invalid and NutLoadConfig() will again fail 
 * during the next system start.
 *
 * \return 0 if OK, -1 on failures.
 */
int NutSaveConfig(void)
{
    /* Sanity checks. */
    NUTASSERT(sizeof(CONFOS) <= 255);
    NUTASSERT(strlen(confos.hostname) <= MAX_HOSTNAME_LEN);

    /* Update the magic part. */
    confos.size = sizeof(CONFOS);
    memcpy(confos.magic, CONFOS_EE_MAGIC, sizeof(CONFOS_EE_MAGIC) - 1);

    return NutNvMemSave(CONFOS_EE_OFFSET, &confos, sizeof(CONFOS));
}
Esempio n. 12
0
/*! \brief Deselect a device on the first SPI bus.
 *
 * Deactivates the chip select and unlocks the bus.
 *
 * \param node Specifies the SPI bus node.
 *
 * \return Always 0.
 */
int NplSpiBusDeselect(NUTSPINODE * node)
{
    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_bus != NULL);

    /* Deactivate the node's chip select. */
    NplSpiChipSelect(node->node_cs, 1);

    /* Release the bus. */
    NutEventPost(&node->node_bus->bus_mutex);

    return 0;
}
Esempio n. 13
0
/*! \brief Deselect a device on the SPI bus.
 *
 * Deactivates the chip select and unlocks the bus.
 *
 * \param node Specifies the SPI bus node.
 *
 * \return Always 0.
 */
int GpioSpiBus0Deselect(NUTSPINODE * node)
{
    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_bus != NULL);

    /* Deactivate the node's chip select. */
    GpioSpi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);

    /* Release the bus. */
    NutEventPost(&node->node_bus->bus_mutex);

    return 0;
}
Esempio n. 14
0
/*! \brief Deselect a device on the SPI bus.
 *
 * Deactivates the chip select and unlocks the bus.
 *
 * \param node Specifies the SPI bus node.
 *
 * \return Always 0.
 */
static int Stm32SpiBusDeselect(NUTSPINODE * node)
{
    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_bus != NULL);

    NutSpiBusWait(node, NUT_WAIT_INFINITE);
    /* Deactivate the node's chip select. */
    Stm32SpiChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);

    /* Release the bus. */
    NutEventPostAsync(&node->node_bus->bus_mutex);

    return 0;
}
Esempio n. 15
0
/*!
 * \brief Return the length of a file.
 * 
 * \param fd   Descriptor of a previously opened file, device or
 *             connected socket.
 *
 * \return Filelength in bytes or -1 in case of an error.
 */
long _filelength(int fd)
{
    NUTFILE *fp = (NUTFILE *) ((uintptr_t) fd);
    NUTDEVICE *dev;
    long l;

    NUTASSERT(fp != NULL);
    dev = fp->nf_dev;
    if (dev == 0) {
        NUTVIRTUALDEVICE *vdv = (NUTVIRTUALDEVICE *) fp;
        if (vdv->vdv_ioctl && vdv->vdv_ioctl(vdv, IOCTL_GETFILESIZE, &l) == 0)
            return l;
        else {
            errno = EBADF;
            return -1;
        }
    }

    if (dev->dev_size == 0) {
        errno = EBADF;
        return -1;
    }

    return (*dev->dev_size) (fp);
}
Esempio n. 16
0
/*! 
 * \brief Initialize an SPI bus node. 
 *
 * This routine is called for each SPI node, which is registered via 
 * NutRegisterSpiDevice().
 *
 * \param node Specifies the SPI bus node.
 *
 * \return 0 on success or -1 if there is no valid chip select.
 */
int NplSpiBusNodeInit(NUTSPINODE * node)
{
    int rc;

    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_bus != NULL);

    /* Try to deactivate the node's chip select. */
    rc = NplSpiChipSelect(node->node_cs, 1);

    if (rc == 0) {
        NplSpiSetup(node);
    }
    return rc;
}
Esempio n. 17
0
/*! 
 * \brief Transfer data on the SPI bus in polling mode.
 *
 * A device must have been selected by calling NplSpiSelect().
 *
 * \param node Specifies the SPI bus node.
 * \param txbuf Pointer to the transmit buffer. If NULL, undetermined
 *              byte values are transmitted.
 * \param rxbuf Pointer to the receive buffer. If NULL, then incoming
 *              data is discarded.
 * \param xlen  Number of bytes to transfer.
 *
 * \return Always 0.
 */
int NplSpiBusPollTransfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
{
    uint8_t rxc;
    uint8_t txc = 0xFF;
    uint8_t *txp = (uint8_t *) txbuf;
    uint8_t *rxp = (uint8_t *) rxbuf;

    /* Sanity check. */
    NUTASSERT(node != NULL);

    while (xlen--) {
        if (txp) {
            txc = *txp++;
        }
        /* Transmission starts by writing the transmit data. */
        outb(NPL_MMCDR, txc);
        /* Wait for receiver data register full. */
        while ((inb(NPL_SLR) & NPL_MMCREADY) == 0);
        /* Read incoming data. */
        rxc = inb(NPL_MMCDR);
        if (rxp) {
            *rxp++ = rxc;
        }
    }
    return 0;
}
Esempio n. 18
0
/*!
 * \brief Update SPI shadow registers.
 *
 * \param node Specifies the SPI bus node.
 *
 * \return Always 0.
 */
static int NplSpiSetup(NUTSPINODE * node)
{
#if defined(NUT_PLL_NPLCLK1)
    uint32_t clk;
    uint32_t clkdiv;

    NUTASSERT(node != NULL);

    /* Query the PLL number routed to Clock B. */
    clk = Cy2239xGetPll(NUT_PLL_NPLCLK1);
    /* Get the frequency of this PLL. */
    clk = Cy2239xPllGetFreq((int)clk, 7);
    /* Calculate the required divider value. */
    clkdiv = (clk + NPL_MMC_CLOCK - 10) / NPL_MMC_CLOCK;

    /* 
     * Not sure about the Cy-routines. The DIVSEL bit specifies which
     * divider is used, which is indirectly connected to S2, which is
     * high by default. For now set both dividers. 
     */
    if (Cy2239xSetDivider(NUT_PLL_NPLCLK1, 1, (int)clkdiv)) {
        return -1;
    }
    if (Cy2239xSetDivider(NUT_PLL_NPLCLK1, 0, (int)clkdiv)) {
        return -1;
    }

    /* Update interface parameters. */
    node->node_rate = clk / clkdiv;
    node->node_mode &= ~SPI_MODE_UPDATE;
#endif

    return 0;
}
Esempio n. 19
0
/*!
 * \brief Insert a new timer in the global timer list.
 *
 * Applications should not call this function.
 *
 * \param tn Pointer to the timer structure to insert.
 *
 * \todo Make this local function static.
 */
void NutTimerInsert(NUTTIMERINFO * tn)
{
    NUTTIMERINFO *tnp;

    NUTASSERT(tn != NULL);

    tn->tn_prev = NULL;
    for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
        if (tn->tn_ticks_left < tnp->tn_ticks_left) {
            tnp->tn_ticks_left -= tn->tn_ticks_left;
            break;
        }
        tn->tn_ticks_left -= tnp->tn_ticks_left;
        tn->tn_prev = tnp;
    }
    tn->tn_next = tnp;
    if (tn->tn_next) {
        tn->tn_next->tn_prev = tn;
    }
    if (tn->tn_prev) {
        tn->tn_prev->tn_next = tn;
    }
    else {
        nutTimerList = tn;
    }
}
Esempio n. 20
0
/*!
 * \brief Stop a specified timer.
 *
 * Only periodic timers need to be stopped. One-shot timers
 * are automatically stopped by the timer management after
 * ther first timer interval. Anyway, long running one-shot
 * timers may be stopped to release the occupied memory.
 *
 * \param handle Identifies the timer to be stopped. This handle must
 *               have been created by calling NutTimerStart() or
 *               NutTimerStartTicks().
 */
void NutTimerStop(HANDLE handle)
{
    NUTTIMERINFO *tn = (NUTTIMERINFO *)handle;

    NUTASSERT(tn != NULL);
#ifdef NUTDEBUG
    if (__os_trf)
        fprintf(__os_trs, " TIM %p NutTimerStop\n", handle);
#endif
    /* Disable periodic operation and callback. */
    tn->tn_ticks = 0;
    tn->tn_callback = NULL;
    /* If not already elapsed, expire the timer. */
    if (tn->tn_ticks_left) {
        if (tn->tn_prev) {
            tn->tn_prev->tn_next = tn->tn_next;
        }
        else {
            nutTimerList = tn->tn_next;
        }
        if (tn->tn_next) {
            tn->tn_next->tn_prev = tn->tn_prev;
            tn->tn_next->tn_ticks_left += tn->tn_ticks_left;
        }
        tn->tn_ticks_left = 0;
        NutTimerInsert(tn);
    }
}
Esempio n. 21
0
int _seek(int fd, long offset, int origin)
{
    NUTFILE *fp = (NUTFILE *) ((uintptr_t) fd);
    NUTDEVICE *dev;
    IOCTL_ARG3 conf;

    NUTASSERT(fp != NULL);

    conf.arg1 = (void*) fp;
    conf.arg2 = (void*) &offset;
    conf.arg3 = (void*) origin;

    dev = fp->nf_dev;
    if (dev != 0) {
        if ((*dev->dev_ioctl) (dev, FS_FILE_SEEK, &conf)) {
            return 0;
        } else {
            errno = EINVAL;
            return -1;
        }
    } else {
        errno = EINVAL;
        return -1;
    }
}
Esempio n. 22
0
/*!
 * \brief Load Nut/OS configuration from non-volatile memory.
 *
 * This routine is automatically called during system initialization.
 * It tries to read the OS configuration structure \ref CONFOS from
 * non-volatile memory, starting at /ref CONFOS_EE_OFFSET.
 *
 * The routine may fail, if 
 * - non-volatile memory is not supported,
 * - non-volatile memory contains invalid data,
 * - the configuration structure has changed.
 *
 * \return 0 if OK, -1 on failures, in which case the hostname will
 *         be set to \ref CONFOS_VIRGIN_HOSTNAME.
 */
int NutLoadConfig(void)
{
    /* Sanity check. */
    NUTASSERT(sizeof(CONFOS) <= 255);

    if (NutNvMemLoad(CONFOS_EE_OFFSET, &confos, sizeof(CONFOS)) == 0 /* If loaded... */
        && confos.size == sizeof(CONFOS) /* ...check magic size and cookie. */
        && memcmp(confos.magic, CONFOS_EE_MAGIC, sizeof(CONFOS_EE_MAGIC) - 1) == 0) {
            return 0;
    }

    /* No valid configuration, set virgin hostname. */
    NUTASSERT(sizeof(confos.hostname) > strlen(CONFOS_VIRGIN_HOSTNAME));
    strcpy(confos.hostname, CONFOS_VIRGIN_HOSTNAME);

    return -1;
}
Esempio n. 23
0
/*!
 * \brief Move file pointer to a specified position.
 *
 * Moving beyond the current file size is not supported.
 *
 * \param nfp    File descriptor.
 * \param pos    Requested file position.
 * \param whence Positioning directive.
 *
 * \return 0 on success, -1 otherwise. In the latter case the position
 *         is unspecified.
 */
static int RawFsFileSeek(NUTFILE * nfp, long *pos, int whence)
{
    int rc = 0;
    long npos;
    RAWFILE *fcb;

    NUTASSERT(nfp != NULL);
    NUTASSERT(nfp->nf_fcb != NULL);
    fcb = nfp->nf_fcb;

    NUTASSERT(pos != NULL);
    npos = *pos;

    switch (whence) {
    case SEEK_CUR:
        /* Relative to current position. */
        npos += fcb->f_pos;
        break;
    case SEEK_END:
        /* Relative to file end. */
        npos += RawFsFileSize(nfp);
        break;
    }

    /* Make sure that we are within limits. */
    if (npos < 0 || npos > RawFsFileSize(nfp)) {
        errno = EINVAL;
        rc = -1;
    } else {
        RAWVOLUME *vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;

        NUTASSERT(nfp != NULL);
        NUTASSERT(nfp != NULL);
        vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;

        *pos = npos;
        fcb->f_pos = npos;
        fcb->f_sect_num = 0;
        while (npos >= (long)vol->vol_sect_len) {
            fcb->f_sect_num++;
            npos -= vol->vol_sect_len;
        }
        fcb->f_sect_pos = npos;
    }
    return rc;
}
Esempio n. 24
0
/*!
 * \brief Reentrant variant of RawFsFileOpen().
 */
static NUTFILE *RawFsApiFileOpen(NUTDEVICE * dev, CONST char *path, int mode, int acc)
{
    NUTFILE *rc;
    RAWVOLUME *vol;

    NUTASSERT(dev != NULL);
    vol = (RAWVOLUME *) dev->dev_dcb;
    NUTASSERT(vol != NULL);

    /* Lock filesystem access. */
    NutEventWait(&vol->vol_fsmutex, 0);
    /* Call worker routine. */
    rc = RawFsFileOpen(dev, path, mode, acc);
    /* Release filesystem lock. */
    NutEventPost(&vol->vol_fsmutex);

    return rc;
}
Esempio n. 25
0
/*!
 * \brief Load sector.
 *
 * \param dev  Specifies the file system device.
 * \param sect Sector to load.
 *
 * \return 0 on success, -1 on failures.
 */
static int RawFsSectorLoad(NUTDEVICE * dev, uint32_t sect)
{
    int rc = -1;
    RAWVOLUME *vol;

    NUTASSERT(dev != NULL);
    vol = (RAWVOLUME *) dev->dev_dcb;

    /* Gain mutex access. */
    NUTASSERT(vol != NULL);
    NutEventWait(&vol->vol_iomutex, 0);

    /* Nothing to do if sector is already loaded. */
    if (vol->vol_sect_num == sect) {
        rc = 0;
    }
    /* Make sure that the sector buffer is clean. */
    else if (RawFsSectorFlush(dev) == 0) {
        NUTFILE *blkmnt = dev->dev_icb;
        NUTDEVICE *blkdev = blkmnt->nf_dev;
        BLKPAR_SEEK pars;

        blkmnt = dev->dev_icb;
        NUTASSERT(blkmnt != NULL);
        blkdev = blkmnt->nf_dev;
        NUTASSERT(blkdev != NULL);

        /* Set the block device's sector position. */
        pars.par_nfp = blkmnt;
        pars.par_blknum = sect;
        if ((*blkdev->dev_ioctl) (blkdev, NUTBLKDEV_SEEK, &pars) == 0) {
            /* Read a single block from the device. */
            if ((*blkdev->dev_read) (blkmnt, vol->vol_sect_buf, 1) == 1) {
                vol->vol_sect_num = sect;
                rc = 0;
            }
        }
    }

    /* Release mutex access. */
    NutEventPostAsync(&vol->vol_iomutex);

    return rc;
}
Esempio n. 26
0
/*!
 * \brief Reentrant variant of RawFsFileRead().
 */
static int RawFsApiFileRead(NUTFILE * nfp, void *buffer, int size)
{
    int rc;
    RAWVOLUME *vol;

    NUTASSERT(nfp != NULL);
    NUTASSERT(nfp->nf_dev != NULL);
    vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
    NUTASSERT(vol != NULL);

    /* Lock filesystem access. */
    NutEventWait(&vol->vol_fsmutex, 0);
    /* Call worker routine. */
    rc = RawFsFileRead(nfp, buffer, size);
    /* Release filesystem lock. */
    NutEventPost(&vol->vol_fsmutex);

    return rc;
}
Esempio n. 27
0
/*!
 * \brief Write a character to a stream.
 *
 * \param c      Character to write.
 * \param stream Pointer to a previously opened stream.
 *
 * \return The character written or EOF to indicate an error.
 *
 * \warning The function will not check, if the stream pointer points
 *          to a valid stream.
 */
int fputc(int c, FILE * stream)
{
    char ch = (char) c;

    NUTASSERT(stream != NULL);
    if (_write(stream->iob_fd, &ch, 1) != 1)
        c = EOF;

    return c;
}
Esempio n. 28
0
/*!
 * \brief I2C bus transfer (STM I2C implementation).
 *
 * This function is called by the platform independent code via the
 * NUTI2C_BUS::bus_tran function pointer.
 */
static int I2cBusTran(NUTI2C_SLAVE *slave, NUTI2C_MSG *msg)
{
    NUTI2C_BUS *bus;
    STM32_I2CCB *icb;
    I2C_TypeDef *i2c;
    uint32_t cr2;
    int rc = 0;

    bus = slave->slave_bus;
    NUTASSERT(bus != NULL);
    NUTASSERT(bus->bus_icb != NULL);
    icb = (STM32_I2CCB *) bus->bus_icb;
    icb->icb_msg = msg;
    icb->errors = 0;
    i2c = (I2C_TypeDef *) icb->icb_base;
    cr2 = i2c->CR2;
    cr2 &= 0xf8000000; /* Clean out */
    cr2 |= slave->slave_address << 1;
    msg->msg_widx = 0;
    msg->msg_ridx = 0;
    /* are there bytes to write? */
    if (msg->msg_wlen)
    {
        i2c->CR1 |= I2C_CR1_TXIE | I2C_CR1_TCIE | I2C_CR1_STOPIE | I2C_CR1_NACKIE;
        if (msg->msg_wlen > 0xff)
            cr2 |= I2C_CR2_NBYTES | I2C_CR2_RELOAD;
        else
            cr2 |= msg->msg_wlen << 16;
    }
    else if (msg->msg_rsiz)
    {
        i2c->CR1 |= I2C_CR1_RXIE | I2C_CR1_STOPIE  | I2C_CR1_NACKIE;
        if (msg->msg_rsiz > 0xff)
            cr2 |= I2C_CR2_RD_WRN | I2C_CR2_NBYTES | I2C_CR2_RELOAD;
        else
            cr2 |= I2C_CR2_RD_WRN | msg->msg_rsiz << 16;
    }
    i2c->CR2 = cr2 | I2C_CR2_START;
    rc = NutEventWait(&icb->icb_queue, slave->slave_timeout);
    if ((icb->errors) || (rc))
        msg->msg_ridx = -1;
    return msg->msg_ridx;
}
Esempio n. 29
0
/*!
 * \brief Read data from a file.
 *
 * \param nfp    Pointer to a \ref NUTFILE structure, obtained by a previous 
 *               call to RawFsFileOpen().
 * \param buffer Pointer to the data buffer to fill.
 * \param size   Maximum number of bytes to read.
 *
 * \return The number of bytes actually read. A return value of -1 indicates 
 *         an error.
 */
int RawFsFileRead(NUTFILE * nfp, void *buffer, int size)
{
    int rc;
    int step;
    uint8_t *buf;
    RAWVOLUME *vol;
    RAWFILE *fcb;

    /* Ignore input flush. */
    if (buffer == NULL || size == 0) {
        return 0;
    }

    NUTASSERT(nfp != NULL);
    NUTASSERT(nfp->nf_dev != NULL);
    fcb = nfp->nf_fcb;
    NUTASSERT(fcb != NULL);
    vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
    NUTASSERT(vol != NULL);

    buf = (uint8_t *) buffer;
    for (rc = 0, step = 0; rc < size; rc += step) {
        /* Did we reach the end of a sector? */
        if (fcb->f_sect_pos >= vol->vol_sect_len) {
            /* Yes, move to the next sector. */
            fcb->f_sect_num++;
            fcb->f_sect_pos -= vol->vol_sect_len;
        }
        /* Make sure that the required sector is loaded. */
        if (RawFsSectorLoad(nfp->nf_dev, fcb->f_sect_num)) {
            rc = -1;
            break;
        }
        step = (int) (vol->vol_sect_len - fcb->f_sect_pos);
        if (step > size - rc) {
            step = size - rc;
        }
        memcpy(&buf[rc], &vol->vol_sect_buf[fcb->f_sect_pos], step);
        fcb->f_pos += step;
        fcb->f_sect_pos += step;
    }
    return rc;
}
Esempio n. 30
0
/*!
 * \brief Mimic initialization without actually registering the device.
 *
 * This is a little bit tricky. If we want to use the existing DataFlash
 * routines for accessing the system configuration, they must be
 * properly initialized. This is normally done by calling NutRegister...
 * in the application. However, the system configuration must be know
 * before entering any application code.
 * 
 */
static int SpiAt45dConfigDevice(void)
{
#if !defined(DEV_SPIBUS)
    return -1;
#else /* DEV_SPIBUS */
    if (devSysConf == NULL) {
        NUTSPINODE *node;
        NUTDEVICE *dev;
#if NUT_CONFIG_AT45D == 0
        dev = &devSpiAt45d0;
#elif NUT_CONFIG_AT45D == 1
        dev = &devSpiAt45d1;
#elif NUT_CONFIG_AT45D == 2
        dev = &devSpiAt45d2;
#elif NUT_CONFIG_AT45D == 3
        dev = &devSpiAt45d3;
#else
        return -1;
#endif
        node = (NUTSPINODE *) dev->dev_icb;
        NUTASSERT(node != NULL);
        if (node->node_bus == NULL) {
            NUTSPIBUS *bus;
            bus = &DEV_SPIBUS;
            node->node_bus = bus;
        }
#ifdef NUT_CONFIG_AT45D_CS
        node->node_cs = NUT_CONFIG_AT45D_CS;
#endif
        NUTASSERT(node->node_bus->bus_initnode != NULL);
        if ((*node->node_bus->bus_initnode) (node)) {
            return -1;
        }
        NutEventPost(&node->node_bus->bus_mutex);
        if (SpiAt45dInit(dev)) {
            return -1;
        }
        devSysConf = dev;
    }
    return 0;
#endif /* DEV_SPIBUS */
}