zeldin / fx3lafw

Blob-free logic analyzer firmware for FX3
75 stars 7 forks source link

How to load the firmware #4

Open danielkucera opened 9 months ago

danielkucera commented 9 months ago

Hello,

how do I load the firmware? These are my built files:

-rw-rw-r--   1 danman danman 108K jan 28 18:11 fx3lafw-cypress-fx3.fw
-rwxrwxr-x   1 danman danman 356K jan 28 18:11 fx3lafw.elf
-rw-rw-r--   1 danman danman  89K jan 28 18:11 fx3lafw.map

I tried flashing fx3lafw-cypress-fx3.fw directly to SPI flash but it doesn't boot.

zeldin commented 9 months ago

The firmware is designed to be uploaded into RAM. If you use my libsigrok branch then sigrok will automatically upload the fw file when it detects a FX3 SuperSpeed Explorer board. Note that due to the device switching from a USB2 to a USB3 bus after fw upload, sigrok will fail to detect the device coming back. Just start sigrok again and it should detect the already programmed device.

zeldin commented 9 months ago

You can also use fx3load to load the fw into RAM manually if you like.

danielkucera commented 9 months ago

Is there a way to store it permanently in SPI flash?

danielkucera commented 9 months ago

I've rebased your branch on latest master and disabled the firmware upload because it was not trivial to rebase the changes: https://github.com/sigrokproject/libsigrok/compare/master...danielkucera:libsigrok:fx3

danielkucera commented 9 months ago

The firmware works when loaded by fx3load but doesn't enumerate when I flash the same file to 0x0 of SPI flash. Do you have an idea what could be wrong?

zeldin commented 9 months ago

Nope, sorry. I never tried to flash anything on the SuperSpeed Explorer. Probably it needs to be in some other format? Or if the flash is XIP the code may need to be relocated to a different address, or prefixed with a loader binary...

danielkucera commented 9 months ago

At the end, the format was right but the firmware was stuck on this loop: https://github.com/zeldin/fx3lafw/blob/master/bsp/usb.c#L564 After changing while to if, it started to work.

zeldin commented 9 months ago

Interresting. I guess you need to do things a little differently when not renumerating. Changing the while to an if is equivalent to removing the code altogether (since executing the empty statement or not will not make any difference), so that is hardly the correct fix...

danielkucera commented 9 months ago

I was trying to understand the meaning of FX3_UIB_POWER_ACTIVE bit but haven't found much. I searched github but found only: CY_U3P_UIB_POWER_ADDRESS used in CyU3PDmaSocketIsValid used in CyU3PDmaChannelGetHandle with almost no usages.

Do you have some reference where this is used?

zeldin commented 9 months ago

The register is documented on page 385 of the TRM as a mechanism for performing a reset on the UIB block, and checking when its initialization is done. I don't remember any more details than this (it's been almost 6 years...).

Since the reset operation works when booting from RAM but not from SPI, my guess would be that it is depending on some part of the chip being powered or initialized which isn't when booting from SPI, but which is (implicitly) when booting from RAM because the bootloader has already been using USB. In which case powering/initializing that part before doing the UIB reset should fix the issue.

danielkucera commented 9 months ago

Now I noticed that the bit is acctually not writable (from software), check this table: image If you check the register definition, there is only R: image When comparing to UIBIN_POWER, it has R/W there: image Or I2S_POWER: image

So it is probably not possible to reset it from software. What do you think?

zeldin commented 9 months ago

Weird. It also says that the ACTIVE bit is read-only for the HW, which makes absolutely no sense given the description. Given that the actual description of the bits is identical to that of the other IP blocks, and that the section before the bit descriptions state that "Every IP block" should implement these same functions, I'd be inclined to believe that the differing direction indication here is just a misprint. Unfortunately there are several of those in the TRM... :confused:

danielkucera commented 9 months ago

Could you please test if setting/resetting the bit has any effect on the ACTIVE bit?

zeldin commented 9 months ago

Well, you'll probably get the results quicker if you do it yourself. :smile:

danielkucera commented 9 months ago

