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

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

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

854 Views
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

Labels (1)
0 Kudos
2 Replies

586 Views
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 Kudos

586 Views
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 Kudos