⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dspi.c

📁 Freescale MCF5445evb 参考测试代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * \param   txb     Buffer holding data to be written * \param   rxb     Buffer to hold read data * \param   length  Number of bytes to read/write * \return  Zero for success; Non-zero otherwise. *  * Write the buffer to the specified SPI device and read the receive * data into the receive buffer.  The receive buffer and transmit  * buffer pointers *can* point to the same buffer. This will stall to wait * for the DSPI to be available if it is busy with another transfer. */intspi_master_write_read(SPI_DEVICE *dev, uint8 *txb, uint8 *rxb, int length){    SPI_MSG_CHAIN m;    SPI_MSG_LINK l;        memset(&m, 0, sizeof(SPI_MSG_CHAIN));    m.device    = dev;    m.link      = &l;    memset(&l, 0, sizeof(SPI_MSG_LINK));    l.tx_buf    = txb;    l.rx_buf    = rxb;    l.length    = length;    l.next      = NULL;    /* Queue it up */    spi_master_enqueue(&m);        /* Wait for the transfer to finish */    while (m.status != SPI_MSG_CHAIN_DONE) {};    	return 0;}/********************************************************************//*! * Queue up a transfer * \param   msg     Message chain * \param   sync    Synchronous flag * \return  Zero for success; Non-zero otherwise. *  * Take a message chain as an argument and queue it up.  If the sync flag * is TRUE, then stall until the message is transferred.  Otherwise,  * return. The caller may specify a callback function in the message * struct or poll the status in the message data structure. *  * No checks are performed on the message data structure. Caller beware! */intspi_master_transfer(SPI_MSG_CHAIN *msg, int sync){    /* Queue it up */    spi_master_enqueue(msg);        if (sync == TRUE)    {        /* Wait for the transfer to finish */        while (msg->status != SPI_MSG_CHAIN_DONE) {};    }    	return 0;}/********************************************************************//*! * Enqueue a message to be transferred by the SPI master * \param   SPI_MSG_CHAIN Message to be transferred * \return  Zero for success; Non-zero otherwise. *  * Add the message to the SPI message queue.  This routine * is asynchronous; it will not wait for the transfer to complete * before returning to the caller. */static intspi_master_enqueue(SPI_MSG_CHAIN *message){    queue_add(&drv_data.queue, (QNODE *)message);    message->status = SPI_MSG_CHAIN_QUEUED;    if (drv_data.status == SPI_DRIVER_IDLE)         spi_master_tx();}/********************************************************************//*! * Interrupt handler for all DSPI interrupts */__interrupt__void spi_master_irq_handler (void){    uint32 dsr;    dsr = MCF_DSPI_DSR;    MCF_DSPI_DSR &= 0xFFFF0000;    if (dsr & MCF_DSPI_DSR_RFDF)    {        drv_data.event_rfd++;    }    if (dsr & MCF_DSPI_DSR_RFOF)    {        drv_data.event_rfo++;    }    if (dsr & MCF_DSPI_DSR_TFFF)    {        drv_data.event_tff++;    }    if (dsr & MCF_DSPI_DSR_TFUF)    {        drv_data.event_tfu++;    }    if (dsr & MCF_DSPI_DSR_EOQF)    {        drv_data.event_eoq++;        spi_master_rx();        spi_master_tx();    }    if (dsr & MCF_DSPI_DSR_TCF)    {        drv_data.event_tc++;    }} /********************************************************************/  /*!  * Start or continue a DSPI transmit  * \return Number of bytes stuffed into FIFO  *  * spi_master_tx() is called to start a new transfer (by spi_master_enqueue)  * or to continue an existing or queued transfer (by interupt handler).  */static intspi_master_tx (void){    int fifo, cnt, data, cs, dummy;    uint32 pushr;        if ((drv_data.status == SPI_DRIVER_IDLE) ||        ((drv_data.status == SPI_DRIVER_RUNNING) &&          (drv_data.chain->status == SPI_MSG_CHAIN_DONE)))    {        /* Pull the next message off the queue */        drv_data.chain = (SPI_MSG_CHAIN *)queue_remove(&drv_data.queue);        if (drv_data.chain == NULL)        {            drv_data.status = SPI_DRIVER_IDLE;            return 0;        }        ASSERT(drv_data.chain->link);                drv_data.tx     = drv_data.chain->link->tx_buf;        drv_data.rx     = drv_data.chain->link->rx_buf;        drv_data.tx_end = (void *)((int)drv_data.tx + drv_data.chain->link->length);        drv_data.rx_end = (void *)((int)drv_data.rx + drv_data.chain->link->length);        drv_data.status = SPI_DRIVER_RUNNING;        drv_data.chain->status = SPI_MSG_CHAIN_RUNNING;        if (drv_data.chain->link->next == NULL)            drv_data.last = drv_data.tx_end;        else            drv_data.last = NULL;            }    /* Calculate chip-select encoding */    if (drv_data.chain->device->cs_muxed)        cs = drv_data.chain->device->cs << 16;    else         cs = 1 << (drv_data.chain->device->cs + 16);        cnt = drv_data.tx_end - drv_data.tx;    if (cnt > SPI_FIFO_SIZE)        cnt = SPI_FIFO_SIZE;    fifo = cnt;    dummy = !drv_data.chain->link->tx_buf;        pushr = 0        | MCF_DSPI_PUSHR_CONT        | MCF_DSPI_PUSHR_CTAS(drv_data.chain->device->cs)        | cs;        while (cnt)    {        --cnt;        /*!         * \todo need some way to handle the case of an odd number of         * bytes being transferred for an otherwise 16bit word transfer         */        if (drv_data.chain->device->frame_size <= 8)        {            if (dummy)                data = 0;            else                data = *(uint8*)drv_data.tx;            drv_data.tx += 1;        }        else        {            if (dummy)                data = 0;            else                data = *(uint16*)drv_data.tx;            drv_data.tx += 2;        }                            /* Mark end-of-queue */        if (0 == cnt)        {            pushr |= MCF_DSPI_PUSHR_EOQ;                        /* Clear continuous bit at the end of a message chain */            if (drv_data.tx == drv_data.last)                pushr &= ~MCF_DSPI_PUSHR_CONT;        }                    MCF_DSPI_PUSHR = pushr | MCF_DSPI_PUSHR_TXDATA(data);                 }        return fifo;      }/********************************************************************/ /*!  * Pull data from the DSPI   * \return Number of bytes stuffed into FIFO  *  * This routine is only called by the interrupt handler.  Data is only  * received following an EOQ interrupt which will occur after the tx routine  * has placed real or fake data into the transmit FIFO and that data has  * all been shifted out.  At that time, the equivalent number receive bytes  * will be available in the FIFO.  */static intspi_master_rx (void){    int fifo, cnt, save;    uint16 rx_data;        cnt = drv_data.rx_end - drv_data.rx;    if (cnt > SPI_FIFO_SIZE)        cnt = SPI_FIFO_SIZE;    fifo = cnt;    save = (drv_data.chain->link->rx_buf != NULL);    /* Pull data from receive FIFO */    while (cnt)    {        --cnt;        rx_data = MCF_DSPI_POPR & 0xFFFF;                /*!         * \todo still need some way to handle the case of an odd number of         * bytes being transferred for an otherwise 16bit word transfer         */        if (drv_data.chain->device->frame_size <= 8)        {            if (save)                *(uint8*)drv_data.rx = rx_data;            drv_data.rx += 1;        }        else        {            if (save)                *(uint16*)drv_data.rx = rx_data;            drv_data.rx += 2;        }    }        /* Check for end of chain or end of link */    if (drv_data.rx >= drv_data.rx_end)    {        drv_data.chain->link = drv_data.chain->link->next;        if (drv_data.chain->link != NULL)        {            /* Update local pointers with info from next link */            drv_data.tx     = drv_data.chain->link->tx_buf;            drv_data.rx     = drv_data.chain->link->rx_buf;            drv_data.tx_end = (void *)((int)drv_data.tx + drv_data.chain->link->length);            drv_data.rx_end = (void *)((int)drv_data.rx + drv_data.chain->link->length);            drv_data.chain->status = SPI_MSG_CHAIN_RUNNING;            if (drv_data.chain->link->next == NULL)                drv_data.last = drv_data.tx_end;            else                drv_data.last = NULL;        }        else        {            drv_data.chain->status = SPI_MSG_CHAIN_DONE;                        if (drv_data.chain->callback != NULL)            {                /* Execute the callback function */                drv_data.chain->callback(drv_data.chain);            }        }    }    return fifo;}/********************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -