打印
[RISC-V MCU 创新应用比赛]

从零介绍risc-v开发的高速可靠的网络版daplink仿真下载器 (一)

[复制链接]
1395|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhifeng|  楼主 | 2022-12-15 14:47 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 zhifeng 于 2022-12-16 17:44 编辑

#申请原创#
简介

使用集成开发环境RISC5IDE开发的一款高速,高可靠的仿真下载器。主控芯片使用risc-v内核的ch32v208。可以直接使用progisp烧录,也可以通过progisp代理,keil中使用仿真功能。
项目管理网址 https://gitee.com/mcu598/network-daplink

硬件,使用wch的208v开发板


集成开发环境 使用 RISC5IDE


固件下载
netdap.rar (53.55 KB)








使用特权

评论回复
评论
cooldog123pp 2022-12-15 19:26 回复TA
这个是通用的吗 

相关帖子

沙发
zhifeng|  楼主 | 2022-12-15 15:10 | 只看该作者
本帖最后由 zhifeng 于 2022-12-16 08:21 编辑

CH32V208系列是基于32位RISC-V设计的无线型微控制器,配备了硬件堆栈区、快速中断入口,在标准RISC-V基础上大大提高了中断响应速度。搭载V4C内核,加入内存保护单元,同时降低硬件除法周期。片上集成2Mbps低功耗蓝牙BLE 通讯模块、10M以太网MAC+PHY模块、USB2.0全速设备+主机/设备接口、CAN控制器等。

1、我们这里主要用到的外设就是 网络接口与普通的io口。由于原先开发板的 网络指示灯均没有与任何io相连。我们需要将其与io关联起来,我只用到GPIOA.3
与GPIOA.4。 分别用杜邦线插上连好。
2、作为仿真下载器我们肯定需要指示灯用来指示工作状态,恰好开发板子上面预留有两个led未与任何端口相连。一个做连接指示,一个做运行指示。我选用的
是GPIOA.0与GPOIOA.1与别用 杜邦线将io与led相连
3、作为编程接口的我们需要3个端口,分别是 reset ,swdio,swdclk 另外烧录还需要电源与地线。在开发板上面找了下恰好GPIOD.4 与GPIOD.2位置有3v电源还有地线。正好作为编程接口使用。(最主要原因是我喜欢用idc线,这个远比杜邦线可靠。而我的板子接口都是2x5或2x3的统一接口)我焊接一根专门用于烧录的线与目标板连接。
4、那需要一个网线与电脑网口,或者与路由相连。5、仿真器 wch-link 或者wch-linke
   至此,整个硬件环境就搭好了。


使用特权

评论回复
板凳
zhifeng|  楼主 | 2022-12-15 15:27 | 只看该作者
软件基础部分1、我们需要先 到wch官方下载ch32v208的官方开发固件包。
2、到网上下载一份 daplink 软件包。这个可以不下。看我的工程里面包含修改后的源码。毕竟原先是arm内核的源码要转到risc-v上面还是需要花很多功夫的。还有就是我使用的daplink的版本可能会与您下载的版本有差异,给移植带来困难。
这些软件包的下载各显神通了就不用过多描述了。

将ch32v208的固件包 下载解压。我们只需要拷贝出 我们需要的部分,外设驱动库,与官方的网络支持库部分。余下的。我们用不大。



至此需要的原始资源我们已经准备齐全



使用特权

评论回复
地板
zhifeng|  楼主 | 2022-12-15 15:41 | 只看该作者
集成开发环境我这里使用的是 RISC5IDE 下载地址:https://pan.baidu.com/s/1QhasNaaT44axrOf7TVZ-Xg   
RISC5IDE 使用习惯与keil 相似。解压就用,无需安装,但是功能该有的都有了。
1、创建工程简单快捷。鼠标点动 期间就完成了工程的创建。
2、编译速度快,有独创的 库源码保护分类,不常用的源码放到保护类里面。
3、编辑源码可以直接查看芯片的 外设寄存器定义。
4、一键编程,擦除,复位,读保护开,读保护关闭。
5、调试简单,不会提示出现不到bin之类的错误。
6、可以直接查看修改外设寄存器内容。比如常用的GPIO,timer之类的。
7、可以查看cpu寄存器,监视变量,内存地址查看
8、运行速度快。