interesting, the same code:

  char buf[64];
  snprintf(buf, sizeof(buf), "power val %lx\n", Fx3ReadReg32(FX3_UIB_POWER));
  Fx3UartTxString(buf);
  Fx3SetReg32(FX3_UIB_POWER, FX3_UIB_POWER_RESETN);
  Fx3UtilDelayUs(100);
  snprintf(buf, sizeof(buf), "power val %lx\n", Fx3ReadReg32(FX3_UIB_POWER));
  Fx3UartTxString(buf);
  Fx3ClearReg32(FX3_UIB_POWER, FX3_UIB_POWER_RESETN);
  Fx3UtilDelayUs(50);
  snprintf(buf, sizeof(buf), "power val %lx\n", Fx3ReadReg32(FX3_UIB_POWER));
  Fx3UartTxString(buf);
  Fx3SetReg32(FX3_UIB_POWER, FX3_UIB_POWER_RESETN);
  Fx3UtilDelayUs(100);
  snprintf(buf, sizeof(buf), "power val %lx\n", Fx3ReadReg32(FX3_UIB_POWER));
  Fx3UartTxString(buf);

behaves diferrently when run in boot from usb:

power val 80000001
power val 80000001
power val 0
power val 80000001

and when from SPI boot:

power val 0
power val 80000000
power val 0
power val 80000000
danielkucera commented 9 months ago

It is super-weird. Even if I put the value printing inside of main loop, it is still 80000000, even during normal operation of the device.

req: c0 b2 value: 0000 index: 0000 length: 0001
CMD_GET_REVID_VERSION
Fx3UsbUsbCoreIsr
  PROT
    STATUS_STAGE
power val 80000000
power val 80000000
power val 80000000
power val 80000000
power val 80000000
power val 80000000
Fx3UsbUsbCoreIsr
  PROT
    SUTOK_EV
req: 40 b1 value: 0000 index: 0000 length: 0003
CMD_START
flags=80, sample_delay_h=00, sample_delay_l=02
Fx3UsbUsbCoreIsr
  PROT
    STATUS_STAGE

But when booted via USB:

req: c0 b2 value: 0000 index: 0000 length: 0001
CMD_GET_REVID_VERSION
Fx3UsbUsbCoreIsr
  PROT
    STATUS_STAGE
power val 80000001
power val 80000001
power val 80000001
power val 80000001
power val 80000001
power val 80000001
power val 80000001
power val 80000001
power val 80000001
power val 80000001
Fx3UsbUsbCoreIsr
  PROT
    SUTOK_EV
req: 40 b1 value: 0000 index: 0000 length: 0003
CMD_START
flags=80, sample_delay_h=00, sample_delay_l=03
Fx3UsbUsbCoreIsr
  PROT
    STATUS_STAGE

this looks like a silicon bug to me but :shrug:

Would you be okay with removing the check inside while?

zeldin commented 9 months ago

So basically when running from RAM then the block is initially out of reset and active, which makes sense. Forcing it into reset makes it not active, and then when you let it out of reset it's active again. So far everything seems sane.

Now when you're running from SPI the block starts out in reset and not active. This also seems reasonable. The only weird thing is that when you release the reset, it does not become active. Then when you make a new reset again it does not become active. So this still feels like there is something that needs to be initialized first, which is implicitly done during USB boot but not SPI boot.

A relevant question is of course what the exact consequences of UIB not becoming "active" is, considering that you suggest that everything works seemingly correct even without it... Did you try USB2 (High Speed) mode as well? (IIRC "SUTOK_EV" means you are in the SuperSpeed path.)

danielkucera commented 9 months ago

Let me correct myself - when I don't deassert reset after SPI boot, it doesn't work (boot). After USB boot it works because it is runinng already. The register behaves the same in USB-HS. Additionaly, I found out it doesn't work (pulse view doesn't capture any samples) in USB-HS in any configuration.

danielkucera commented 9 months ago

you were right: https://community.infineon.com/t5/USB-superspeed-peripherals/FX3-UIB-power-register/m-p/688372#M36240