This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] DS90UB953-Q1:无法从 ub960进入 BIST 模式

Guru**** 651100 points
Other Parts Discussed in Thread: ALP
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/1109957/ds90ub953-q1-unable-to-enter-bist-mode-from-ub960

器件型号:DS90UB953-Q1
主题中讨论的其他器件:ALP

您好!

我们的系统有两个 ub960、每个都有四个 ub953连接到它。 每个 ub953都连接到摄像头。 整个系统工作正常、我们能够从摄像头流式传输图像。 我正在尝试编写一个程序、通过使用 BIST 功能来评估 ub960和 ub953之间的链路质量。 但是、当我将 ub960上的 BIST 控制寄存器(0xB3)设置为0x1时、任何连接的 ub953都不会进入 BIST 模式。 检查 ub960上每个 RX 端口的 PORT_DEBUG 寄存器(0xD0)中的 SER_BIST_ACT 位即可确认这一点。 我还检查 ub953上的 REMOAL_PAR_CAP1寄存器(0x35)、BIST_EN 位为0。 在 ub960上启用 ub953后、是否有任何原因使其无法进入 BIST 模式? 此外、由于寄存器0xB3不是特定于 RX 端口、它是否会在所有连接的 ub953上启用 BIST? 谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Kevin:

    您能否运行随 ALP 软件提供的示例代码、 其中四 个 UB953连接 到一个 UB960?  希望运行提供的示例代码将使您在所有 UB953上进入正常工作的 BIST 模式。  

     

    ## BIST_953_960_WithForcedError.py
    ##
    ## revision 1.1 June 26, 2018
    ##
    ########
    ######################
    ##
    ## This script file is used to check the link between the 953 and 960
    ##
    ## The Built In Self Test (BIST) generates a puesdo random sequence
    ## and checks for CRC errors between transmitted and received sequence.
    ##
    ## Rev. 1.1
    ## Added Parity Errors, restructured code
    ##
    ##
    ######################
    
    import time
    
    UB960 = 0x7A
    
    #	Port selection, Passthrough, and aliasing
    board.WriteI2C(UB960, 0x4C, 0x01)
    board.WriteI2C(UB960, 0x58, 0x5E)
    board.WriteI2C(UB960, 0x5C, 0x18)											#953a aliasing
    
    board.WriteI2C(UB960, 0x4C, 0x12)
    board.WriteI2C(UB960, 0x58, 0x5E)
    board.WriteI2C(UB960, 0x5C, 0x20)											#953b aliasing
    
    board.WriteI2C(UB960, 0x4C, 0x24)
    board.WriteI2C(UB960, 0x58, 0x5E)
    board.WriteI2C(UB960, 0x5C, 0x22)											#953c aliasing
    
    board.WriteI2C(UB960, 0x4C, 0x38)
    board.WriteI2C(UB960, 0x58, 0x5E)
    board.WriteI2C(UB960, 0x5C, 0x24)											#953d aliasing
    
    board.WriteI2C(UB960, 0x4C, 0x01)
    
    for x in range (0, 4):
    
    	#print ("x = ", x)
    
    	if x == 0:
    		UB953 = 0x18
    		board.WriteI2C(UB960, 0x4C, 0x01)		#0x4C is FPD3_PORT_SEL. RX0 R/W Enabled				
    		print ("\t\tRX0")
    	elif x == 1:
    		UB953 = 0x20
    		board.WriteI2C(UB960, 0x4C, 0x12)		#0x4C is FPD3_PORT_SEL. RX1 R/W Enabled
    		print ("\t\tRX1")
    	elif x == 2:
    		UB953 = 0x22
    		board.WriteI2C(UB960, 0x4C, 0x24)		#0x4C is FPD3_PORT_SEL. RX2 R/W Enabled
    		print ("\t\tRX2")
    	else:
    		UB953 = 0x24
    		board.WriteI2C(UB960, 0x4C, 0x38)		#0x4C is FPD3_PORT_SEL. RX3 R/W Enabled
    		print ("\t\tRX3")
    
    
    	#	Digital Reset except for registers
    	board.WriteI2C(UB953, 0x01, 0x01)											#Resets 953a
    	time.sleep(0.5)
    	board.WriteI2C(UB960, 0x01, 0x01)											#Resets 960
    	time.sleep(0.5)
    
    	print ("Devices Reset")
    
    
    	#	Confirm Devices can communicate with each other
    	print ("960 Device ID (0x00):", hex(board.ReadI2C(UB960, 0x00, 1)))			#960 Device ID, should be 0x7A, check 0x00 for confirmation
    	time.sleep(0.5)
    	print ("953 Device ID (0x00):", hex(board.ReadI2C(UB953, 0x00, 1)))			#953 Device ID, should be 0x30, check 0x5B for confirmation
    
    
    	print ("------------------------------------------------------------------")
    	time.sleep(0.5)
    
    
    	#	Read Reciever Lock Status
    	print ("Reciever Lock Status (0x4D):", hex(board.ReadI2C(UB960, 0x4D, 1)))						#0x04 is DEVICE_STS of 960
    	print ("Bit [1:0] should be high. i.e. 0x13")
    
    	print ("------------------------------------------------------------------")
    
    	#time.sleep(1)
    
    
    
    	#	Enable write for Port0 of FPD3_PORT_SEL. Note this is done earlier in script 
    	#board.WriteI2C(UB960, 0x4C, 0x01)											#0x4C is FPD3_PORT_SEL
    
    
    
    	#	Clear Errors and Error Count
    	board.WriteI2C(UB953, 0x49, 0x28)											#0x49 is BC_CTRL. 0x28 selects BIST_CRC ERR CLR and CRC ERR CLR
    
    	print ("Read BCC Error Status (0x79):", hex(board.ReadI2C(UB953, 0x79, 1)))	#Clear possible BCC_Error by Reading BCC Error Status
    	print ("Consult Register 0x79 on the SER for more information")
    
    	print ("------------------------------------------------------------------")
    
    	print ("Pre-Error Link Status of 953 (0x52):", hex(board.ReadI2C(UB953, 0x52,1)))					#0x52 is GENERAL_STS of 953
    	print ("Should read 0x45 = RX Lock Detect, HS PLL Lock, Link Detect")
    
    	print ("------------------------------------------------------------------")
    
    	print ("BIST CRC Error count (0x54) on 953 before BIST.", hex(board.ReadI2C(UB953, 0x54, 1)))#0x54 is BIST ERR CNT
    
    	print ("------------------------------------------------------------------")
    
    
    
    
    
    	#	Enabling BIST, Error, and Lock-Change Status
    	print ("Read BIST CTL register (0xB3) Before BIST ENABlED", hex(board.ReadI2C(UB960, 0xB3, 1)))		#0xB3 is BIST_CTL, bit 1 controls if enabled or not
    	print ("Should read 0x00 or 0x08\n")
    
    	board.WriteI2C(UB960, 0xB3, 0x01)											#Enable BIST using BIST_CTL
    
    	print ("Read BIST CTL (0xB3) register After BIST ENABLED", hex(board.ReadI2C(UB960, 0xB3, 1)))		#0xB3 is BIST_CTL
    	print ("Should read 0x01")
    
    	time.sleep(0.25)
    	print ("------------------------------------------------------------------")
    	print ("Read BIST Lock Status Change of 960 RIGHT AFTER BIST enabled (0x4D):", hex(board.ReadI2C(UB960, 0x4D,1)))		#0x4D is RX_PORT_STS1 of 960
    	print ("Read to clear BIST enable Lock Status Change.")
    
    	board.WriteI2C(UB960, 0xD0, 0x01)											#Force 1 Error, 0xD0 is PORT_DEBUG register
    
    	#board.WriteI2C(UB960, 0xD0, 0x02)											#Force Continious errors, 0xD0 is PORT_DEBUG register
    	time.sleep(3)																#Can run BIST for as long as needed
    	#board.WriteI2C(UB960, 0xD0, 0x00)											#If forced continious errors, stop forcing errors
    
    	print ("Read Post-BIST Lock Status Change of 960 RIGHT BEFORE BIST disabled (0x4D):", hex(board.ReadI2C(UB960, 0x4D,1)))		#0x4D is RX_PORT_STS1 of 960
    	print ("bits [1:0] should be high i.e. 0x3, If lock status changed during BIST, bit [4] will be high")
    
    
    
    	#	Disable BIST and Port0
    	board.WriteI2C(UB960, 0xB3, 0x00)											#Disable BIST, using BIST_CTL
    	#board.WriteI2C(UB960, 0x4C, 0x00)											#0x4C is FPD3_PORT_SEL
    	print ("------------------------------------------------------------------")
    
    
    	#	Check if Error(s) occured
    	print ("Reciever Lock Status (0x4D):", hex(board.ReadI2C(UB960, 0x4D, 1)))						#0x4D is PORT_STS1 of 960
    	print ("Bits [1:0] should be high. i.e. 0x13")
    	print ("------------------------------------------------------------------")
    
    
    	print ("Pre-Error Link Status of 953 (0x52):", hex(board.ReadI2C(UB953, 0x52,1)))					#0x52 is GENERAL_STS of 953
    	print ("Should read 0x4D = RX Lock Detect, HS PLL Lock, Link Detect, and BIST CRC Error")
    	print ("------------------------------------------------------------------")
    
    
    	print ("BIST CRC Error count (0x54) on 953 after BIST.", hex(board.ReadI2C(UB953, 0x54, 1))) #0x54 is BIST ERR CNT
    	print ("Parity Error count MSB (0x56) on 960.", hex(board.ReadI2C(UB960, 0x56, 1))) #0x56 is number of Parity error 8 most significant bits
    	print ("Parity Error count LSB (0x55) on 960.", hex(board.ReadI2C(UB960, 0x55, 1))) #0x55 is number of Parity error 8 least significant bits	
    	print ("------------------------------------------------------------------")
    
    	
    	#	Clear BIST Errors on 953
    	board.WriteI2C(UB953, 0x49, 0x28)											#0x49 is BC_CTRL. 0x28 selects BIST_CRC ERR CLR and CRC ERR CLR
    
    	print ("#################################################################") 			#New line Printed
    
    print ("\n\n")


    由于寄存器0xB3为共享寄存器、它将尝试在所有 UB953上启用 BIST。 为了使 BIST 在 UB953上激活、必须事先正确设置 UB953和反向通道、您可以在提供的示例代码中看到如何设置 UB953和反向通道。  

    请注意、与示例代码中一样、您必须首先配置反向通道、然后才能启用 BIST。

    如果您没有 ALP 软件、您可以 在此处下载 ALP

    此致、

    约书亚  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已经将代码与该脚本进行了比较、除了我检查 SER_BIST_ACT 位以验证 ub953是否处于 BIST 模式之外、没有看到任何主要差异。 脚本执行的所有检查(RX_LOCK_DETECT、HS_PLL_LOCK、串行器上的 LINK_DET、解串器上的 LOCK_STS 等)也都是为我的代码传递的。 由于串行器上的 REMOAL_PAR_CAP1寄存器(0x35)填充了正确的 mport 和 PORT_NUM 字段、因此反向通道肯定是设置和工作的。

    遗憾的是、我无法使用 ALP 软件进行测试、因为它似乎是一个 Windows GUI 程序、这些系统运行 Linux、我只能进行 ssh 访问。 该脚本是否有不需要 ALP 软件运行的版本?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Kevin:

    我可以让您向我发送您的脚本吗?

    遗憾的是、我们没有可以在 Linux 上运行的 ALP 或脚本版本、但这应该是一个简单的过程、您可以将脚本中的读取和写入函数转换为可在 Linux 环境中使用的表单。  

    谢谢、

    约书亚

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    #include <stdio.h>
    #include <fstream>
    #include <fcntl.h>
    #include <unistd.h>
    #include <linux/i2c.h>
    #include <linux/i2c-dev.h>
    #include <errno.h>
    #include <sys/ioctl.h>
    #include <cstring>
    
    int i2c_bus = 2;
    
    const int num_des = 2;
    const int num_des_ports = 4;
    const int des_add[num_des] = { 0x30, 0x3d };
    
    const int num_ser = 8;
    const int ser_add[num_des][num_des_ports] = { { 0x43, 0x42, 0x41, 0x40 },
                                                  { 0x47, 0x46, 0x45, 0x44 } };
    
    int get_serializer_address(int sidx)
    {
      return ser_add[sidx / num_des_ports][sidx % num_des_ports];
    }
    
    const int num_cam = 8;
    const int cam_add[num_des][num_des_ports] = { { 0x63, 0x62, 0x61, 0x60 },
                                                  { 0x67, 0x66, 0x65, 0x64 } };
    
    int get_camera_address(int cidx)
    {
      return cam_add[cidx / num_des_ports][cidx % num_des_ports];
    }
    
    class I2CGetSet
    {
    public:
      I2CGetSet() : file(0), prev_chip_address(-255)
      {
        char buf[512];
        snprintf(buf, 511, "/dev/i2c-%d", i2c_bus);
        file = open(buf, O_RDWR);
      }
    
      ~I2CGetSet()
      {
        cleanup();
      }
    
      void cleanup()
      {
        if (file > 0)
          close(file);
        file = 0;
      }
    
      // Return codes:
      //  -1 -> popen failed
      //  -2 -> pclose didn't return 0
      //  -3 -> i2cget output couldn't be converted to u8
      //  -4 -> open failed
      //  -5 -> ioctl(I2C_SLAVE_FORCE) failed
      //  -6 -> ioctl(I2C_SMBUS) failed
      //   _ -> value
      int get(int chip_address, int data_address)
      {
        if (file <= 0)
          return -4;
        if (chip_address != prev_chip_address)
        {
          if (ioctl(file, I2C_SLAVE_FORCE, chip_address) < 0)
          {
            prev_chip_address = -255;
            return -5;
          }
          prev_chip_address = chip_address;
        }
        // below is equivalent to i2c_smbus_read_byte_data()
        i2c_smbus_data data;
        i2c_smbus_ioctl_data args;
        args.read_write = I2C_SMBUS_READ;
        args.command = data_address;
        args.size = I2C_SMBUS_BYTE_DATA;
        args.data = &data;
        int err = ioctl(file, I2C_SMBUS, &args);
        if (err < 0)
          printf("I2C_SMBUS-read fail: %s %d\n", strerror(errno), err);
        return err < 0 ? -6 : (data.byte & 0x0FF);
      }
    
      // Return codes:
      //   0 -> success
      //  -1 -> popen failed
      //  -2 -> pclose didn't return 0
      //  -3 -> open failed
      //  -4 -> reading current value failed
      //  -5 -> ioctl(I2C_SLAVE_FORCE) failed
      //  -6 -> ioctl(I2C_SMBUS) failed
      int set(int chip_address, int data_address, int mask, int value)
      {
        if (file <= 0)
          return -3;
        int oldvalue =
            mask < 0 ? 0 : get(chip_address, data_address);  // read current value
        if (oldvalue < 0)
        {
          printf("i2cset: failed to read old value %d\n", oldvalue);
          return -4;
        }
        if (chip_address != prev_chip_address)
        {
          if (ioctl(file, I2C_SLAVE_FORCE, chip_address) < 0)
          {
            prev_chip_address = -255;
            return -5;
          }
          prev_chip_address = chip_address;
        }
        if (mask >= 0)
          value = (value & mask) | (oldvalue & ~mask);  // apply mask
        // below is equivalent to i2c_smbus_write_byte_data()
        i2c_smbus_data data;
        data.byte = value;
        i2c_smbus_ioctl_data args;
        args.read_write = I2C_SMBUS_WRITE;
        args.command = data_address;
        args.size = I2C_SMBUS_BYTE_DATA;
        args.data = &data;
        int err = ioctl(file, I2C_SMBUS, &args);
        if (err < 0)
          printf("I2C_SMBUS-write fail: %s %d\n", strerror(errno), err);
        return err < 0 ? -6 : 0;
      }
    
    private:
      int file, prev_chip_address;
    };
    
    int is_busy(int file, int chip_address)
    {
      int ret = ioctl(file, I2C_SLAVE, chip_address);
      if (ret < 0 && errno == EBUSY)  // bound to driver?
        return 1;
      return 0;
    }
    
    int check_devices()
    {
      printf("\nChecking for devices...\n");
    
      char buf[512];
      snprintf(buf, 511, "/dev/i2c-%d", i2c_bus);
      int file = open(buf, O_RDWR);
      if (file <= 0)
      {
        printf("failed to open i2c bus %d!\n", i2c_bus);
        return 1;
      }
    
      // deserializers
      for (int d = 0; d < num_des; ++d)
      {
        if (!is_busy(file, des_add[d]))
        {
          printf("des %#x not detected!\n", des_add[d]);
          close(file);
          return 2;
        }
      }
      printf("Deserializers detected.\n");
    
      // serializers
      for (int s = 0; s < num_ser; ++s)
      {
        int sadd = get_serializer_address(s);
        if (!is_busy(file, sadd))
        {
          printf("ser %#x not detected!\n", sadd);
          close(file);
          return 3;
        }
      }
      printf("Serializers detected.\n");
    
      // cameras
      for (int c = 0; c < num_cam; ++c)
      {
        int cadd = get_camera_address(c);
        if (!is_busy(file, cadd))
        {
          printf("cam %#x not detected!\n", cadd);
          close(file);
          return 4;
        }
      }
      printf("Cameras detected.\n");
    
      printf("All devices detected successfully.\n");
    
      return 0;
    }
    
    int reset_ser_and_des(I2CGetSet& i2c)
    {
      printf("\nResetting serializers and deserializers...\n");
    
      for (int s = 0; s < num_ser; ++s)
      {
        int sadd = get_serializer_address(s);
        int ret = i2c.set(sadd, 0x1, -1, 0x1);
        if (ret != 0)
        {
          printf("failed to set reg 0x1 on ser %#x %d!\n", sadd, ret);
          return 1;
        }
      }
    
      usleep(500000);
    
      for (int d = 0; d < num_des; ++d)
      {
        int ret = i2c.set(des_add[d], 0x1, -1, 0x1);
        if (ret != 0)
        {
          printf("failed to set reg 0x1 on des %#x %d!\n", des_add[d], ret);
          return 2;
        }
      }
    
      usleep(500000);
    
      printf("Reset complete.\n");
    
      return 0;
    }
    
    int verify_device_ids(I2CGetSet& i2c)
    {
      printf("\nVerifying device ids...\n");
    
      for (int d = 0; d < num_des; ++d)
      {
        int des_id = i2c.get(des_add[d], 0x0) >> 1;
        if (des_id != des_add[d])
        {
          printf("des %#x id mismatch (%#x)!\n", des_add[d], des_id);
          return 1;
        }
      }
    
      for (int s = 0; s < num_ser; ++s)
      {
        int sadd = get_serializer_address(s);
        int ser_id = i2c.get(sadd, 0x0) >> 1;
        // serializer id from deserializer
        int didx = s / num_des_ports;
        int dadd = des_add[didx];
        int dport = s % num_des_ports;
        if (i2c.set(dadd, 0x4C, 0x30, dport << 4) != 0)  // read port select
        {
          printf("failed to select port on des %#x-%d\n", dadd, dport);
          return 2;
        }
        int des_ser_id = i2c.get(dadd, 0x5b) >> 1;
        // deserializer id from serializer
        int ser_des_id = i2c.get(sadd, 0x37) >> 1;
        if (ser_id != 0x18 || ser_id != des_ser_id || ser_des_id != dadd)
        {
          printf("ser %#x id mismatch (%#x %#x %#x)!\n", sadd, ser_id, des_ser_id,
                 ser_des_id);
          return 3;
        }
        // check REMOTE_PAR_CAP1 on serializer
        int remote_par_cap1 = i2c.get(sadd, 0x35);
        if (remote_par_cap1 != (0x10 | dport))
        {
          printf("ser %#x REMOTE_PAR_CAP1 error (%#x %#x)!\n", sadd,
                 remote_par_cap1);
          return 4;
        }
      }
    
      printf("ID checks passed.\n");
    
      return 0;
    }
    
    int verify_lock_status(I2CGetSet& i2c)
    {
      printf("\nVerifying lock status...\n");
    
      for (int d = 0; d < num_des; ++d)
      {
        for (int p = 0; p < num_des_ports; ++p)
        {
          if (i2c.set(des_add[d], 0x4C, 0x30, p << 4) != 0)  // read port select
          {
            printf("failed to select port on des %#x-%d\n", des_add[d], p);
            return 1;
          }
          int sts1 = i2c.get(des_add[d], 0x4d);
          int sts2 = i2c.get(des_add[d], 0x4e);
          if (sts1 < 0 || sts2 < 0)
          {
            printf("failed to read status regs of des %#x-%d!\n", des_add[d], p);
            return 2;
          }
          int port_num = sts1 >> 6;
          int lock_sts = sts1 & 0x1;
          int freq_stable = sts2 & 0x4;
          int no_fpd3_clk = sts2 & 0x2;
          if (port_num != p || !lock_sts || !freq_stable || no_fpd3_clk)
          {
            printf("des %#x-%d not locked (%#x %#x)!\n", des_add[d], p, sts1, sts2);
            return 3;
          }
        }
      }
      printf("All deserializer ports indicate lock.\n");
    
      for (int s = 0; s < num_ser; ++s)
      {
        int sadd = get_serializer_address(s);
        int sts = i2c.get(sadd, 0x52);
        if (sts < 0)
        {
          printf("failed to read status reg of ser %#x!\n", sadd);
          return 4;
        }
        int rx_lock_detect = sts & 0x40;
        int hs_pll_lock = sts & 0x4;
        int link_det = sts & 0x1;
        if (!rx_lock_detect || !hs_pll_lock || !link_det)
        {
          printf("ser %#x not locked (%#x)!\n", sadd, sts);
          return 5;
        }
      }
      printf("All serializers indicate lock.\n");
    
      printf("Lock status verified.\n");
    
      return 0;
    }
    
    int run_bist(I2CGetSet& i2c, int bist_len, int didx, int dport)
    {
      int dadd = des_add[didx];
      int sadd = ser_add[didx][dport];
    
      printf("\nRunning BIST for [%#x-%d <-> %#x]...\n", dadd, dport, sadd);
    
      // read and write port select
      if (i2c.set(dadd, 0x4C, 0x30 | 0xF, (dport << 4) | (1 << dport)) != 0)
      {
        printf("failed to select port on des %#x-%d\n", dadd, dport);
        return 1;
      }
    
      printf("Clearing error counts prior to BIST...\n");
    
      {
        if (i2c.set(sadd, 0x49, 0x28, 0x28) != 0)
        {
          printf("failed to clear err cnts on ser %#x!\n", sadd);
          return 2;
        }
        if (i2c.get(sadd, 0x52) < 0)
        {
          printf("failed to read reg 0x52 on ser %#x!\n", sadd);
          return 3;
        }
        if (i2c.get(sadd, 0x54) < 0)
        {
          printf("failed to read reg 0x54 on ser %#x!\n", sadd);
          return 4;
        }
      }
    
      printf("Enabling BIST mode and verifying lock after...\n");
    
      {
        int bist_ctrl_before = i2c.get(dadd, 0xB3);
        if (bist_ctrl_before < 0)
        {
          printf("failed to read reg 0xB3 on des %#x\n", dadd);
          return 5;
        }
        printf(" BIST_CTRL before = %#x\n", bist_ctrl_before);
        if (i2c.set(dadd, 0xB3, -1, 0x1) != 0)
        {
          printf("failed to set BIST_EN on des %#x\n", dadd);
          return 6;
        }
        usleep(250000);
        int bist_ctrl_after = i2c.get(dadd, 0xB3);
        if (bist_ctrl_after < 0)
        {
          printf("failed to read reg 0xB3 on des %#x\n", dadd);
          return 7;
        }
        printf(" BIST_CTRL after  = %#x\n", bist_ctrl_after);
        if (bist_ctrl_after != 0x1)
        {
          printf("failed to enable BIST on des %#x\n", dadd);
          return 8;
        }
        int sts1 = i2c.get(dadd, 0x4D);
        if (sts1 < 0 || (sts1 >> 6) != dport)
        {
          printf("failed to read reg 0x4D on des %#x-%d\n", dadd, dport);
          return 9;
        }
        if (!(sts1 & 0x1))
        {
          printf("no lock on des %#x-%d after setting BIST_CTRL\n", dadd, dport);
          return 10;
        }
      }
    
      printf("Running BIST for %d seconds...\n", bist_len);
    
      bool ser_was_in_bist_mode = true;
    
      for (int t = 0; t < bist_len; t += 5)
      {
        int sleep_secs = std::min(bist_len - t, 5);
        usleep(sleep_secs * 1000000);
        printf("... %d of %d\n", t + sleep_secs, bist_len);
    
        // verify BIST is enabled on the serializer
        int port_debug = i2c.get(dadd, 0xD0);
        if (port_debug != 0x20)
        {
          printf("  BIST is not enabled on ser %#x (%#x)!\n", sadd, port_debug);
          printf("    ser = %#x %#x %#x %#x %#x %#x %#x %#x %#x\n",
                 i2c.get(sadd, 0x3), i2c.get(sadd, 0x9), i2c.get(sadd, 0x13),
                 i2c.get(sadd, 0x14), i2c.get(sadd, 0x32), i2c.get(sadd, 0x35),
                 i2c.get(sadd, 0x52), i2c.get(sadd, 0x5D), i2c.get(sadd, 0x5C),
                 (i2c.get(sadd, 0x56) << 8) | i2c.get(sadd, 0x55));
          printf("    des = %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x\n",
                 i2c.get(dadd, 0xB3), i2c.get(dadd, 0x47), i2c.get(dadd, 0x4d),
                 i2c.get(dadd, 0x4e),
                 (i2c.get(dadd, 0x4f) << 8) | i2c.get(dadd, 0x50),
                 i2c.get(dadd, 0x51), i2c.get(dadd, 0x54),
                 (i2c.get(dadd, 0x55) << 8) | i2c.get(dadd, 0x56),
                 i2c.get(dadd, 0x7a), i2c.get(dadd, 0x7b));
          ser_was_in_bist_mode = false;
        }
      }
    
      printf("Disabling BIST mode...\n");
    
      {
        int bist_ctrl_before = i2c.get(dadd, 0xB3);
        if (bist_ctrl_before < 0)
        {
          printf("failed to read reg 0xB3 on des %#x\n", dadd);
          return 11;
        }
        printf(" BIST_CTRL before = %#x\n", bist_ctrl_before);
        if (i2c.set(dadd, 0xB3, -1, 0x0) != 0)
        {
          printf("failed to set BIST_EN on des %#x\n", dadd);
          return 12;
        }
        usleep(250000);
        int bist_ctrl_after = i2c.get(dadd, 0xB3);
        if (bist_ctrl_after < 0)
        {
          printf("failed to read reg 0xB3 on des %#x\n", dadd);
          return 13;
        }
        printf(" BIST_CTRL after  = %#x\n", bist_ctrl_after);
        if (bist_ctrl_after != 0x0)
        {
          printf("failed to disable BIST on des %#x\n", dadd);
          return 14;
        }
        int port_debug = i2c.get(dadd, 0xD0);
        if (port_debug != 0x0)
        {
          printf("BIST is still enabled on ser %#x (%#x)\n", sadd, port_debug);
          return 15;
        }
        if (!ser_was_in_bist_mode)
        {
          printf("BIST was not enabled on ser %#x!\n", sadd);
          return 16;
        }
      }
    
      printf("Gathering results...\n");
    
      int ser_err_cnt = 0, des_err_cnt = 0;
      bool ser_lock_lost = false, des_lock_lost = false;
    
      {
        int sts = i2c.get(dadd, 0x4D);
        if (sts < 0 || (sts >> 6) != dport)
        {
          printf("failed to read reg 0x4D on des %#x-%d\n", dadd, dport);
          return 17;
        }
        int bist_err_cnt = i2c.get(dadd, 0x57);
        if (bist_err_cnt < 0)
        {
          printf("failed to read reg 0x57 on des %#x-%d\n", dadd, dport);
          return 18;
        }
        des_lock_lost = !(sts & 0x1) || (sts & 0x10);
        des_err_cnt = bist_err_cnt;
      }
    
      {
        int sts = i2c.get(sadd, 0x52);
        if (sts < 0)
        {
          printf("failed to read reg 0x52 on ser %#x\n", sadd);
          return 19;
        }
        int bist_err_cnt = i2c.get(sadd, 0x54);
        if (bist_err_cnt < 0)
        {
          printf("failed to read reg 0x54 on ser %#x\n", sadd);
          return 20;
        }
        ser_lock_lost =
            !(sts & 0x40) || (sts & 0x10) || !(sts & 0x4) || !(sts & 0x1);
        ser_err_cnt = bist_err_cnt;
      }
    
      if (des_lock_lost || des_err_cnt > 0 || ser_lock_lost || ser_err_cnt > 0)
      {
        printf("Link [%#x-%d <-> %#x] errors detected.\n", dadd, dport, sadd);
        printf("   ll = (%d,%d)  cnts = (%d,%d)\n", des_lock_lost, ser_lock_lost,
               des_err_cnt, ser_err_cnt);
        return -1;
      }
      else
      {
        printf("Link [%#x-%d <-> %#x] passed without errors.\n", dadd, dport, sadd);
        return 0;
      }
    }
    
    int main(int argc, char* argv[])
    {
      if (argc != 2)
      {
        printf("invalid syntax:  cam_diag bist_run_len_seconds\n");
        return 1;
      }
    
      int bist_len = atoi(argv[1]);
      if (bist_len < 10 || bist_len > 3600)
      {
        printf("invalid bist_len: [10, 3600]\n");
        return 2;
      }
    
      if (check_devices())
      {
        printf("check_devices failed!\n");
        return 3;
      }
    
      I2CGetSet i2c;
    
      if (reset_ser_and_des(i2c))
      {
        printf("reset_ser_and_des failed!\n");
        return 4;
      }
    
      if (verify_device_ids(i2c))
      {
        printf("verify_device_ids failed!\n");
        return 5;
      }
    
      if (verify_lock_status(i2c))
      {
        printf("verify_lock_status failed!\n");
        return 6;
      }
    
      for (int d = 0; d < num_des; ++d)
      {
        for (int p = 0; p < num_des_ports; ++p)
        {
          int ret = run_bist(i2c, bist_len, d, p);
          if (ret > 0)
            printf("BIST failed to run!\n");
          else if (ret == 0)
            printf("BIST completed successfully. No link errors detected.\n");
          else
            printf("BIST completed successfully. Link errors were detected.\n");
        }
      }
    
      usleep(250000);
    
      reset_ser_and_des(i2c);
    
      return 0;
    }

    这是我的程序的代码。 下面是运行它的日志。 除了从未置位 SER_BIST_ACT 之外、一切都正常。 我发现、如果我通过设置寄存器0x14中的 LOCAL_BIST_EN 在 ub953上手动启用 BIST 模式、则会在解串器上声明 SER_BIST_ACT。 但是、在设置 LOCAL_BIST_EN 之后、在对系统进行下电上电之前、我无法通过 i2c 与 ub953进行通信。

    Checking for devices...
    Deserializers detected.
    Serializers detected.
    Cameras detected.
    All devices detected successfully.
    
    Resetting serializers and deserializers...
    Reset complete.
    
    Verifying device ids...
    ID checks passed.
    
    Verifying lock status...
    All deserializer ports indicate lock.
    All serializers indicate lock.
    Lock status verified.
    
    Running BIST for [0x30-0 <-> 0x43]...
    Clearing error counts prior to BIST...
    Enabling BIST mode and verifying lock after...
     BIST_CTRL before = 0
     BIST_CTRL after  = 0x1
    Running BIST for 10 seconds...
    ... 5 of 10
      BIST is not enabled on ser 0x43 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x10 0x45 0 0
        des = 0x1 0 0x3 0xc 0x6400 0 0 0 0x2 0x1
    ... 10 of 10
      BIST is not enabled on ser 0x43 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x10 0x45 0 0
        des = 0x1 0 0x3 0x4 0x6400 0 0 0 0 0
    Disabling BIST mode...
     BIST_CTRL before = 0x1
     BIST_CTRL after  = 0
    BIST was not enabled on ser 0x43!
    BIST failed to run!
    
    Running BIST for [0x30-1 <-> 0x42]...
    Clearing error counts prior to BIST...
    Enabling BIST mode and verifying lock after...
     BIST_CTRL before = 0
     BIST_CTRL after  = 0x1
    Running BIST for 10 seconds...
    ... 5 of 10
      BIST is not enabled on ser 0x42 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x11 0x45 0 0
        des = 0x1 0 0x43 0xc 0x6400 0 0 0 0x2 0x1
    ... 10 of 10
      BIST is not enabled on ser 0x42 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x11 0x45 0 0
        des = 0x1 0 0x43 0x4 0x6400 0 0 0 0 0
    Disabling BIST mode...
     BIST_CTRL before = 0x1
     BIST_CTRL after  = 0
    BIST was not enabled on ser 0x42!
    BIST failed to run!
    
    Running BIST for [0x30-2 <-> 0x41]...
    Clearing error counts prior to BIST...
    Enabling BIST mode and verifying lock after...
     BIST_CTRL before = 0
     BIST_CTRL after  = 0x1
    Running BIST for 10 seconds...
    ... 5 of 10
      BIST is not enabled on ser 0x41 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x12 0x45 0 0
        des = 0x1 0 0x83 0x4 0x6400 0 0 0 0 0
    ... 10 of 10
      BIST is not enabled on ser 0x41 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x12 0x45 0 0
        des = 0x1 0 0x83 0x4 0x6400 0 0 0 0 0
    Disabling BIST mode...
     BIST_CTRL before = 0x1
     BIST_CTRL after  = 0
    BIST was not enabled on ser 0x41!
    BIST failed to run!
    
    Running BIST for [0x30-3 <-> 0x40]...
    Clearing error counts prior to BIST...
    Enabling BIST mode and verifying lock after...
     BIST_CTRL before = 0
     BIST_CTRL after  = 0x1
    Running BIST for 10 seconds...
    ... 5 of 10
      BIST is not enabled on ser 0x40 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x13 0x45 0 0
        des = 0x1 0 0xc3 0xc 0x6400 0 0 0 0x2 0x1
    ... 10 of 10
      BIST is not enabled on ser 0x40 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x13 0x45 0 0
        des = 0x1 0 0xc3 0x4 0x6400 0 0 0 0 0
    Disabling BIST mode...
     BIST_CTRL before = 0x1
     BIST_CTRL after  = 0
    BIST was not enabled on ser 0x40!
    BIST failed to run!
    
    Running BIST for [0x3d-0 <-> 0x47]...
    Clearing error counts prior to BIST...
    Enabling BIST mode and verifying lock after...
     BIST_CTRL before = 0
     BIST_CTRL after  = 0x1
    Running BIST for 10 seconds...
    ... 5 of 10
      BIST is not enabled on ser 0x47 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x10 0x45 0 0x4
        des = 0x1 0 0x3 0xc 0x6400 0 0x3 0 0x2 0x2
    ... 10 of 10
      BIST is not enabled on ser 0x47 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x10 0x45 0 0
        des = 0x1 0 0x3 0x4 0x6400 0 0x3 0 0 0
    Disabling BIST mode...
     BIST_CTRL before = 0x1
     BIST_CTRL after  = 0
    BIST was not enabled on ser 0x47!
    BIST failed to run!
    
    Running BIST for [0x3d-1 <-> 0x46]...
    Clearing error counts prior to BIST...
    Enabling BIST mode and verifying lock after...
     BIST_CTRL before = 0
     BIST_CTRL after  = 0x1
    Running BIST for 10 seconds...
    ... 5 of 10
      BIST is not enabled on ser 0x46 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x11 0x45 0 0
        des = 0x1 0 0x43 0x4 0x6400 0 0x7 0 0 0
    ... 10 of 10
      BIST is not enabled on ser 0x46 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x11 0x45 0 0
        des = 0x1 0 0x43 0x4 0x6400 0 0x7 0 0 0
    Disabling BIST mode...
     BIST_CTRL before = 0x1
     BIST_CTRL after  = 0
    BIST was not enabled on ser 0x46!
    BIST failed to run!
    
    Running BIST for [0x3d-2 <-> 0x45]...
    Clearing error counts prior to BIST...
    Enabling BIST mode and verifying lock after...
     BIST_CTRL before = 0
     BIST_CTRL after  = 0x1
    Running BIST for 10 seconds...
    ... 5 of 10
      BIST is not enabled on ser 0x45 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x12 0x45 0 0
        des = 0x1 0 0x83 0xc 0x6400 0 0x1 0 0x2 0x2
    ... 10 of 10
      BIST is not enabled on ser 0x45 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x12 0x45 0 0
        des = 0x1 0 0x83 0x4 0x6400 0 0x1 0 0 0
    Disabling BIST mode...
     BIST_CTRL before = 0x1
     BIST_CTRL after  = 0
    BIST was not enabled on ser 0x45!
    BIST failed to run!
    
    Running BIST for [0x3d-3 <-> 0x44]...
    Clearing error counts prior to BIST...
    Enabling BIST mode and verifying lock after...
     BIST_CTRL before = 0
     BIST_CTRL after  = 0x1
    Running BIST for 10 seconds...
    ... 5 of 10
      BIST is not enabled on ser 0x44 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x13 0x45 0 0
        des = 0x1 0 0xc3 0xc 0x6400 0 0 0 0x2 0x1
    ... 10 of 10
      BIST is not enabled on ser 0x44 (0)!
        ser = 0x48 0x1e 0 0 0x9 0x13 0x45 0 0
        des = 0x1 0 0xc3 0x4 0x6400 0 0 0 0 0
    Disabling BIST mode...
     BIST_CTRL before = 0x1
     BIST_CTRL after  = 0
    BIST was not enabled on ser 0x44!
    BIST failed to run!
    
    Resetting serializers and deserializers...
    Reset complete.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Kevin:

    在960的 BIST 操作期间、您能给我一个寄存器转储吗?

    谢谢、

    约书亚

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 60 00 1e 40 d0 01 00 fe 1c 10 7a 7a 0f 00 ff ff    `.?@??.???zz?...
    10: 00 00 00 00 00 00 00 00 80 61 a8 e3 dd 00 04 04    ........?a???.??
    20: 00 03 00 0f 00 00 00 00 00 00 00 00 00 00 00 00    .?.?............
    30: 00 00 01 43 00 00 00 00 00 00 00 00 00 00 00 00    ..?C............
    40: 00 a9 71 01 00 00 20 00 00 00 00 12 01 03 0c 64    .?q?.. ....????d
    50: 00 00 00 03 00 00 00 00 5e 00 00 30 00 30 60 00    ...?....^..0.0`.
    60: 00 00 00 00 00 86 c6 00 00 00 00 00 00 7c 8a a8    .....??......|??
    70: 2b 2c 00 00 00 00 00 c5 00 01 02 01 00 00 00 00    +,.....?.???....
    80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    a0: 00 00 00 00 00 1d 00 00 00 00 00 00 00 00 00 00    .....?..........
    b0: 1c 13 1f 01 25 00 18 00 8c 33 83 74 80 00 00 00    ????%.?.?3?t?...
    c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    d0: 00 43 94 02 60 f2 00 02 00 01 00 00 00 00 00 00    .C??`?.?.?......
    e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    f0: 5f 55 42 39 36 30 00 00 00 00 00 00 00 00 00 00    _UB960..........

         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 30 00 72 48 00 03 41 28 fe 1e 10 7f 7f 83 b4 00
    10: 00 00 00 00 00 20 18 3c 80 62 62 62 00 00 00 00
    20: 00 00 00 00 00 02 00 00 67 33 01 00 00 00 00 00    .....?..g3?.....
    30: 00 20 09 04 00 10 00 60 00 00 00 00 00 00 00 00    . ??.?.`........
    40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    50: 20 c0 45 00 00 00 00 00 07 07 07 00 00 00 00 00     ?E.....???.....
    60: 00 00 00 00 00 88 00 00 00 00 00 00 00 00 00 00    .....?..........
    70: 00 00 25 00 00 00 00 00 00 00 e4 00 00 00 00 00    ..%.......?.....
    80: 00 00 00 00 00 00 90 00 00 00 00 00 04 00 00 00    ......?.....?...
    90: 32 e3 64 01 00 00 00 00 00 00 08 00 00 00 23 0f    2?d?......?...#?
    a0: 00 0f 0f 0d 0d 10 42 10 10 10 03 01 00 00 00 00    .?????B?????....
    b0: 04 08 07 00 00 00 00 00 00 00 00 00 00 00 00 00    ???.............
    c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    f0: 5f 55 42 39 35 33 00 00 00 00 00 00 00 00 00 00    _UB953.........

    当应启用 BIST 时、这是 ub960和 ub953的 i2cdump 输出。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Kevin:

    在 BIST 模式下 、正向和反向通道不断被 BIST 相关数据覆盖、这将阻止解串器和串行器之间的通信。  

     在脚本中、请注释掉在 BIST 处于活动状态时从 UB960对 UB953进行的任何读取和写入操作。 在 BIST 激活时通过 UB960写入 UB953会将 UB960置于保持状态、直到完成电源复位。  如果您希望在 BIST 处于活动状态时读取和写入 UB953、请在本地与 UB953通信、而不是认为 UB960。

    谢谢、

    Joshua Horlander-Cruz   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    约书亚、您好!

    启用 BIST 后、我的程序不会对 ub953执行任何读取或写入操作、除非端口调试寄存器 SER_BIST_ACT 位指示串行器上没有启用 BIST。

    我还想知道您发布的脚本为什么不检查 SER_BIST_ACT 位来验证串行器是否处于 BIST 模式? 如果不进行检查、就无法知道它实际上处于 BIST 模式、除非我丢失了一些东西。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Kevin:

    当运行我发送给您的脚本时、使用 UB960和单个 UB530时、即使我切换端口并适当修改代码、SER_DES_ACT 也能像 BIST 模式一样正常工作。  

    由于我们不支持 Linux、您能否 将我发送给您的脚本转换为您可以使用的格式、然后将结果报告给我、以防  您的脚本与我发送的脚本之间存在微小差异、从而导致问题?

    我发送的脚本不检查 SER_BIST_ACT 的原因是它会强制出现 BIST 错误、如果 BIST 被正确激活、这些错误将记录在串行器上的寄存器0x54中、这基本上验证了 BIST 被启用并且运行 正常。  

    此致、

    约书亚

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    程序是翻译成我可以使用的表单的脚本。 我不知道如何更准确地翻译它。

    当 BIST 模式应该处于活动状态(ub960上的0xB3被设置为0x1)时、我尝试使用 ub960上端口调试寄存器的位0来触发反向通道错误。 错误由 ub953检测。 但是、它们在 ub953中显示为 CRC 错误(寄存器0x55和0x56)、而不是 BIST 错误(寄存器0x54)。

    对我来说、主要问题是:如果 ub960上的寄存器0xB3设置为0x1、SER_BIST_ACT 不会被置位的可能原因是什么? 数据表对此不提供任何提示。 如果有用、我可以提供更多寄存器转储。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Kevin:

    据我所知、如果 UB953和 UB960之间的通信出现问题、SER_BIST_ACT 位不会置位的唯一原因。  

    我注意到、在您的脚本中、UB960上没有写入0x5C 来设置 UB953的别名 ID、但 UB953都具有不同的地址、这些地址是否在其他地方设置?

    您能否运行下面提供的新脚本并查看您获得的输出是否与我提供的输出相匹配、下面提供的输出图像?  在这个新的脚本中、大多数检查都被删除、BIST 验证更加简化、从而使读取更容易、脚本更短。 由于我们不支持 Linux、您能否将下面附加的脚本转换为您可以使用的表单?

    提供的脚本仅使用一个连接到 UB960上 RX0的 UB953、在 UB960 EVM (J7处于打开状态)和 UB953 EVM 上具有默认设置、请确保在运行脚本时使用此硬件设置。  

    import time
    
    UB960 = 0x60
    UB953 = 0x18
    
    #Hard reset 953 and 960
    board.WriteI2C(UB953, 0x02, 0x01)
    board.WriteI2C(UB960, 0x02, 0x01)
    
    #set up port and SER alias ID
    board.WriteI2C(UB960, 0x4C, 0x01)
    board.WriteI2C(UB960, 0x58, 0x5E)
    board.WriteI2C(UB960, 0x5C, 0x18)
    
    print ("\t\tRX0")
    print ("960 Device ID (0x00):", hex(board.ReadI2C(UB960, 0x00, 1)))
    print ("953 Device ID (0x00):", hex(board.ReadI2C(UB953, 0x00, 1)))
    print ("Reciever Lock Status (0x4D), Bit [1:0] should be high:", hex(board.ReadI2C(UB960, 0x4D, 1)))
    print("------------------------------------------------------------------")
    print("Read BCC Error Status (0x79):", hex(board.ReadI2C(UB953, 0x79, 1)))
    board.WriteI2C(UB960, 0xB3, 0x01)	#Enable BIST using BIST_CTL
    print ("Read BIST CTL (0xB3) register After BIST ENABLED", hex(board.ReadI2C(UB960, 0xB3, 1)))
    time.sleep(0.25)
    print ("Read BIST Lock Status Change of 960 RIGHT AFTER BIST enabled (0x4D):", hex(board.ReadI2C(UB960, 0x4D,1)))
    
    for x in range(7):
        board.WriteI2C(UB960, 0xD0, 0x01)										#Force 1 Error, 0xD0 is PORT_DEBUG register
        time.sleep(0.1)
    print("SER_BIST_ACT (0xD0) VALUE, BIST is Enabled",hex(board.ReadI2C(UB960, 0xD0, 1)))
    board.WriteI2C(UB960, 0xB3, 0x00) #Disable BIST
    print ("Read BIST CTL (0xB3) register After BIST DISABLED", hex(board.ReadI2C(UB960, 0xB3, 1)))
    print ("BIST CRC Error count (0x54) on 953 after BIST.", hex(board.ReadI2C(UB953, 0x54, 1))) #0x54 is BIST ERR CNT
    print("SER_BIST_ACT (0xD0) VALUE, BIST disabled",hex(board.ReadI2C(UB960, 0xD0, 1)))
    print ("#################################################################")
    print ("\n\n")

     

    此致、

    Joshua Horlander-Cruz