Post Go back to editing

Bootloader problem with SPI flash on BF592

Category: Software
Product Number: BF592

We use for many years in one of our products a two-stage bootloader with success. One application is linked together with the primary bootloader (with elfloader -init option), while another one is burned into the flash at 0x10000. If a pushbutton is pressed at power on then the first application will be loaded, if it is not pressed then the second one. This is how it works:

 

  BYTEu c;

  *pPORTF_MUX = 0x0;

  *pPORTG_MUX = 0x0;

  *pPORTF_FER = 0x1de2;

  *pPORTG_FER = 0x700;

  *pPORTFIO_DIR = 0x2208;

  *pPORTGIO_DIR = 0x78ff;

  *pPORTFIO_INEN = 0xc011;

  *pPORTGIO_INEN = 0x8000;

  *pPORTFIO = 0xffff;                    // init output bits

  *pPORTGIO = 0xffff - (OUTPUT_BITS);    // init output bits

  c = 1;

  if ((*pPORTFIO BITAND PUSHBUTTON_MASK) == PUSHBUTTON_MASK) // switch not pressed?

    {

    MIDLED_ON;

    sysreg_write(reg_B0, ((int) c) << 16);

    asm("P0=0x0f84; P0.H=0xffb0; R0=B0; [P0]=R0; SSYNC;"); // load app from c*0x10000

    }

  else

    {

    NOP;

    LOWLED_ON;

    }

 

Now for a new product we have to extend this so, that several apps are located at 0x10000 bytes apart, and the value of a byte in the flash decides which of them should be loaded if the button is not pressed.

 

  . . . . port initializations like before

  *pSPI1_BAUD = 10;                   // Set SPI bit rate

  *pSPI1_CTL  =0x5001;                // Setup SPI in main mode, 8 bits

  *pPORTFIO = 0xffff;                 // init output bits

  *pPORTGIO = 0xffff - (OUTPUT_BITS); // init output bits

#define source 0x30001

  // ***** c = PEEK(source)   (unsigned byte) *****************

  SFLASHCS_OFF;                       // flash chip select activated

  *pSPI1_TDBR = DF3_3READ;

  while ((*pSPI1_STAT BITAND 1)==0);

  c = *pSPI1_RDBR;

  *pSPI1_TDBR = (source>>16) BITAND 0xff;

  while ((*pSPI1_STAT BITAND 1)==0);

  c = *pSPI1_RDBR;

  *pSPI1_TDBR = (source>>8) BITAND 0xff;

  while ((*pSPI1_STAT BITAND 1)==0);

  c = *pSPI1_RDBR;

  *pSPI1_TDBR = source BITAND 0xff;

  while ((*pSPI1_STAT BITAND 1)==0);

  c = *pSPI1_RDBR;

  *pSPI1_TDBR = 0;

  while ((*pSPI1_STAT BITAND 1)==0);

  c = *pSPI1_RDBR;

  while ((*pSPI1_STAT BITAND 1)==0);

  SFLASHCS_ON;                        // flash chip select off

  // ******** end of PEEK ***************************     

  if ((*pPORTFIO) BITAND PUSHBUTTON_MASK) == PUSHBUTTON_MASK) // switch not pressed?

    {

    MIDLED_ON;

    sysreg_write(reg_B0, ((int) c) << 16);

    asm("P0=0x0f84; P0.H=0xffb0; R0=B0; [P0]=R0; SSYNC;"); // load app from c*0x10000

    }

  else

    {

    NOP;

    LOWLED_ON;

    }

 

This program is definitely good, I can see on oscilloscope that the byte from the flash is read correctly, but it does not work at all, neither of the two apps will be loaded. After successfully reading the flash the control is lost and the program hangs. What is wrong?

 

One remark: It can be strange that I write to the RAM location 0xffb00f84 the flash address of the app to be loaded from the flash. Normally this supposed to be written to the address where P5 points to in the RAM. However, I found that the content of P5 is always 0xffb00f84, and if the bootloader program is moderately complex then the compiler saves P5 to the stack and starts to use it, so the primary bootloader cannot read the address from P5 any more.

  • Hi,

    1.Are you using ADSP-BF592 processor for both old and new products. If so, what is the difference between the two products.
    2.Can you please explain more about "Now for a new product we have to extend this so, that several apps are located at 0x10000 bytes apart, and the value of a byte in the flash decides which of them should be loaded if the button is not pressed."
    3.Please try to connect the processor in DND (Do Not Disturb) mode and check. This would help to isolate whether the issue is with booting or the application. Please refer the below FAQ for connecting the processor in DND mode.
    https://ez.analog.com/dsp/software-and-development-tools/visualdsp/w/documents/9552/faq-how-to-debug-a-target-board-which-boots-from-flash
    4.Can you please verify the Clock and Reset Timing(Page No: 22/44) and Power-Up Sequencing timing (Page No: 23/44) diagram which is mentioned in the ADSP-BF592 datasheet.

    Regards,
    Divya.P

  • Hi Divya,

    thanks for the very useful help!

    1. Actually, the hardware of the two products is identical, both BF592, we just make a new product software where the user should be able to boot one of 4 or 5 different application images. This is necessary, because our original program grew out of the available 32k program memory. Actually, I used an almost identical routine 12 years ago in a BF532 application, ands it worked there correctly. Although I seem to remember (I am not sure) that I had to use the elfloader of VDSP 5.0, it did not work with the newer elfloader of 5.1. I do not have 5.0 any more, although I think the BF592 was not yet supported then anyway.

    2. Different program images will be located at 0x40000, 0x50000, 0x60000 and 0x70000. In all of these programs a tiny editor can set the content of a magic flash location to 4,5,6, or 7. When booting, if the button is not pressed then this location selects which of the images will be loaded. If the button is pressed, then the program that was linked together with the init bootloader will be activated, (of course, they are located at address 0 in the flash). This program will start a software update through MIDI (a serial interface for musical instruments).

    3. This was my greatest concern that I cannot debug what is going on, because starting VDSP resets the processor. The method described in the link will solve this. I will test this as soon as I can and let you know then result.

    4. I am confident that the processor works basically correctly, because I see on oscilloscope that reading one byte of the flash is performed. Also, I see that the flash content is exactly what I expected.

    Regards

    Andras

  • Hi Andras,

    Thank you for sharing more details.

    Please find the simple test for ADSP-BF592 second stage loader. This code shows the behavior of bfrom_SpiBoot function. The application code resides at the 0x10000 location of SPI flash and can be booted via runtime API using the below function. You can modify the start address in the bfrom_SpiBoot function as per your requirement.
    bfrom_SpiBoot((void*)(0x10000),0,0,NULL)

    Can you please confirm whether the applications are working properly during emulation period instead of booting. You mentioned "Different program images will be located at 0x40000, 0x50000, 0x60000 and 0x70000", please ensure that the boot loaders sizes do not exceed the size of the sectors. If so, it may corrupt the loader fileBF592_SSL.zip.

    Regards,
    Divya.P

  • Hi Divya,

     

    It took me very much time to solve this problem, but finally I got it. Debugging in DND mode helped me a lot to follow more exactly what happens. I could single step the secondary bootloader that is executed in the ROM of the BF592, but I could not see the instructions in the debugger, it displays *illegal opcode*. Anyway, I figured out by intuition that the secondary bootloader goes wrong because I read the SPI flash in my primary bootloader. By trial and error I found that resetting the SPI port after reading the flash solves the problem, and everything works fine now:

     

    outph(SPI1_CTL,0);   // Reset SPI !!!!          

     

    Regards

     

    Andras