【电子DIY】DIY行车记录仪为游戏机之主控软件开发(9)可测试行可维护性

代码见: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查看信息如下

224301rkk6tkrckxy1r9fz

三.任意内存读写

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个数据。

224301yp6xdqldscx66ej1

写内存

setmem 20000000 11223344

往0x20000000地址处写16进制数据0x11 0x22 0x33 0x44

224301y38r3rfc8pcrtkwp

四.任意存储导入导出

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上进行仿真分析。

224301rdx9mzc2p5cdxco9

五.总结

实现完以上功能,我们的平台就具备很强的可调试,可维护,可测试性了。比如要读写任意寄存器,dump任意内存内容等等,非常方便。