Read back i.MX28 fuses using DevSupport.DeviceManager.HidDevice

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Read back i.MX28 fuses using DevSupport.DeviceManager.HidDevice

875 次查看
stephenhewitson
Contributor III

Hi,

I am using the DevSupport.dll (as supplied with BitInit) to burn the fuses inside an i.MX28.

To do this I do the following:

DevSupport.DeviceManager.HidDevice CurrentDevice = (DevSupport.DeviceManager.HidDevice)DeviceManager.Instance.FindDevice(typeof(DevSupport.DeviceManager.HidDeviceClass), new ushort?((ushort)5538), new ushort?());

if (0 == CurrentDevice.InitializeOtpRegs(otpInitLocation))

{

    //Successful

}

How do I read values back from specific registers similar to BitBurner?

Thanks,

Stephen

标签 (1)
0 项奖励
2 回复数

607 次查看
alejandrolozan1
NXP Employee
NXP Employee

Hi,

I have never used that dll, but I have done is to use the obds and the fuse driver.

Ther you can find API that can be executed in the imx28 to  write and read back the fuse state.

For example:

nt fuse_read(int addr)

{

    int temp;

    /* Check that HW_OCOTP_CTRL_BUSY and HW_OCOTP_CTRL_ERROR are clear */

    temp = *(u32 *) (HW_OCOTP_CTRL);

    temp &= 0x00000300;

    if (temp != 0) {

        printf("OTP is busy or there is an error, register value is: 0x%x\n", temp);

        return -1;

    }

    if (((addr >= 0x8) && (addr <= 0x0F)) || ((addr >= 0x18) && (addr <= 0x1F))) {  /* Address falls within range of shadow registers */

        /* Force re-load of shadow registers */

        *(u32 *) (HW_OCOTP_CTRL_SET) = 0x00000200;

        /* wait until busy and re-load are cleared */

        while (1) {

            temp = *(u32 *) (HW_OCOTP_CTRL);

            temp &= 0x00000120;

            if (temp == 0x00000000) {

                break;

            }

        }

        /* return the value of the register being read */

        return *(u32 *) ((addr << 0x4) + HW_OCOTP_CUST0);

    } else if (addr > 0x1F) {   /* Check to see if the address is a valid one */

        printf("invalid address! \n");

        return -1;

    } else {                    /* Otherwise, the address is a non shadow register and needs a special operation */

        /* Force open all of the fuse banks */

        *(u32 *) (HW_OCOTP_CTRL_SET) = 0x00001000;

        /* After issuing the open-all-banks, poll for BUSY  */

        while (1) {

            temp = *(u32 *) (HW_OCOTP_CTRL);

            temp &= 0x00000100;

            if (temp == 0x00000000) {

                break;

            }

        }

        /* store read value into temp variable */

        temp = *(u32 *) ((addr << 0x4) + HW_OCOTP_CUST0);

        /* now close the fuse bank to save power */

        *(u32 *) (HW_OCOTP_CTRL_CLR) = 0x00001000;

        /* return the value of the register being read */

        return temp;

    }

}

Are you developing a GUI similar to bitburner?

Best Regards,

Alejandro

0 项奖励

607 次查看
stephenhewitson
Contributor III

Alejandro,


Thanks for that information.

I am trying to create some test bed software that, among other things, sets the HW_OCOTP_CUST0 register programmatically.


I have managed to read and write to the register using:

DevSupport.Api.HidApi.PitcRead pitcRead = new DevSupport.Api.HidApi.PitcRead(0, 1, 0, 16);

iResult = CurrentDevice.SendCommand(pitcRead);

DevSupport.Api.HidApi.PitcWrite pw = new DevSupport.Api.HidApi.PitcWrite(0, 1, 0, new byte[] {0,0,0,0});

iResult = CurrentDevice.SendCommand(PitcWrite );

But this only works if BitBurner is ran first, and OtpAccessPitc.MX28.sb is loaded into the processor.

0 项奖励