void OS_dcache_invalidate_mlines(void *addr, uint32_t length) { #if (PSP_HAS_DATA_CACHE && USBCFG_BUFF_PROPERTY_CACHEABLE) if ((addr < (void *)__UNCACHED_DATA_START) || (((uint32_t)addr + length) > (uint32_t)__UNCACHED_DATA_END)) { if (((uint32_t)addr & (PSP_CACHE_LINE_SIZE - 1)) != 0) { _dcache_flush_mlines((void *)addr, PSP_CACHE_LINE_SIZE); } if (((uint32_t)((uint8_t *)addr + length) & (PSP_CACHE_LINE_SIZE - 1)) != 0) { _dcache_flush_mlines((uint8_t *)addr + length, PSP_CACHE_LINE_SIZE); } _dcache_invalidate_mlines(addr, length); } #endif }
static _mqx_int _dspi_dma_tx_rx ( /* [IN] Device specific context structure */ void *io_info_ptr, /* [IN] Data to transmit */ uint8_t *txbuf, /* [OUT] Received data */ uint8_t *rxbuf, /* [IN] Length of transfer in bytes */ uint32_t len ) { DSPI_DMA_INFO_STRUCT_PTR dspi_info_ptr = (DSPI_DMA_INFO_STRUCT_PTR)io_info_ptr; int regw; uint32_t head_len; uint32_t tail_len; uint32_t zero_copy_len; _mqx_int result; /* Check whether there is at least something to transfer */ if (0 == len) { return 0; } /* Check frame width */ if (DSPI_CTAR_FMSZ_GET(dspi_info_ptr->DSPI_PTR->CTAR[0]) > 7) { len = len & (~1UL); /* Round down to whole frames */ regw = 2; } else { regw = 1; } /* If there is no data to transmit, prepare dummy pattern in proper byte order */ if (NULL == txbuf) { if (regw == 1) { dspi_info_ptr->TX_BUF[0] = dspi_info_ptr->DUMMY_PATTERN & 0xFF; } else { dspi_info_ptr->TX_BUF[0] = (dspi_info_ptr->DUMMY_PATTERN>>8) & 0xFF; dspi_info_ptr->TX_BUF[1] = dspi_info_ptr->DUMMY_PATTERN & 0xFF; } _dcache_flush_line(dspi_info_ptr->TX_BUF); } if (!(len % PSP_CACHE_LINE_SIZE) && !((uint32_t)txbuf % PSP_CACHE_LINE_SIZE) && !((uint32_t)rxbuf % PSP_CACHE_LINE_SIZE)) { /* Everything is perfectly aligned, perform single zero copy operation without any head or tail */ head_len = 0; tail_len = 0; } else if (len <= 2*PSP_CACHE_LINE_SIZE) { /* The whole transfer fits into intermediate buffers, perform single transfer (head only) */ head_len = len; tail_len = 0; } else { /* Split the transfer into head, zero copy portion and tail */ uint32_t cache_line_offset; uint32_t tx_head_len; uint32_t tx_tail_len; uint32_t rx_head_len; uint32_t rx_tail_len; if (NULL != rxbuf) { cache_line_offset = (uint32_t)rxbuf % PSP_CACHE_LINE_SIZE; rx_head_len = cache_line_offset ? PSP_CACHE_LINE_SIZE - cache_line_offset : 0; rx_tail_len = (((uint32_t)rxbuf + len) % PSP_CACHE_LINE_SIZE); } else { rx_head_len = 0; rx_tail_len = 0; } if (NULL != txbuf) { cache_line_offset = (uint32_t)txbuf % PSP_CACHE_LINE_SIZE; tx_head_len = cache_line_offset ? PSP_CACHE_LINE_SIZE - cache_line_offset : 0; tx_tail_len = (((uint32_t)txbuf + len) % PSP_CACHE_LINE_SIZE); } else { tx_head_len = 0; tx_tail_len = 0; } head_len = (rx_head_len > tx_head_len) ? rx_head_len : tx_head_len; tail_len = (rx_tail_len > tx_tail_len) ? rx_tail_len : tx_tail_len; if (regw > 1) { head_len += (head_len & 1); tail_len += (tail_len & 1); } } zero_copy_len = len - head_len - tail_len; /* Head processed through intermediate buffers */ if (head_len) { if (txbuf) { _mem_copy(txbuf, dspi_info_ptr->TX_BUF, head_len); _dcache_flush_mlines(dspi_info_ptr->TX_BUF, len); result = _dspi_dma_transfer(dspi_info_ptr, dspi_info_ptr->TX_BUF, dspi_info_ptr->RX_BUF, head_len, regw); } else { result = _dspi_dma_transfer(dspi_info_ptr, NULL, dspi_info_ptr->RX_BUF, head_len, regw); } if (result != head_len) { return IO_ERROR; } /* * Copy to application buffer intentionally ommited. * It is done later after invalidation of zero copy area as it may overlap into it. */ } /* Zero copy area */ if (zero_copy_len) { uint8_t *txbuf_real; uint8_t *rxbuf_real; txbuf_real = txbuf ? txbuf + head_len : NULL; rxbuf_real = rxbuf ? rxbuf + head_len : NULL; if (txbuf_real) { _dcache_flush_mlines(txbuf_real, zero_copy_len); } result = _dspi_dma_transfer(dspi_info_ptr, txbuf_real, rxbuf_real, zero_copy_len, regw); if (rxbuf_real) { _dcache_invalidate_mlines(rxbuf_real, zero_copy_len); } if (result != zero_copy_len) { return IO_ERROR; } } /* Copy head data into application buffer if desired */ if (head_len && rxbuf) { _dcache_invalidate_mlines(dspi_info_ptr->RX_BUF, head_len); _mem_copy(dspi_info_ptr->RX_BUF, rxbuf, head_len); } /* Tail processed through intermediate buffers */ if (tail_len) { if (txbuf) { _mem_copy(txbuf + len - tail_len, dspi_info_ptr->TX_BUF, tail_len); _dcache_flush_mlines(dspi_info_ptr->TX_BUF, tail_len); result = _dspi_dma_transfer(dspi_info_ptr, dspi_info_ptr->TX_BUF, dspi_info_ptr->RX_BUF, tail_len, regw); } else { result = _dspi_dma_transfer(dspi_info_ptr, NULL, dspi_info_ptr->RX_BUF, tail_len, regw); } if (result != tail_len) { return IO_ERROR; } if (rxbuf) { _dcache_invalidate_mlines(dspi_info_ptr->RX_BUF, tail_len); _mem_copy(dspi_info_ptr->RX_BUF, rxbuf + len - tail_len, tail_len); } } return len; }