Files
OpenTXW81X/sdk/hal/dma.c
T
2025-08-27 09:51:58 +01:00

206 lines
6.4 KiB
C

#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "hal/dma.h"
#include <string.h>
int32 dma_pause(struct dma_device *dma, uint32 ch)
{
if (dma && ((const struct dma_hal_ops *)dma->dev.ops)->pause) {
return ((const struct dma_hal_ops *)dma->dev.ops)->pause(dma, ch);
}
return RET_ERR;
}
int32 dma_resume(struct dma_device *dma, uint32 ch)
{
if (dma && ((const struct dma_hal_ops *)dma->dev.ops)->resume) {
return ((const struct dma_hal_ops *)dma->dev.ops)->resume(dma, ch);
}
return RET_ERR;
}
#pragma GCC push_options
#pragma GCC optimize ("O3")
void dma_memcpy(struct dma_device *dma, void *dst, const void *src, uint32 n)
{
uint8 dma_buf[32];
uint8_t *s,*d;
uint8_t *s1,*d1,*s2,*d2;
uint32 addr;
uint32 dst_addr = (uint32)dst >> 24;
uint32 src_addr = (uint32)src >> 24;
struct dma_xfer_data xfer_data;
if ((n <= 32) ||
((src_addr == 0x28) || (src_addr == 0x18)) ||
((dst_addr == 0x28) || (dst_addr == 0x18)) ) {
memcpy(dst, src, n);
return;
}
s1 = (uint8_t *)src;
d1 = (uint8_t *)dst;
//处理头
memcpy(dma_buf, s1, 16);
s2 = (uint8_t *)src+n-16;
d2 = (uint8_t *)dst+n-16;
//处理尾
memcpy(dma_buf+16, s2, 16);
n = n - 32;
s = (uint8_t *)src+16;
d = (uint8_t *)dst+16;
xfer_data.dest = (uint32)d;
xfer_data.src = (uint32)s;
xfer_data.element_per_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
xfer_data.element_num = n;
xfer_data.dir = ((((uint32)dst) < SRAM_BASE) || (((uint32)src) < SRAM_BASE)) ? DMA_XFER_DIR_M2D : DMA_XFER_DIR_M2M;
xfer_data.src_addr_mode = DMA_XFER_MODE_INCREASE;
xfer_data.dst_addr_mode = DMA_XFER_MODE_INCREASE;
xfer_data.dst_id = 0;
xfer_data.src_id = 0;
xfer_data.irq_hdl = NULL;
addr = (uint32)s;
addr = addr&CACHE_CIR_INV_ADDR_Msk;
s = (uint8*)addr;
addr = (uint32)d;
addr = addr&CACHE_CIR_INV_ADDR_Msk;
d = (uint8*)addr;//&CACHE_CIR_INV_ADDR_Msk;
sys_dcache_clean_range((void *)s, (int32_t)s2-(int32_t)s); //sram->psram
sys_dcache_clean_invalid_range((void *)d, (int32_t)d2-(int32_t)d); //psram cache invalid //最后一行可能没有无效化
// xfer_data.irq_data = 0;
((const struct dma_hal_ops *)dma->dev.ops)->xfer(dma, &xfer_data);
sys_dcache_invalid_range((void *)d, (int32_t)d2-(int32_t)d);
//处理头
memcpy(d1, dma_buf, 16);
//处理尾
memcpy(d2, dma_buf+16, 16);
}
void dma_memset(struct dma_device *dma, void *dst, uint8 c, uint32 n)
{
uint8 val = c;
uint8_t *d,*d1,*d2;
uint32_t i = 0;
uint32 addr;
if(n <= 32){
d1 = (uint8_t *)dst;
for(i = 0;i < n;i++){
d1[i] = val;
}
return;
}
d1 = (uint8_t *)dst;
d2 = (uint8_t *)dst+n-16;
n = n - 32;
d = (uint8_t *)dst+16;
ASSERT(dma && ((const struct dma_hal_ops *)dma->dev.ops)->xfer);
struct dma_xfer_data xfer_data;
xfer_data.dest = (uint32)d;
xfer_data.src = (uint32)&val;
xfer_data.element_per_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
xfer_data.element_num = n;
xfer_data.dir = (((uint32)dst) < SRAM_BASE) ? DMA_XFER_DIR_M2D : DMA_XFER_DIR_M2M;
xfer_data.src_addr_mode = DMA_XFER_MODE_RECYCLE;
xfer_data.dst_addr_mode = DMA_XFER_MODE_INCREASE;
xfer_data.dst_id = 0;
xfer_data.src_id = 0;
xfer_data.irq_hdl = NULL;
// xfer_data.irq_data = 0;
addr = (uint32)d;
addr = addr&CACHE_CIR_INV_ADDR_Msk;
d = (uint8*)addr;//&CACHE_CIR_INV_ADDR_Msk;
sys_dcache_clean_invalid_range((void *)d, (int32_t)d2-(int32_t)d);
((const struct dma_hal_ops *)dma->dev.ops)->xfer(dma, &xfer_data);
sys_dcache_invalid_range((void *)d, (int32_t)d2-(int32_t)d);
for(i = 0;i < 16;i++){ //处理头
d1[i] = val;
}
for(i = 0;i < 16;i++){ //处理尾
d2[i] = val;
}
}
#pragma GCC pop_options
#if ((defined(TXW81X)))
void dma_blkcpy(struct dma_device *dma , struct dma_blkcpy_cfg *cfg)
{
ASSERT(dma && ((const struct dma_hal_ops *)dma->dev.ops)->xfer);
ASSERT(cfg->blk_width <= cfg->src_width);
ASSERT(cfg->blk_width <= cfg->dst_width);
struct dma_xfer_data xfer_data;
xfer_data.dest = (uint32)cfg->dest;
xfer_data.src = (uint32)cfg->src;
xfer_data.element_per_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
xfer_data.element_num = cfg->src_width * cfg->blk_height;
xfer_data.dir = (((uint32)cfg->dest) < SRAM_BASE) ? DMA_XFER_DIR_M2D : DMA_XFER_DIR_M2M;
xfer_data.src_addr_mode = DMA_XFER_MODE_BLKCPY;
xfer_data.dst_addr_mode = DMA_XFER_MODE_BLKCPY;
xfer_data.dst_id = 0;
xfer_data.src_id = 0;
xfer_data.blk_width = cfg->blk_width;
xfer_data.blk_height = cfg->blk_height;
xfer_data.src_width = cfg->src_width;
xfer_data.dst_width = cfg->dst_width;
xfer_data.irq_hdl = NULL;
// xfer_data.irq_data = 0;
sys_dcache_clean_range((void *)cfg->src, cfg->src_width * cfg->blk_height);
sys_dcache_clean_invalid_range((void *)cfg->dest, cfg->dst_width * cfg->blk_height);
((const struct dma_hal_ops *)dma->dev.ops)->xfer(dma, &xfer_data);
sys_dcache_invalid_range((void *)cfg->dest, cfg->dst_width * cfg->blk_height);
}
#endif
int32 dma_xfer(struct dma_device *dma, struct dma_xfer_data *data)
{
if (dma && ((const struct dma_hal_ops *)dma->dev.ops)->xfer) {
return ((const struct dma_hal_ops *)dma->dev.ops)->xfer(dma, data);
}
return RET_ERR;
}
int32 dma_status(struct dma_device *dma, uint32 ch)
{
if (dma && ((const struct dma_hal_ops *)dma->dev.ops)->get_status) {
return ((const struct dma_hal_ops *)dma->dev.ops)->get_status(dma, ch);
}
return RET_ERR;
}
int32 dma_stop(struct dma_device *dma, uint32 ch)
{
if (dma && ((const struct dma_hal_ops *)dma->dev.ops)->stop) {
return ((const struct dma_hal_ops *)dma->dev.ops)->stop(dma, ch);
}
return RET_ERR;
}
int32 dma_ioctl(struct dma_device *dma, uint32 cmd, int32 param1, int32 param2)
{
if (dma && ((const struct dma_hal_ops *)dma->dev.ops)->ioctl) {
return ((const struct dma_hal_ops *)dma->dev.ops)->ioctl(dma, cmd, param1, param2);
}
return RET_ERR;
}