Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
385
sdk/hal/dma.c
Normal file
385
sdk/hal/dma.c
Normal file
@@ -0,0 +1,385 @@
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "errno.h"
|
||||
#include "dev.h"
|
||||
#include "hal/dma.h"
|
||||
#include "osal/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 cache_deal_invalid(void *dst,uint32 n){
|
||||
uint8 *d1;
|
||||
uint8 *d2;
|
||||
uint8 st_head,end_head;
|
||||
d1 = (uint8 *)dst;
|
||||
st_head = (uint32)d1%32;
|
||||
end_head = 32 - ((uint32)d1+n)%32;
|
||||
n = n+st_head+end_head;
|
||||
d1 = d1 - st_head;
|
||||
d2 = (uint8 *)((uint32)d1&0x0fffffff);
|
||||
memcpy(d2,d1,32);
|
||||
memcpy(d2+n-32,d1+n-32,32);
|
||||
|
||||
sys_dcache_invalid_range((void *)d1, n);
|
||||
}
|
||||
|
||||
void cache_deal_writeback(void *dst,uint32 n){
|
||||
uint8 *d1;
|
||||
uint8 *d2;
|
||||
uint8 st_head,end_head;
|
||||
d1 = (uint8 *)dst;
|
||||
st_head = ((uint32)d1 % 32);
|
||||
end_head = 32 - ((uint32)d1+n)%32;
|
||||
n = n+st_head+end_head;
|
||||
d1 = d1 - st_head;
|
||||
d2 = (uint8 *)((uint32)d1&0x0fffffff);
|
||||
memcpy(d2,d1,32);
|
||||
memcpy(d2+n-32,d1+n-32,32);
|
||||
|
||||
sys_dcache_clean_range((void *)d1, n);
|
||||
|
||||
}
|
||||
void dma_memcpy(struct dma_device *dma, void *dst, const void *src, uint32 n)
|
||||
{
|
||||
uint8 dma_buf[64];
|
||||
uint8 *s,*d;
|
||||
uint8 *s1,*d1,*s2,*d2;
|
||||
uint32 i = 0;
|
||||
uint32 addr;
|
||||
ASSERT(dma && ((const struct dma_hal_ops *)dma->dev.ops)->xfer);
|
||||
|
||||
struct dma_xfer_data xfer_data;
|
||||
if(n <= 64){
|
||||
s1 = (uint8 *)src;
|
||||
d1 = (uint8 *)dst;
|
||||
for(i = 0;i < n;i++){
|
||||
d1[i] = s1[i];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
s1 = (uint8 *)src;
|
||||
d1 = (uint8 *)dst;
|
||||
|
||||
// for(i = 0;i < 16;i++){ //处理头
|
||||
// dma_buf[i] = s1[i];
|
||||
// }
|
||||
memcpy(dma_buf, s1, 32);
|
||||
|
||||
s2 = (uint8 *)src+n-32;
|
||||
d2 = (uint8 *)dst+n-32;
|
||||
// for(i = 0;i < 16;i++){ //处理头
|
||||
// dma_buf[i+16] = s2[i];
|
||||
// }
|
||||
memcpy(dma_buf+32, s2, 32);
|
||||
|
||||
n = n - 64;
|
||||
s = (uint8 *)src+32;
|
||||
d = (uint8 *)dst+32;
|
||||
|
||||
|
||||
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;
|
||||
xfer_data.endian = 0;
|
||||
addr = (uint32)s;
|
||||
|
||||
|
||||
addr = addr&((0x7FFFFFFUL << 5));
|
||||
s = (uint8*)addr;
|
||||
addr = (uint32)d;
|
||||
addr = addr&((0x7FFFFFFUL << 5));
|
||||
d = (uint8*)addr;//&CACHE_CIR_INV_ADDR_Msk;
|
||||
sys_dcache_clean_range((void *)s, (int32_t)s2-(int32_t)s); //cache->psram
|
||||
sys_dcache_invalid_range((void *)d, (int32_t)d2-(int32_t)d); //psram cache invalid //最后一行可能没有无效化
|
||||
// printf("===============s:%08x d:%08x\r\n\r\n",s,d);
|
||||
// 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);
|
||||
|
||||
// for(i = 0;i < 16;i++){ //处理头
|
||||
// d1[i] = dma_buf[i];
|
||||
// }
|
||||
memcpy(d1, dma_buf, 32);
|
||||
// for(i = 0;i < 16;i++){ //处理尾
|
||||
// d2[i] = dma_buf[i+16];
|
||||
// }
|
||||
memcpy(d2, dma_buf+32, 32);
|
||||
}
|
||||
|
||||
void dma_memcpy_no_cache(struct dma_device *dma, void *dst, const void *src, uint32 n)
|
||||
{
|
||||
//uint8 dma_buf[64];
|
||||
uint8 *s,*d;
|
||||
//uint8 *s1,*d1,*s2,*d2;
|
||||
//uint32 i = 0;
|
||||
uint32 addr;
|
||||
ASSERT(dma && ((const struct dma_hal_ops *)dma->dev.ops)->xfer);
|
||||
|
||||
struct dma_xfer_data xfer_data;
|
||||
|
||||
s = (uint8 *)src;
|
||||
d = (uint8 *)dst;
|
||||
|
||||
|
||||
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;
|
||||
xfer_data.endian = 0;
|
||||
addr = (uint32)s;
|
||||
|
||||
((const struct dma_hal_ops *)dma->dev.ops)->only_hw_xfer(dma, &xfer_data);
|
||||
}
|
||||
|
||||
void dma_memset_word(struct dma_device *dma, void *dst, uint32 c, uint32 n)
|
||||
{
|
||||
uint32 val = c;
|
||||
uint8 *d, *d1, *d2;
|
||||
uint32 i = 0;
|
||||
uint32 size = 0;
|
||||
uint32 addr;
|
||||
|
||||
if(n <= 64){
|
||||
d1 = (uint8 *)dst;
|
||||
i = (uint32)dst % 4;
|
||||
size = i + n;
|
||||
for(;i < (size);i++){
|
||||
*d1++ = (val >> ((i % 4)<<3));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
d1 = (uint8 *)(dst);
|
||||
d2 = (uint8 *)(dst+n-32);
|
||||
n = n - 64;
|
||||
d = (uint8 *)(dst+32);
|
||||
|
||||
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;
|
||||
xfer_data.endian = 0;
|
||||
|
||||
addr = (uint32)d;
|
||||
addr = addr&((0x7FFFFFFUL << 5));
|
||||
d = (uint8 *)addr;//&CACHE_CIR_INV_ADDR_Msk;
|
||||
sys_dcache_invalid_range((void *)d, (int32_t)d2-(int32_t)d);
|
||||
|
||||
((const struct dma_hal_ops *)dma->dev.ops)->xfer(dma, &xfer_data);
|
||||
|
||||
i = (uint32)dst % 4;
|
||||
size = i + 32;
|
||||
for(;i < (size);i++){ //处理头
|
||||
*d1++ = (val >> ((i % 4)<<3));
|
||||
}
|
||||
i = (uint32)d2 % 4;
|
||||
size = i + 32;
|
||||
for(;i < (size);i++){ //处理尾
|
||||
*d2++ = (val >> ((i % 4)<<3));
|
||||
}
|
||||
}
|
||||
|
||||
void dma_memset(struct dma_device *dma, void *dst, uint8 c, uint32 n)
|
||||
{
|
||||
uint32 val = c | (c<<8) | (c<<16) | (c<<24);
|
||||
dma_memset_word(dma, dst, val, n);
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
void dma_memcpy_endian(struct dma_device *dma, void *dst, const void *src, uint32 n, enum dma_endian_type type)
|
||||
{
|
||||
uint32 dma_buf[16];
|
||||
uint8 *s,*d;
|
||||
uint8 *s1, *d1, *s2, *d2;
|
||||
uint16 *s3, *d3, *s4;
|
||||
uint32 *s5, *d5, *s6;
|
||||
uint32 i = 0;
|
||||
uint32 addr;
|
||||
uint32 ret = RET_OK;
|
||||
ASSERT(dma && ((const struct dma_hal_ops *)dma->dev.ops)->xfer);
|
||||
|
||||
struct dma_xfer_data xfer_data;
|
||||
switch (type)
|
||||
{
|
||||
case DMA_ENDIAN_TYPE_NO_OVERTURN:
|
||||
s1 = (uint8 *)src;
|
||||
d1 = (uint8 *)dst;
|
||||
s2 = (uint8 *)dma_buf;
|
||||
if (n <= 64)
|
||||
{
|
||||
for(i = 0; i < (n >> type); i++){
|
||||
*d1++ = *s1++;
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < (32 >> type); i++){ // 处理头
|
||||
*s2++ = *s1++;
|
||||
}
|
||||
s1 = (uint8 *)((uint32)src+n-32);
|
||||
for(i = 0; i < (32 >> type); i++){ // 处理尾
|
||||
*s2++ = *s1++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DMA_ENDIAN_TYPE_16BIT_OVERTURN:
|
||||
s3 = (uint16 *)src;
|
||||
d3 = (uint16 *)dst;
|
||||
s4 = (uint16 *)dma_buf;
|
||||
ret = (n % 2 != 0);
|
||||
if (!ret)
|
||||
{
|
||||
if (n <= 64)
|
||||
{
|
||||
for(i = 0; i < (n >> type); i++){
|
||||
*d3++ = __REVSH(*s3++);
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < (32 >> type); i++){ // 处理头
|
||||
*s4++ = __REVSH(*s3++);
|
||||
}
|
||||
s3 = (uint16 *)((uint32)src+n-32);
|
||||
for(i = 0; i < (32 >> type); i++){ // 处理尾
|
||||
*s4++ = __REVSH(*s3++);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
os_printf("dma memcpy size : %d endian: %d err\r\n", n, type);
|
||||
}
|
||||
break;
|
||||
|
||||
case DMA_ENDIAN_TYPE_32BIT_OVERTURN:
|
||||
s5 = (uint32 *)src;
|
||||
d5 = (uint32 *)dst;
|
||||
s6 = (uint32 *)dma_buf;
|
||||
ret = (n % 4 != 0);
|
||||
if (!ret)
|
||||
{
|
||||
if (n <= 64)
|
||||
{
|
||||
for(i = 0; i < (n >> type); i++){
|
||||
*d5++ = __REV(*s5++);
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < (32 >> type); i++){ // 处理头
|
||||
*s6++ = __REV(*s5++);
|
||||
}
|
||||
s5 = (uint32 *)((uint32)src+n-32);
|
||||
for(i = 0; i < (32 >> type); i++){ // 处理尾
|
||||
*s6++ = __REV(*s5++);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
os_printf("dma memcpy size : %d endian: %d err\r\n", n, type);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
os_printf("dma memcpy endian type err!");
|
||||
ret = RET_ERR;
|
||||
break;
|
||||
}
|
||||
if (ret || (n <= 64)) return;
|
||||
|
||||
s1 = (uint8 *)src;
|
||||
d1 = (uint8 *)dst;
|
||||
s2 = (uint8 *)(src+n-32);
|
||||
d2 = (uint8 *)(dst+n-32);
|
||||
n = n - 64;
|
||||
s = (uint8 *)(src+32);
|
||||
d = (uint8 *)(dst+32);
|
||||
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;
|
||||
xfer_data.endian = type;
|
||||
addr = (uint32)s;
|
||||
addr = addr&((0x7FFFFFFUL << 5));
|
||||
s = (uint8*)addr;
|
||||
addr = (uint32)d;
|
||||
addr = addr&((0x7FFFFFFUL << 5));
|
||||
d = (uint8*)addr;//&CACHE_CIR_INV_ADDR_Msk;
|
||||
sys_dcache_clean_range((void *)s, (int32_t)s2-(int32_t)s); //cache->psram
|
||||
sys_dcache_invalid_range((void *)d, (int32_t)d2-(int32_t)d); //psram cache invalid //最后一行可能没有无效化
|
||||
|
||||
((const struct dma_hal_ops *)dma->dev.ops)->xfer(dma, &xfer_data);
|
||||
memcpy(d1, dma_buf, 32);
|
||||
memcpy(d2, (void *)((uint32)dma_buf+32), 32);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user