代码见:https://github.com/qinyunti/py32f403-nes.git
一.前言
前面我们已经实现了大量的文件操作命令,spi,flash操作命令,处于可测试性可维护性考虑,我们再来实现任意mem地址的修改,内容导入导出,任务信息查看等功能。
二.任务查看
configUSE_TRACE_FACILITY中以下宏定义为1
#define configUSE_TRACE_FACILITY 1
shell_func.c中申明函数
static void psfunc(uint8_t* param);
g_shell_cmd_list_ast中添加命令行
{ (uint8_t*)"ps", psfunc, (uint8_t*)"ps"},
实现如下
static void psfunc(uint8_t* param)
{
(void)param;
uint32_t tasknum = uxTaskGetNumberOfTasks();
if(tasknum > 0)
{
TaskStatus_t * p_task_array = pvPortMalloc(sizeof(TaskStatus_t) * tasknum);
if (NULL == p_task_array) {
return;
}
uint32_t *total_time;
tasknum = uxTaskGetSystemState(p_task_array, tasknum, total_time);
xprintf("name id\tpri\tts\tsta\tsbase\t smark\r\n");
for (uint32_t i = 0; i < tasknum; i++) {
TaskStatus_t * p_task = p_task_array + i;
xprintf("%-16s%-8d%-8d%-8d%-8d%-8x%8d\r\n",p_task->pcTaskName,
p_task->xTaskNumber,
p_task->uxCurrentPriority,
p_task->ulRunTimeCounter,
p_task->eCurrentState,
(uint32_t)(p_task->pxStackBase),
p_task->usStackHighWaterMark);
}
vPortFree(p_task_array);
}
}
输入ps查看信息如下
三.任意内存读写
static void printmemfunc(uint8_t* param);
static void setmemfunc(uint8_t* param);
{ (uint8_t*)"printmem", printmemfunc, (uint8_t*)"printmem mode[hex/dec] addr[hex] len datasize[8/16/32] sig[1/0]"},
{ (uint8_t*)"setmem", setmemfunc, (uint8_t*)"setmem addr[hex] val[hex]"},
static void setmemfunc(uint8_t* param)
{
uint32_t addr;
uint32_t val;
if(2 == sscanf((const char*)param, "%*s %x %x", &addr, &val))
{
xprintf("setmem %x %x\r\n",addr,val);
if((addr % 4) ==0)
{
*(volatile uint32_t*)addr = val;
xprintf("%x\r\n",*(volatile uint32_t*)addr);
}
else
{
xprintf("addr must be mul of 4\r\n");
}
}
}
static void printmemfunc(uint8_t* param)
{
uint32_t addr;
uint32_t len;
uint8_t mode[64];
int datasize;
uint8_t* tmp8_u;
uint16_t* tmp16_u;
uint32_t* tmp32_u;
int8_t* tmp8_i;
int16_t* tmp16_i;
int32_t* tmp32_i;
int sig;
if(5 == sscanf((const char*)param, "%*s %s %x %d %d %d", mode, &addr, &len, &datasize, &sig))
{
if(strncmp((const char*)mode,"hex", 3) == 0)
{
if(datasize == 8)
{
tmp8_u = (uint8_t*)addr;
for(uint32_t i=0; i<len ;i++)
{
if(i%16 == 0)
{
xprintf("\r\n[%08x]:",addr+i*1);
}
xprintf("%02x ",tmp8_u);
}
xprintf("\r\n");
}
else if(datasize == 16)
{
tmp16_u = (uint16_t*)addr;
for(uint32_t i=0; i<len ;i++)
{
if(i%16 == 0)
{
xprintf("\r\n[%08x]:",addr+i*2);
}
xprintf("%04x ",tmp16_u);
}
xprintf("\r\n");
}
else if(datasize == 32)
{
tmp32_u = (uint32_t*)addr;
for(uint32_t i=0; i<len ;i++)
{
if(i%16 == 0)
{
xprintf("\r\n[%08x]:",addr+i*4);
}
xprintf("%08x ",tmp32_u);
}
xprintf("\r\n");
}
else
{
xprintf("datasize must be 8/16/32\r\n");
}
}
else if(strncmp((const char*)mode,"dec", 3) == 0)
{
if(datasize == 8)
{
if(sig == 0)
{
tmp8_u = (uint8_t*)addr;
for(uint32_t i=0; i<len ;i++)
{
if(i%16 == 0)
{
xprintf("\r\n");
}
xprintf("%d ",tmp8_u);
}
xprintf("\r\n");
}
else
{
tmp8_i = (int8_t*)addr;
for(uint32_t i=0; i<len ;i++)
{
if(i%16 == 0)
{
xprintf("\r\n");
}
xprintf("%d ",tmp8_i);
}
xprintf("\r\n");
}
}
else if(datasize == 16)
{
if(sig == 0)
{
tmp16_u = (uint16_t*)addr;
for(uint32_t i=0; i<len ;i++)
{
if(i%16 == 0)
{
xprintf("\r\n");
}
xprintf("%d ",tmp16_u);
}
xprintf("\r\n");
}
else
{
tmp16_i = (int16_t*)addr;
for(uint32_t i=0; i<len ;i++)
{
if(i%16 == 0)
{
xprintf("\r\n");
}
xprintf("%d ",tmp16_i);
}
xprintf("\r\n");
}
}
else if(datasize == 32)
{
if(sig == 0)
{
tmp32_u = (uint32_t*)addr;
for(uint32_t i=0; i<len ;i++)
{
if(i%16 == 0)
{
xprintf("\r\n");
}
xprintf("%d ",tmp32_u);
}
xprintf("\r\n");
}
else
{
tmp32_i = (int32_t*)addr;
for(uint32_t i=0; i<len ;i++)
{
if(i%16 == 0)
{
xprintf("\r\n");
}
xprintf("%d ",tmp32_i);
}
xprintf("\r\n");
}
}
else
{
xprintf("datasize must be 8/16/32\r\n");
}
}
else
{
xprintf("mode must be [hex/dec]\r\n");
}
}
}
查看内存
printmem hex 8000000 16 32
16进制模式查看0x8000000处以32位为单位,16个数据。
写内存
setmem 20000000 11223344
往0x20000000地址处写16进制数据0x11 0x22 0x33 0x44
四.任意存储导入导出
static void rxmemfunc(uint8_t* param);
static void sxmemfunc(uint8_t* param);
{ (uint8_t*)"rxmem", rxmemfunc, (uint8_t*)"rxmem addr[hex] len"},
{ (uint8_t*)"sxmem", sxmemfunc, (uint8_t*)"sxmem addr[hex] len"},
实现如下
static uint32_t mem_read(uint32_t addr, uint8_t* buffer, uint32_t len)
{
memcpy(buffer, (uint8_t*)addr, len);
return len;
}
static uint32_t mem_write(uint32_t addr, uint8_t* buffer, uint32_t len)
{
memcpy((uint8_t*)addr, buffer, len);
return len;
}
static void rxmemfunc(uint8_t* param)
{
uint32_t addr;
uint32_t len;
int res = 0;
if(2 == sscanf((const char*)param, "%*s %lx %ld", &addr, &len))
{
xprintf("rxmem to 0x%x %d\r\n",addr,len);
xmodem_cfg_st cfg=
{
.buffer = rxtx_buf,
.crccheck = 1,
.getms = getms,
.io_read = io_read,
.io_read_flush = io_read_flush,
.io_write = io_write,
.start_timeout = 60,
.packet_timeout = 1000,
.ack_timeout = 1000,
.mem_write = mem_write,
.addr = addr,
.totallen = len,
};
xmodem_init_rx(&cfg);
while((res = xmodem_rx()) == 0);
xprintf("res:%d\r\n",res);
}
}
static void sxmemfunc(uint8_t* param)
{
uint32_t addr;
uint32_t len;
int res = 0;
if(2 == sscanf((const char*)param, "%*s %lx %ld", &addr, &len))
{
xprintf("sxmem to 0x%x %d\r\n",addr,len);
xmodem_cfg_st cfg=
{
.buffer = rxtx_buf,
.plen = 1024,
.getms = getms,
.io_read = io_read,
.io_read_flush = io_read_flush,
.io_write = io_write,
.start_timeout = 60,
.packet_timeout = 1000,
.ack_timeout = 5000,
.mem_read = mem_read,
.addr = addr,
.totallen = len,
};
xmodem_init_tx(&cfg);
while((res = xmodem_tx()) == 0);
xprintf("res:%d\r\n",res);
}
}
sxmem 8000000 393216
导出384kB程序
也可以导出20000000处的所有RAM的内容,所有外设的寄存器等,
导出后就可以在PC上进行仿真分析。
五.总结
实现完以上功能,我们的平台就具备很强的可调试,可维护,可测试性了。比如要读写任意寄存器,dump任意内存内容等等,非常方便。