📄 cfe_dmtest.c
字号:
* * Return value: * nothing ********************************************************************* */voiddm_bsink(void *src, int cnt){ dm_bsink_p(SBDMA_CMD_CH, phys_addr((long) src), cnt, 0);}/* Address parsing adapted from ui_examcmds. */#define ATYPE_TYPE_NONE 0#define ATYPE_TYPE_PHYS 1#define ATYPE_TYPE_VIRT 2#define ATYPE_TYPE_MASK (ATYPE_TYPE_PHYS | ATYPE_TYPE_VIRT)static intgetaddrarg(ui_cmdline_t *cmd, int arg, uint64_t *addr, int *atype){ int res; res = -1; if (atype) { *atype &= ~ATYPE_TYPE_MASK; *atype |= ATYPE_TYPE_NONE; if (cmd_sw_isset(cmd, "-p")) { *atype |= ATYPE_TYPE_PHYS; } else if (cmd_sw_isset(cmd, "-v")) { *atype |= ATYPE_TYPE_VIRT; } else { *atype |= ATYPE_TYPE_VIRT; /* best default? */ } } if (addr) { char *x = cmd_getarg(cmd, arg); *addr = 0; if (x) { /* Following gdb, we Make 64-bit addresses expressed as 8-digit numbers sign extend automagically. Saves typing, but is very gross. */ int longaddr; longaddr = strlen(x); if (memcmp(x, "0x", 2) == 0) longaddr -= 2; *addr = (longaddr > 8) ? (uint64_t) xtoq(x) : (uint64_t) xtoi(x); res = 0; } } return res;}static intgetlenarg(ui_cmdline_t *cmd, int arg, size_t *len){ int res; res = -1; if (len) { char *x = cmd_getarg(cmd, arg); *len = 0; if (x) { *len = (size_t) xtoi(x); res = 0; } } return res;}static voidshow_rate(size_t len, uint64_t elapsed){ uint64_t rate; char digits[4+1]; if (elapsed == 0) elapsed = 1; /* zbclk always 0 in the simulator */ rate = ((uint64_t)len * zb_mhz * 10L)/elapsed; sprintf(digits, "%04d", rate); cfe_ledstr(digits); printf("%3d.%1d MB/s\n", rate/10L, rate%10L);}static intui_cmd_zero(ui_cmdline_t *cmd, int argc, char *argv[]){ uint64_t dest; int dtype; size_t len; flags_t flags = 0; uint64_t elapsed; getaddrarg(cmd, 0, &dest, &dtype); getlenarg(cmd, 1, &len); if (cmd_sw_isset(cmd, "-u")) flags |= DSTUNC; else if (cmd_sw_isset(cmd, "-l2")) flags |= L2CDEST; if ((dtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT) dest = phys_addr(dest); if (len > 0x100000) len = 0x100000; /* XXX single command for now */ dm_cmd_init((flags & DSTUNC) != DSTUNC); elapsed = dm_bzero_p(SBDMA_CMD_CH, dest, len, flags); show_rate(len, elapsed); return 0;}static intui_cmd_sink(ui_cmdline_t *cmd, int argc, char *argv[]){ uint64_t src; int stype; size_t len; flags_t flags = 0; uint64_t elapsed; getaddrarg(cmd, 0, &src, &stype); getlenarg(cmd, 1, &len); if (cmd_sw_isset(cmd, "-u")) flags |= SRCUNC; else if (cmd_sw_isset(cmd, "-l2")) flags |= L2CSRC; if ((stype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT) src = phys_addr(src); if (len > 0x100000) len = 0x100000; /* XXX single command for now */ dm_cmd_init((flags & SRCUNC) != SRCUNC); elapsed = dm_bsink_p(SBDMA_CMD_CH, src, len, flags); show_rate(len, elapsed); return 0;}static intui_cmd_cpy(ui_cmdline_t *cmd, int argc, char *argv[]){ uint64_t src, dest; int stype, dtype; size_t len; flags_t flags = 0; uint64_t elapsed; getaddrarg(cmd, 0, &dest, &dtype); getaddrarg(cmd, 1, &src, &stype); getlenarg(cmd, 2, &len); if (cmd_sw_isset(cmd, "-u")) flags |= SRCUNC|DSTUNC; else if (cmd_sw_isset(cmd, "-l2")) flags |= L2CDEST; if ((dtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT) dest = phys_addr(dest); if ((stype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT) src = phys_addr(src); if (len > 0x100000) len = 0x100000; /* XXX single command for now */ dm_cmd_init((flags & (SRCUNC|DSTUNC)) != (SRCUNC|DSTUNC)); elapsed = dm_bcopy_p(SBDMA_CMD_CH, src, dest, len, flags); show_rate(len, elapsed); return 0;}static intui_cmd_mcpy(ui_cmdline_t *cmd, int argc, char *argv[]){ uint64_t src, dest; int stype, dtype; size_t len, blksize; flags_t flags = 0; uint64_t elapsed; getaddrarg(cmd, 0, &dest, &dtype); getaddrarg(cmd, 1, &src, &stype); getlenarg(cmd, 2, &len); getlenarg(cmd, 3, &blksize); if (cmd_sw_isset(cmd, "-u")) flags |= SRCUNC|DSTUNC; else if (cmd_sw_isset(cmd, "-l2")) flags |= L2CDEST; if ((dtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT) dest = phys_addr(dest); if ((stype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT) src = phys_addr(src); dm_cmd_init((flags & (SRCUNC|DSTUNC)) != (SRCUNC|DSTUNC)); if (len <= blksize) elapsed = dm_bcopy_p(SBDMA_CMD_CH, src, dest, len, flags); else elapsed = dm_multibcopy_p(SBDMA_MCMD_CH, src, dest, len, blksize, flags); show_rate(len, elapsed); return 0;}/* ********************************************************************* * ui_cmd_testdm() * * Test program. * * Input parameters: * argc,argv * * Return value: * 0 ********************************************************************* */#ifdef _SBDMA_INTERRUPTS_#define N_SAMPLES 8typedef struct sbgendma_args_s { int ch; int enabled; uint64_t src, dest; size_t len; flags_t flags; uint64_t start; uint64_t last; uint64_t delta[N_SAMPLES]; int index; int toggle; uint64_t count;} sbgendma_args_t;static voiddm_restart(sbgendma_args_t *args){ sbdmadscr_t dscr; dm_builddescr_p(&dscr, args->dest, args->src, args->len, args->flags); args->start = dm_startone(args->ch, &dscr);}static voiddm_interrupt_loop(void *ctx){ sbgendma_args_t *args = (sbgendma_args_t *)ctx; sbgendma_t *d = &sbgendma_ctx[args->ch]; /* Clear the interrupt (better in procbuffers? */ (void) DM_READCSR(d->dm_dscrbase); dm_procbuffers(d); if (G_DM_CUR_DSCR_DSCR_COUNT(DM_READCSR(d->dm_curdscr)) == 0) { uint64_t start, now; char digits[4+1]; now = zclk_get(); start = args->start; d->dm_busy = 0; if (args->len == 0) { args->enabled = 0; cfe_free_irq(K_INT_DM_CH_0 + args->ch, 0); dm_uninitctx(args->ch); cfe_ledstr("CFE "); } else { dm_restart(args); args->delta[args->index] = zclk_elapsed(now, start); args->index = (args->index + 1) % N_SAMPLES; if (zclk_elapsed(now, args->last) > zb_hz/4) { int i; uint64_t avg, rate; args->last = now; avg = 0; for (i = 0; i < N_SAMPLES; i++) avg += args->delta[i]; avg /= N_SAMPLES; rate = ((uint64_t)(args->len) * zb_mhz * 10L)/avg; sprintf(digits, "%04d", rate);#ifdef _SENTOSA_#define WRITECSR(csr,val) *((volatile uint64_t *) (csr)) = (val) args->toggle ^= 1; if (args->toggle) WRITECSR(PHYS_TO_K1(A_GPIO_PIN_SET), M_GPIO_DEBUG_LED); else WRITECSR(PHYS_TO_K1(A_GPIO_PIN_CLR), M_GPIO_DEBUG_LED); args->count += 1; if (args->count % (5*60*4) == 0) xprintf("%ld\n", args->count/(60*4));#undef WRITECSR#else cfe_ledstr(digits);#endif } } }}static sbgendma_args_t *test_args[DM_NUM_CHANNELS] = { NULL, NULL, NULL, NULL};static intui_cmd_testdm(ui_cmdline_t *cmd, int argc, char *argv[]){ uint64_t src, dest; int stype, dtype; size_t len; flags_t flags = 0; sbgendma_args_t *args; int ch = SBDMA_TEST_CH; /* always single channel for now */ int i; if (argc == 0) { /* OK values for demos */ dest = 0xE000120000LL; src = 0x0000020000LL; len = 0x100000LL; } else { getaddrarg(cmd, 0, &dest, &dtype); getaddrarg(cmd, 1, &src, &stype); getlenarg(cmd, 2, &len); if (cmd_sw_isset(cmd, "-u")) flags |= SRCUNC|DSTUNC; /* XXX Only pass 1 parts have this form of throttle. */ if (cmd_sw_isset(cmd, "-t")) flags |= THROTTLE; if ((dtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT) dest = phys_addr(dest); if ((stype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT) src = phys_addr(src); } if (cmd_sw_isset(cmd, "-off")) len = 0; if (src < dest && (uint64_t)(src + len) > (uint64_t)dest) { flags |= SRCDEC|DSTDEC; dest += len - 1; src += len - 1; } else { flags |= SRCINC|DSTINC; } args = test_args[ch]; if (args == NULL) { args = (sbgendma_args_t *)KMALLOC(sizeof(sbgendma_args_t), 0); if (args == NULL) return -1; args->ch = ch; args->enabled = 0; args->len = 0; test_args[ch] = args; } args->src = src; args->dest = dest; args->len = len; args->flags = flags|INTER; args->index = 0; for (i = 0; i < N_SAMPLES; i++) args->delta[i] = 0; args->toggle = 0; args->count = 0; dm_init(); if (!args->enabled && len != 0) { dm_initctx(args->ch, 1, K_DM_DSCR_BASE_PRIORITY_1); cfe_request_irq(K_INT_DM_CH_0 + args->ch, dm_interrupt_loop, args, 0, 0); args->enabled = 1; args->last = zclk_get(); dm_restart(args); } return 0;}#else /* !_SBDMA_INTERRUPTS_ */static intui_cmd_testdm(ui_cmdline_t *cmd, int argc, char *argv[]){ uint64_t src, dest; int stype, dtype; size_t len; flags_t flags = 0; uint64_t now, elapsed; uint64_t rate; char digits[4+1]; uint64_t last; getaddrarg(cmd, 0, &dest, &dtype); getaddrarg(cmd, 1, &src, &stype); getlenarg(cmd, 2, &len); if (cmd_sw_isset(cmd, "-u")) flags |= SRCUNC|DSTUNC; if ((dtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT) dest = phys_addr(dest); if ((stype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT) src = phys_addr(src); last = zclk_get(); printf("Press ENTER to stop timing\n"); dm_cmd_init((flags & (SRCUNC|DSTUNC)) != (SRCUNC|DSTUNC)); dm_initctx(SBDMA_TEST_CH, 1, K_DM_DSCR_BASE_PRIORITY_1); do { elapsed = dm_bcopy_p(SBDMA_TEST_CH, src, dest, len, flags); now = zclk_get(); if (zclk_elapsed(now, last) > zb_hz/4) { last = now; rate = ((uint64_t)len * zb_mhz * 10L)/elapsed; sprintf(digits, "%04d", rate); cfe_ledstr(digits); } } while (!console_status()); dm_uninitctx(SBDMA_TEST_CH); return 0;}#endif /* !_SBDMA_INTERRUPTS_ *//* demo stuff *//* The communication area */#define SBDMA_REMOTEP(x) ((uint64_t)(x) | 0xe000000000LL)/* Using physical address 0x10000 as the mailbox base is arbitrary but compatible with CFE. */#define MBOX_PADDR 0x10000#define BUFFER_PADDR (MBOX_PADDR + sizeof(int))#define BUFFER_SIZE 200static int listener = 0;static voidcfe_recvdm(void *arg){ /* always use the local values */ volatile int *mailbox = (volatile int *) PHYS_TO_K1(MBOX_PADDR); volatile char *rx_buffer = (volatile char *) PHYS_TO_K1(BUFFER_PADDR); if (*mailbox) { int len; for (len = 0; len < BUFFER_SIZE-1 && rx_buffer[len] != '\000'; len++) ; rx_buffer[len] = '\000'; console_write("[", 1); console_write((char *)rx_buffer, len); console_write("]\r\n", 3); *mailbox = 0; }}static intui_cmd_talkdm(ui_cmdline_t *cmd, int argc, char *argv[]){ volatile int *mailbox; char tx_buffer[BUFFER_SIZE]; int tx_len; uint64_t src, dst; int local = cmd_sw_isset(cmd, "-l"); static char prompt[] = "Enter text, exit with \"!<ENTER>\"\r\n"; if (!listener) { *((volatile int *) PHYS_TO_K1(MBOX_PADDR)) = 0; cfe_bg_add(cfe_recvdm, NULL); listener = 1; } src = K0_TO_PHYS((long)tx_buffer); if (local) { mailbox = (volatile int *) PHYS_TO_K1 (MBOX_PADDR); dst = BUFFER_PADDR; } else { mailbox = (volatile int *) PHYS_TO_XKSEG_UNCACHED (SBDMA_REMOTEP(MBOX_PADDR)); dst = SBDMA_REMOTEP(BUFFER_PADDR); } dm_init(); dm_initctx(SBDMA_TALK_CH, 1, K_DM_DSCR_BASE_PRIORITY_1);#ifdef _SBDMA_INTERRUPTS_ cfe_request_irq(K_INT_DM_CH_0 + SBDMA_TALK_CH, dm_interrupt, &sbgendma_ctx[SBDMA_TALK_CH], 0, 0);#endif /* _SBDMA_INTERRUPTS_ */ console_write(prompt, strlen(prompt)); for (;;) { tx_len = console_readline("", tx_buffer, BUFFER_SIZE-1); if (tx_len == 1 && tx_buffer[0] == '!') { console_write("bye\r\n", 5); break; } tx_buffer[tx_len] = '\000'; while (*mailbox == 1) POLL(); dm_bcopy_p(SBDMA_TALK_CH, src, dst, tx_len+1, 0); *mailbox = 1; while (*mailbox == 1) POLL(); }#ifdef _SBDMA_INTERRUPTS_ cfe_free_irq(K_INT_DM_CH_0 + SBDMA_TALK_CH, 0);#endif dm_uninitctx(SBDMA_TALK_CH); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -