梳理一下JTAG控制器最基本的几个底层函数。

来源:互联网 发布:如何部署阿里云服务器 编辑:程序博客网 时间:2024/05/22 02:02

上位机最最基本有两个函数,如下:

//tested ok
int ejtag_read_back(char*buff,unsigned int bytes)//buff 长度将512的整数倍
{
printf("enter ejtag_read_back >>>>> bytes  = %d" ,bytes);
    char tmp[20];
    unsigned int cmd ;
    unsigned int i,t ;

    cmd=6<<25 ;

i=align(bytes,4);//对齐   

   //-- cmd|=bytes ;//在次可以将bytes按照4字节对齐

    cmd |= i ; //将读会的字节数是被4整除

   fill_byte(cmd,tmp); //    

  t=align(i,512);//数据包对齐

    cmd=7<<25 ;//发送填充命令。   

 cmd|=(t-i);//填充数量是以字节对单位。

    fill_byte(cmd,&tmp[4]);

if (t==i) t=4;else t=8; 

    #ifdef VC_TEST 
    
    if((t-i)!=0)printf("\npadding data len %d\n",t-i);
    else printf("\nno padding data\n",t-i);
    lw_usb_write(tmp,t);
    lw_usb_write(tmp,0);

    i=lw_usb_read(buff,t);
    
    ///getchar () ;
    
    #else 
    
    usb_buffer_write(tmp,t) ;
LOG_INFO("           ejtag_read_back write  len = %d",t) ;
    usb_buffer_write(NULL,0);
    i=usb_bulk_read(loongsonejtag_jtag_handle->usb_handle,0x86,buff,t,5000);
LOG_INFO("           ejtag_read_back  read len  = %d",t) ;

    #endif 
    
    LOG_INFO("\nejtag_read_back >  usb_read result is %d\n",(int)i);
    //for(i=0;i<bytes;++i) LOG_INFO("0x%02x ",(unsigned char )buff[i]);
    return i ;

}

上面代码的基本操作单位是字节。首先使用6号指令读写回FIFO,之后不够512字节的使用7号指令进行填充,再看一下对应NIOS里面处理代码:

      i=usb_rd_u32();
        op_code=i>>25 ;


if ((op_code ==6)||(op_code ==7 )) //read data back!
{
            t=i&0xffffff;  t>>=2;///if(i&3)t++;
if (op_code ==7 )while(t--) usb_wr_u32(EJTAG_BACK_FIFO_USEDW);
if (op_code ==6 )
{
while(t--){
   while(EJTAG_STATUS&1);
usb_wr_u32(EJTAG_FIFO_DATA);
}
}


而在JTAG控制器的VERILOG代码中,最后一个字不足32位也是按照32位写回的:


always@ (posedge clk)
if (bit_syn&op_wb_r) 
back_fifo_wr<=  ((state == 'h322 )&&(~|sft32)) || (state == 'h325) ;
else 
back_fifo_wr<=0;

这里也是按照字节处理的,明天硬件测试时候可以在上位机将6号指令换成7号指令。看看是否能够在不进行JTAG操作的时候顺利读写。



///tested ok
int ejtag_scan(unsigned int ir0dr1,unsigned int wb,char*p,unsigned int bits)
{

printf("enter ejtag_scan >>>>   \n");
printf("bits = %d ir0dr1=%d  wb=%d\n",bits,ir0dr1,wb);
    unsigned int cmd,i,j,t ;
    char*tmp=malloc(bits/8+32);
    cmd=(ir0dr1)?(4<<25):(3<<25);
    if(wb)cmd|=1<<24 ;
    cmd|=bits ;
    fill_byte(cmd,tmp);
    j=bits/8+1 ;//字节拷贝,
    for(i=0;i<j;i++)tmp[4+i]=p[i];
    t=align(bits,32);//32位对齐
    t=t/8 ;
    t+=4 ;//加上命令的四个字节
    #ifdef VC_TEST 
    lw_usb_write(tmp,t);
    lw_usb_write(NULL,0);
    printf("write data to usb len = %d!\n",t);
    getchar();
    #else 
    usb_buffer_write(tmp,t);//是否立即写回了。
    #endif 
    free(tmp);
printf("return from  ejtag_scan <<<<<<<  \n");
    return 1 ;

}

以下是NIOS的对应处理片段。

        else if((op_code==3)||(op_code==4))
        {
            EJTAG_FIFO_DATA=i ;
            t=i&0xffffff ;

            t=t>>5 ;
            if(i&31)t++;//首先转变成32个BIT,多少个字
            for(i=0;i<t;++i)
            {
                while(EJTAG_STATUS&2); //1:wb_dout <= {29'b0,state_idle,front_fifo_full,back_fifo_empty} 
                EJTAG_FIFO_DATA=usb_rd_u32();
            }//将这写字都发送给JTAG控制器。
        }

这里是以BITS为单位。没有发现什么BUG。



今天实现的现象是无法回读,通过以上分析,我觉得比较妥当的入手点是ejtag_read_back,这个函数,将6号指令修改成7号无条件回读。看是否能够立即回读回数据来,如果能。如果不能,找基本通讯对话的问题,如果能则继续实验看看JTAG控制器是否存在问题造成了写会FIFO内部没有足够的数。


//////////////////////////

代码中1处小小修改:


static int usb_read_sync2()
{
    int ret=1 ;

printf("eneter usb_read_sync2() >>>>>>>> \n");
printf("  usb_read_sync2() >>>usb_expect_read = %d  \n",usb_expect_read);
    if(usb_expect_read)
    {
      //  fpga_info_ejtag(7,0,NULL);
        //set read back command
      //  usb_write_flush();
        if(usb_read_buffer)free(usb_read_buffer);
        usb_read_buffer=malloc(usb_expect_read + 512 );   //buffer 不至于因为512整数读书的内存错误。
       // ret=usb_bulk_read(loongsonejtag_jtag_handle->u


这个问题解决之后将考虑将把7号命令做成加速器。不需要NIOS处理器循环操作,只告诉加速器需要填充多少个32BIT的字就可以。

加速器做成功之后就可以考虑进行实际的JTAG ID的读取。如果读取顺利就可以接入OPENOCD进行GDB操作了。

<------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->

2013-8-13 

bug已经解决,是10号指令的处理有问题,修改了NIOS代码。解决。

今天调试成功,暂时用8MHZ的TCK速度连通了OPENOCD。调试LS1板子没有问题。

今天晚上回家写了一个小小的加速器,很精简,很巧妙。


module padding_fsm(
input clk,
input fifo_full,
input wr,
input [15:0]din,
output reg wr_fifo,idle
);

reg [15:0] cnt;
always@(posedge clk)
if (wr)cnt<=din;
else if (wr_fifo) cnt<=cnt-1;
always@(*) wr_fifo = (~|cnt ) & (~fifo_full); 
always @ (posedge clk)idle<=~|cnt;
endmodule

是自动添填充FIFO的小加速器,没有延迟,不占用另外周期。

以下是调用此加速器的顶层:



module wb_ejtag(
        input clk,rst,clk_2x,
        input wb_wr,
        input[1:0] wb_addr,
        input [31:0]wb_din,
        output reg [31:0]wb_dout,
        input wb_rd,
        input ejtag_tdo,
        output ejtag_tdi,ejtag_tck,ejtag_tms,
        output reg ejtag_led,ejtag_rrst,ejtag_trst
    ); 
    wire state_idle;
    wire   front_fifo_wr, front_fifo_full;
    wire [31:0] front_fifo_d;
    reg  back_fifo_rd;
    wire back_fifo_empty ;
    wire [31:0] back_fifo_q;
    reg front_fifo_wrr;
    assign front_fifo_d = wb_din ;
    assign front_fifo_wr  =  (wb_addr[1:0] == 0) & wb_wr &(~front_fifo_wrr);
    
wire [15:0]back_fifo_usedw;
    always@ (posedge clk)front_fifo_wrr<=front_fifo_wr;
    
    
         wire wr_front_fifo_by_padding_fsm ;
    ejtag_top  uu(
                   .clk(clk),
                   .clk_2x(clk_2x),
                   .rst(rst),
                   .state_idle(state_idle),
                   .front_fifo_wr(front_fifo_wr   |   wr_front_fifo_by_padding_fsm),
                   .front_fifo_full(front_fifo_full),
                   .front_fifo_d(front_fifo_d),
                   .back_fifo_rd(back_fifo_rd),
                   .back_fifo_empty(back_fifo_empty),
                   .back_fifo_q(back_fifo_q),
                   .ejtag_tck(ejtag_tck),
                   .ejtag_tdi(ejtag_tdi),
                   .ejtag_tms(ejtag_tms),
                   .ejtag_tdo(ejtag_tdo),
                   .back_fifo_usedw(back_fifo_usedw)
               );
               
         wire  wr_padding_fsm; 
         wire  padding_fsm_idle ;
            
padding_fsm padding_fsm(
.clk(clk),
.fifo_full(front_fifo_full),
.wr(wr_padding_fsm),
.din(wb_din[15:0]),
.wr_fifo(wr_front_fifo_by_padding_fsm),
.idle(padding_fsm_idle)
);
    
    assign wr_padding_fsm  =  (wb_addr[1:0] == 2) & wb_wr  ;
    
    


    //-----------------------------------------
    reg wb_rdr,wb_rdrr;


    always @ (*)wb_rdr<= wb_rd & (wb_addr[1:0] == 0);
    always @ (posedge clk)wb_rdrr<= wb_rdr;
    always @ (*)back_fifo_rd = {wb_rdrr,wb_rdr}==2'b01;
    //-----------------------------------------




always @ (posedge clk) if((wb_wr)&(wb_addr == 1)) ejtag_led <= wb_din[0];
always @ (posedge clk) if((wb_wr)&(wb_addr == 1)) ejtag_trst <= wb_din[1];
always @ (posedge clk) if((wb_wr)&(wb_addr == 1)) ejtag_rrst <= wb_din[2]; 




    always @ (posedge clk)
    case (wb_addr)
        0:wb_dout <= back_fifo_q;
        1:wb_dout <= {28'b0,padding_fsm_idle,state_idle,front_fifo_full,back_fifo_empty} ; //some state
        2:wb_dout <= {16'b0 , back_fifo_usedw} ; //some state
         
        default
        wb_dout<= 'hx ;


    endcase




endmodule

用了一个或逻辑实现了NIOS和加速器的读写的统一。







原创粉丝点击