使用特权

评论回复
5
zhifeng|  楼主 | 2022-12-15 15:50 | 只看该作者
前面讲过 源码准备齐全了,我们将他们放到一个目录下面

前面,没有提到的 app 是我们需要开发程序放置的目录。ld 是链接需要的目录,注意:没有特殊要求的情况下可以直接使用官方的ld文件。


我这里的按这个模式规划的,可以按自己喜欢搞

使用特权

评论回复
6
zhifeng|  楼主 | 2022-12-15 16:10 | 只看该作者
本帖最后由 zhifeng 于 2022-12-15 16:13 编辑

下面使用RISC5IDE 创建一个netdap的工程。 我们使用目录方式创建工程 会将不需要的 源码也会包含进来,启动文件,我们需要的是startup_ch32v20x_D8.S  余下 的删除。 也可以按照 keil的方式将源码添加进来,并设置包含目录,但是那样操作显然麻烦的多。
ld文件也是如此。



工程创建完毕,并且编译成功。

使用特权

评论回复
7
zhifeng|  楼主 | 2022-12-15 16:36 | 只看该作者
daplink的  修改 部分 大多数是包含在DAP_config.h中。我这里做了调整,将与硬件相关的 io定义新建一个IO_config.h用于定义所以用到的 硬件配置
#ifndef __IO_CONFIG_H__
#define __IO_CONFIG_H__

#include "ch32v20x.h"

typedef  struct
{
        unsigned   gpio0:
                4;
        unsigned   gpio1:
                4;
        unsigned   gpio2:
                4;
        unsigned   gpio3:
                4;
        unsigned   gpio4:
                4;
        unsigned   gpio5:
                4;
        unsigned   gpio6:
                4;
        unsigned   gpio7:
                4;
}
_gpiol_bit_t;

typedef  struct
{
        unsigned   gpio8:
                4;
        unsigned   gpio9:
                4;
        unsigned   gpio10:
                4;
        unsigned   gpio11:
                4;
        unsigned   gpio12:
                4;
        unsigned   gpio13:
                4;
        unsigned   gpio14:
                4;
        unsigned   gpio15:
                4;
}
_gpioh_bit_t;

extern _gpiol_bit_t* GPIOAlo;
extern _gpiol_bit_t* GPIOBlo;
extern _gpiol_bit_t* GPIOClo;
extern _gpiol_bit_t* GPIODlo;
extern _gpioh_bit_t* GPIOAhi;
extern _gpioh_bit_t* GPIOBhi;
extern _gpioh_bit_t* GPIOChi;
extern _gpioh_bit_t* GPIODhi;

#define KEYDELAY 500

typedef struct
{
    uint16_t cnt;
    uint8_t ok;
    uint8_t dat;
    uint8_t press;
}
tKEY;


typedef struct
{
    volatile        unsigned int        Count;                          //计数器
    volatile        unsigned         char Flag;                          //计数器工作标志
    volatile        unsigned        char TimeOut;                  //计数器溢出标志
}
TimerStruct;

// Debug Unit LEDs
#define NET_OK_PORT                       GPIOA              //BLUE
#define NET_OK_PIN             GPIO_Pin_3
#define NET_OK(x)             ((x)?(NET_OK_PORT->BCR = NET_OK_PIN):(NET_OK_PORT->BSHR = NET_OK_PIN))

#define NET_LINK_PORT                       GPIOA              //BLUE
#define NET_LINK_PIN             GPIO_Pin_4
#define NET_LINK(x)             ((x)?(NET_LINK_PORT->BCR = NET_LINK_PIN):(NET_LINK_PORT->BSHR = NET_LINK_PIN))

