/*FUNCTION*------------------------------------------------------------------- * * Function Name : _kuart_period_isr * Returned Value : void * Comments : * Periodic interrupt for mix uart. * *END*----------------------------------------------------------------------*/ static void _kuart_period_isr(void * data_ptr) { IO_SERIAL_INT_DEVICE_STRUCT_PTR int_io_dev_ptr = data_ptr; KUART_INFO_STRUCT_PTR sci_info_ptr = int_io_dev_ptr->DEV_INFO_PTR; uint32_t dmaUC, dmaC; _int_disable(); dma_channel_status(sci_info_ptr->RX_DCH, &sci_info_ptr->RX_DMA_SEQ, &dmaUC); dmaC = int_io_dev_ptr->IQUEUE_SIZE - dmaUC; if (_QUEUE_GET_SIZE(int_io_dev_ptr->IN_WAITING_TASKS)) { if((int64_t)(dmaC + sci_info_ptr->dmaC - sci_info_ptr->readC) >= sci_info_ptr->rxwakeupnum){ _taskq_resume(int_io_dev_ptr->IN_WAITING_TASKS, TRUE); } } _int_enable(); }
_mqx_int _io_serial_mix_read ( /* [IN] the handle returned from _fopen */ FILE_DEVICE_STRUCT_PTR fd_ptr, /* [IN] where the characters are to be stored */ char *data_ptr, /* [IN] the number of characters to input */ _mqx_int num ) { /* Body */ IO_DEVICE_STRUCT_PTR io_dev_ptr; IO_SERIAL_INT_DEVICE_STRUCT_PTR int_io_dev_ptr; KUART_INFO_STRUCT_PTR sci_info_ptr; uint32_t dmaUC = 0, dmaC = 0; uint32_t queueSize = 0; uint8_t *dmaBuffer = NULL; uint32_t dmaOff = 0, readOff = 0; io_dev_ptr = fd_ptr->DEV_PTR; int_io_dev_ptr = (void *)io_dev_ptr->DRIVER_INIT_PTR; sci_info_ptr = int_io_dev_ptr->DEV_INFO_PTR; queueSize = int_io_dev_ptr->IQUEUE_SIZE; dmaBuffer = (uint8_t *)sci_info_ptr->RX_BUF; _int_disable(); dma_channel_status(sci_info_ptr->RX_DCH, &sci_info_ptr->RX_DMA_SEQ, &dmaUC); dmaC = queueSize - dmaUC; #if 1 if((int64_t)(dmaC + sci_info_ptr->dmaC - sci_info_ptr->readC) < num){ sci_info_ptr->rxwakeupnum = num; _int_enable(); _taskq_suspend(int_io_dev_ptr->IN_WAITING_TASKS); _int_disable(); dma_channel_status(sci_info_ptr->RX_DCH, &sci_info_ptr->RX_DMA_SEQ, &dmaUC); dmaC = queueSize - dmaUC; } #endif #if 0 while((int64_t)(dmaC + sci_info_ptr->dmaC - sci_info_ptr->readC) < num){ sci_info_ptr->rxwakeupnum = num; _int_enable(); _taskq_suspend(int_io_dev_ptr->IN_WAITING_TASKS); //_sched_yield(); _int_disable(); dma_channel_status(sci_info_ptr->RX_DCH, &sci_info_ptr->RX_DMA_SEQ, &dmaUC); dmaC = queueSize - dmaUC; } #endif if((int64_t)(dmaC + sci_info_ptr->dmaC - sci_info_ptr->readC) > queueSize){ printf("UART dma buffer full! Reset read header. \n"); sci_info_ptr->readC = dmaC + sci_info_ptr->dmaC - num; } dmaOff = (dmaC + sci_info_ptr->dmaC) % queueSize; readOff = sci_info_ptr->readC % queueSize; if(readOff + num > queueSize){ memcpy(data_ptr, dmaBuffer + readOff, queueSize - readOff); memcpy(data_ptr + queueSize - readOff, dmaBuffer, readOff + num - queueSize); }else{ memcpy(data_ptr, dmaBuffer + readOff, num); } sci_info_ptr->readC += num; _int_enable(); //printf("mix read %d bytes, dmaC %d \n", num, dmaC); return num; } /* Endbody */
/*FUNCTION**************************************************************** * * Function Name : _dspi_dma_transfer * Returned Value : number of bytes transferred * Comments : * Internal routine performing actual DMA transfer of given width * If txbuf is NULL the function expects dummy pattern already prepared in dspi_info_ptr->TX_BUFFER * *END*********************************************************************/ static _mqx_int _dspi_dma_transfer ( /* [IN] Device specific context structure */ DSPI_DMA_INFO_STRUCT_PTR dspi_info_ptr, /* [IN] Data to transmit */ uint8_t *txbuf, /* [OUT] Received data */ uint8_t *rxbuf, /* [IN] Length of transfer in bytes */ uint32_t len, /* [IN] Width of data register access for DMA transfer */ int regw ) { DMA_TCD tx_tcd; DMA_TCD rx_tcd; #if PSP_ENDIAN == MQX_LITTLE_ENDIAN if (regw > 1) { regw = -regw; } #endif if (NULL != rxbuf) { dma_tcd_reg2mem(&rx_tcd, &(dspi_info_ptr->DSPI_PTR->POPR), regw, rxbuf, len); } else { dma_tcd_reg2mem(&rx_tcd, &(dspi_info_ptr->DSPI_PTR->POPR), regw, dspi_info_ptr->RX_BUF, len); rx_tcd.LOOP_DST_OFFSET = -regw; } if (NULL != txbuf) { dma_tcd_mem2reg(&tx_tcd, &(dspi_info_ptr->DSPI_PTR->PUSHR), regw, txbuf, len); } else { dma_tcd_mem2reg(&tx_tcd, &(dspi_info_ptr->DSPI_PTR->PUSHR), regw, dspi_info_ptr->TX_BUF, len); tx_tcd.LOOP_SRC_OFFSET = -regw; } /* ensure that the semaphore is at zero count */ while (_lwsem_poll(&dspi_info_ptr->EVENT_IO_FINISHED)) {} dma_transfer_submit(dspi_info_ptr->DMA_RX_CHANNEL, &rx_tcd, NULL); dma_transfer_submit(dspi_info_ptr->DMA_TX_CHANNEL, &tx_tcd, NULL); /* block the task until completion of the background operation */ _lwsem_wait(&dspi_info_ptr->EVENT_IO_FINISHED); if (dma_channel_status(dspi_info_ptr->DMA_RX_CHANNEL, NULL, NULL) || dma_channel_status(dspi_info_ptr->DMA_TX_CHANNEL, NULL, NULL) ) { return 0; } return len; }