// Connected LED (GREEN)
#define LED_CONNECTED_PORT            GPIOA             //GREEN
#define LED_CONNECTED_PIN                 GPIO_Pin_0
// Target Running LED (RED)
#define LED_RUNNING_PORT                      GPIOA             //RED
#define LED_RUNNING_PIN                   GPIO_Pin_1

#define LED_OK_PORT                              GPIOA              //BLUE
#define LED_OK_PIN                        GPIO_Pin_2

#define LED_RUNNING(x)             ((x)?(LED_RUNNING_PORT->BCR = LED_RUNNING_PIN):(LED_RUNNING_PORT->BSHR = LED_RUNNING_PIN))
#define LED_CONNECTED(x)           ((x)?(LED_CONNECTED_PORT->BCR = LED_CONNECTED_PIN):(LED_CONNECTED_PORT->BSHR = LED_CONNECTED_PIN))
#define LED_OK(x)                  ((x)?(LED_OK_PORT->BCR = LED_OK_PIN):(LED_OK_PORT->BSHR = LED_OK_PIN))


#define PIN_SWCLK_TCK_PORT                        GPIOD
#define PIN_SWCLK_TCK                           GPIO_Pin_2
#define  PIN_SWCLK_TCK_D(x)             GPIODlo->gpio2=(x)
#define PIN_SWDCLK_I                    (PIN_SWCLK_TCK_PORT->INDR & PIN_SWCLK_TCK)

#define PIN_SWDIO_TMS_PORT              GPIOD
#define PIN_SWDIO_TMS                   GPIO_Pin_4
#define PIN_SWDIO_TMS_D(x)              GPIODlo->gpio4=(x)
#define PIN_SWDIO_I                     (PIN_SWDIO_TMS_PORT->INDR & PIN_SWDIO_TMS)
        // TDO/SWO Pin (input)
#define PIN_TDO_PORT                    GPIOD
#define PIN_TDO                                                GPIO_Pin_3
#define PIN_TDO_D(x)                    GPIODlo->gpio3=(x)
#define PIN_TDO_I                       (PIN_TDO_PORT->INDR & PIN_TDO)
        // TDI Pin (output)
#define PIN_TDI_PORT                                GPIOD
#define PIN_TDI                                                GPIO_Pin_1
#define PIN_TDI_D(x)                    GPIODlo->gpio1=(x)
#define PIN_TDI_I                       (PIN_TDI_PORT->INDR & PIN_TDI)
        // nRESET Pin
#define PIN_nRESET_PORT                                GPIOD
#define PIN_nRESET                                  GPIO_Pin_0
#define PIN_nRESET_D(x)                 GPIOBlo->gpio0=(x)
#define PIN_nRESET_I                    (PIN_nRESET_PORT->INDR & PIN_nRESET)
#endif


使用特权

评论回复
8
zhifeng|  楼主 | 2022-12-15 16:40 | 只看该作者
在 main.c
初始化网络,IO端口 等。
调用 官方的 网络部分函数实现 一个tcp server

将 dap部分与 tcp server 挂接

#include "DAP_queue.h"

static uint8_t *ptrDataIn;
static uint16_t DataInReceLen;
static DAP_queue DAP_Cmd_queue;

void WCHNET_Data_Dap(u8 id)
{
  u32 n;
  uint8_t * rbuf;
  uint8_t * sbuf = 0;

  n = WCHNET_SocketRecvLen(id, NULL);                                //query length
//  printf("Receive Len = %02x\n", n);
  if(n>0)
  {
    WCHNET_SocketRecv(id, ptrDataIn,&n);                                  //Read the data of the receive buffer into MyBuf
    ptrDataIn      += n;
    DataInReceLen  += n;

    if (DAP_queue_execute_buf(&DAP_Cmd_queue, MyBuf, DataInReceLen,&rbuf))
    {
      if(DAP_queue_get_send_buf(&DAP_Cmd_queue, &sbuf, &n))
      {
        WCHNET_SocketSend(id, sbuf,&n);                                  //Send the data
      }
    }
    //revert the input pointers
    DataInReceLen = 0;
    ptrDataIn     = MyBuf;
  }
}

void Dap_data_Init(void)
{
  memset(MyBuf,0xff,RECE_BUF_LEN);
  ptrDataIn     = MyBuf;
  DataInReceLen = 0;
  DAP_queue_init(&DAP_Cmd_queue);
}


使用特权

评论回复
9
zhifeng|  楼主 | 2022-12-15 16:51 | 只看该作者
所有的 程序修改完毕,我们就可以启动 ide的调试功能进入调试环节了。

我们将运行到  Run to main 打勾 让程序直接运行到main 处停止。是不是特熟悉的味道--和keil一样
点击 小绿人 下载并进入调试(蜘蛛不下载,直接进入调试)

使用特权

评论回复
10
zhifeng|  楼主 | 2022-12-15 16:57 | 只看该作者
左边选择  gpioA   外设 点击 OUTDR寄存器 弹出  gpio详情。 点击,单步运行。可以直接看到我们的前面定义用到的  GPIOA 的执行动作




使用特权

评论回复
11
zhifeng|  楼主 | 2022-12-15 17:00 | 只看该作者
开发完成,不想进入调试  点击 左边的 download  可以直接烧录。

至此,整个项目开发完毕,下一步进入测试环节。

使用特权

评论回复
12
zhifeng|  楼主 | 2022-12-15 20:29 | 只看该作者
选择risc5ide Tools菜单找到MS-DOS 点击进入  命令行模式运行  ipconfig 查看网络配置

我这里使用的 是无线连接路由器 局域网无线网卡网段是192.168.0.xxx。
有线网卡是网段是 192.168.1.xxx
我们的程序的ip地址需要根据您将板子的网卡连接到路由还是直连网卡 实际情况配置
比如我这里 使用直连网卡 就设置 192.168.1.10     如果连接路由就设置192.168.0.10

如果您的网卡不是 上面的网址,请自行查阅相关资料进行配置,这里不做累述。

特别注意,这里设置的网络地址非常有用。我们要靠这个实现通信。


使用特权

评论回复
13
zhifeng|  楼主 | 2022-12-15 20:46 | 只看该作者
简单讲下  使用接路由 与直连网卡的差异。
我们通过无线连接路由,由于无线通信的延时性,速度会受影响。 使用有线连接路由模式我没有测试过,速度未知。但是,使用网卡直连模式,速度极快远超市面销售的许多商品级的link。
    如果想实现 编程让keil 能够识别 他工作,我们还需要在免费软件 progisp中进行相应的配置。progisp下载地址https://pan.baidu.com/s/1QhasNaaT44axrOf7TVZ-Xg

   选择progisp的 设备选项 菜单  选择net config页面。 红色框里面网址设置和 源程序中的 网址一致。


点击 select 菜单 选择keil 的安装目录


点击 install keil, 全部设置完毕。网线一头插入电脑,一头插入板子 的网卡,可以看到网卡指示灯亮。


使用特权

评论回复
14
zhifeng|  楼主 | 2022-12-15 20:53 | 只看该作者
这时候,我们连上待写的目标板子, 目标板子的芯片是stm32f103cb




点击联网 。下面会显示 wifi dap  这个不用管他。只要有绿色 已连接字样就能正常工作了。


使用特权

评论回复
15
zhifeng|  楼主 | 2022-12-15 21:03 | 只看该作者
本帖最后由 zhifeng 于 2022-12-15 21:06 编辑

keil 下debug 仿真器选择

仿真烧录 演示



screenshots.gif (1.41 MB )

screenshots.gif

使用特权

评论回复
16
WoodData| | 2022-12-15 21:50 | 只看该作者
学习学习,谢谢

使用特权

评论回复
17
tobot| | 2022-12-16 09:27 | 只看该作者
你大概什么时候收到的板卡啊,我到现在还没收到

使用特权

评论回复
18
lancer你| | 2022-12-16 10:47 | 只看该作者
牛的,看看

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:智峰科技-你所信赖的开发专家 https://bbzfkj.taobao.com/

43

主题

385

帖子

11

粉丝