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.

MSP430FR5739: Minimum startup time to execution of main()

Part Number: MSP430FR5739

What is the minimum/typical  startup up time for a msp430fr5739 to get to the first line of code in main() with the standard TI bootloader?

The typical startup time I am measuring is ~= 6.45ms. Is there anyway to decrease it? Change to a custom bootloader?

Do to an application where this part is embedded having had a firmware update, I now have an situation where the part must be ready by 2.5 ms instead of 10ms.

I have 150,000 parts in stock which will be affected and rendered unusable unless a solution is found.

Help!

  • The time is impacted by your hardware design and software choices.

    Without knowing your desig , it is unknowable to us.
  • Internal oscillator. 3.3v. This MUST be a quantifiable and tested parameter. What software choices? I am using IAR workbench, although it should not make any difference. I am asking about time from power on until the first instruction of user code is executed. Does 6.45 ms sound like its typical or should I expect any quicker? Are there any delays in the standard bootloader code?
  • As I indicated earlier start-up is determined by many factors, none of which is specified here. I think you can do yourself a huge favor by going through the datasheet of your device and sharing more with others about your design.

    In general, it will take some time for the oscillator to start working. That time is often specified but not tested. The number range from a few ms to over 100ms, depending on vendor and oscillator speed and times - it can take over 500ms for a low frequency oscillator to get it going.

    With that said, TI prides itself on its "instant on" oscillator so your start up time should be shorter, everything else being equal - which unfortunately is never true.

    Again the start up time for your specific design is unknowable to anything but yourself, based on the limuted information you have provided.

    Hope it helps. And yes, 6ms is pretty fast for a typical MCU. If you want faster, consider an external oscillator, especially an always on one.
  • Hi Rick,

    Thanks for your post. Actually, the start up time to get mcu to first line of code in main includes two parts, power cycle time and boot code running time.

    1. For power cycle time, it's related to your power supply circuit, especially dVcc/dt. If you use a too larger capacitance in power supply pin, the voltage will rise too slow, which causes power up time increase.  I check the MSP430FR5739 datasheet, the wake-up time is as below.

    Seems the MCU power supply of your design is controlled by other device. A solution to reduce power up time is keep MCU stay at power on state, but wake up it from reset or LPM4 state by GPIO.  

    2. For boot code running time, if you don't  enable mpu and don't have global static variable to initialize, the boot code is just implement stack init and jump to main(). The total CPU cycle is 37, about 37 us at 1MHz default power up main frequency. 

    But it still can be decreased by custom boot code. If you didn't have global static variable to init, the C language boot code can be replaced by assembly boot code as below.

    Best Regards,

    If my post helped solve your issue, please click on the  VERIFY ANSWER    button. 

    Winter,

    Search E2E! Your questions may already be answered! 

  • Thank you for your reply. It seems Winter's reply is on track.

  • Thanks for your reply. It seems tWakeup BOR or power up is relevant. If this is the case it would seem that the boot code is consuming the majority of the measured 6.45 ms. Measured on several parts and seems consistent.

    You are correct, this device is embedded as an I2C slave in another device which controls power so the power supply characteristics are out of my control, DV/DT is what it is.

    Where is the boot code located so I can dump it and disassemble it, unless there is published source or binary available?

    As for my code here are the relevant parts -

    Here is my main():

    void main(void)
    {
    // The SFRRPCR register has the SYSRSTRE - reset resister enable set at power up
    // SYSRSTUP - pullup selected is also set at power up
    // SYSNMI is not set.
    // All of this lets the pin be a non-floating reset input, so we don't change these

    // Startup clock system in max. DCO setting, hi-range ~=23.8mhz

    CSCTL0_H = 0xA5; // Unlock register
    CSCTL1 = DCORSEL + DCOFSEL0 + DCOFSEL1; // Set hirange and max. DCO setting
    CSCTL2 = SELA_3 + SELS_3 + SELM_3; // set ACLK = DCO; SMCLK source= DCO, MCLK = DCO
    CSCTL3 = DIVA_0 + DIVS_0 + DIVM_0; // set all dividers to /1
    CSCTL0_H = 0x01; // Lock Register

    // Turn off reference
    REFCTL0 |= REFTCOFF;
    REFCTL0 &= ~REFON;

    // Configure GPIOs
    P1OUT = 0xfb; // external asic rst low as early as possible
    P2OUT = 0xff;

    P1DIR = (BIT0 + BIT1 + BIT2 + BIT4); // outputs: debug0, debug1, asic_rst, (spi cs on 4, sck on 5, i2c sda on 6 sck on 7)
    // asic_rdy is input on bit3

    P1SEL1 |= (BIT5 + BIT6 + BIT7); // 1
    // P1SEL0 |= (BIT5 + BIT6 + BIT7); // 0 (secondary module function on 5,6 and 7

    // Configure port 2.0 and 2.1 as secondary module function (SPI), simo and somi

    P2SEL1 |= (BIT0 + BIT1); // 1
    // P2SEL0 &= ~(BIT0 + BIT1); // 0 (secondary module function on 0 and 1

    WDTCTL = WDTPW + WDTHOLD; // Stop WDT

    application(); // perform function
    }

    Here is my main application global space:

    // Bss, but not zero initialized
    __no_init uint8 Printer2ChipData[IIC_RECEIVE_BUFFER_SIZE]; //Holds message from device
    __no_init uint16 Printer2ChipCount;

    __no_init uint8 Chip2PrinterData[IIC_SEND_BUFFER_SIZE]; //Holds built message for device
    __no_init uint16 Chip2PrinterCount;

    __no_init uint8 spi_rec_buf[256]; // uP to ASIC
    __no_init uint8 asic_rev[2];
    __no_init uint16 tc; // for timing test

    __no_init uint8 SAuthData[AUTH_CHALLENGE_SIZE]; // incoming
    __no_init uint8 SAuthReply[AUTH_REPLY_SIZE]; // outgoing

    __no_init uint8 FlashInitialized; // 1 if true

    __no_init uint8 backdoor_opened; // 1 if true

    __no_init uint16 number_of_received_commands; // starts at 0 after power up

    // multiple serial number data pointers
    __no_init uint8 *cmd20dp;
    __no_init uint8 *cmd28dp;
    __no_init uint8 *chaldp;
    __no_init uint8 *rwdp;
    __no_init uint8 *rodp;

    // non-initialized persistant data (in feram)
    __persistent uint8 TableFlag; // if 0 use table 20, else use table 28 (lives at 0xed00)
    __persistent uint8 TablePointer; // table pointer (lives at 0xed01

    const uint8 ApplicationVersion[3] = {0x02, 0x00, 0x0d}; // in nv memory (lives at 0xed02-0xed04)
    // versaion c added support for old and new printer firmwares
    // old mono printer do not issue cmd20, so we marry on a write to address 0x0020
    // version d 06/21/16 changed mono printer S switch to read from 0x440

    // JTAG PASSWORD STUFF 06/16/16
    #pragma location = 0xFF80
    __root const uint16 JTAG_signatures[] = {0xAAAA, 0x0002};

    #pragma location = 0xFF84
    __root const uint16 BSL_signature1 = 0x5555; // disable BSL

    #pragma location = 0xFF86
    __root const uint16 BSL_signature2 = 0x5555; // disable BSL

    #pragma location = 0xFF88
    __root const uint8 JTAG_password[] = {0x01,0x09,0x06,0x02}; // 1962

    #pragma vector = TIMER1_A1_VECTOR
    __interrupt void T1_A1_ISR(void)
    {
    // the address of this ISR will be put at 0xFFE0 part of the BSL password 32 bytes from 0xffe0-0xffff
    }

    #pragma vector = TIMER1_A0_VECTOR
    __interrupt void T1_A0_ISR(void)
    {
    // the address of this ISR will be put at 0xFFE2 part of the BSL password 32 bytes from 0xffe0-0xffff
    }
  • I have this I2c interrupt service function set to execute from RAM for speed, I think this may be consuming a lot of time in the boot code:

    Is there another way to effect this copy AFTER I set the DCO to run at 23.8 MHZ in my main()?

    // ATTENTION: This function is in flash to be copied to RAM and executed there
    __ramfunc void service_i2c_int(void)
    {
    ...
    }

    //---------------------------------------------------------------------------------------
    // void USCIB0_ISR - what it is
    //---------------------------------------------------------------------------------------

    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCIB0_ISR(void)
    {
    service_i2c_int();
    }
  • Ok, issue resolved.

    I placed the following code in __low_level_init() to throttle up the clock to 28 MHz prior to the execution of cstart_init_copy_ramfunc ().

    Startup went from 6.45ms to 2.38ms.

    The size of the interrupt service routine was 0xd4 bytes and took 4749 cycles to execute at 1mhz (4.74 ms), it now takes 1.99ms.

    int __low_level_init(void )
    {
    // Startup clock system in max. DCO setting, hi-range ~=23.8mhz
    CSCTL0_H = 0xA5; // Unlock register
    CSCTL1 = DCORSEL + DCOFSEL0 + DCOFSEL1; // Set hirange and max. DCO setting
    CSCTL2 = SELA_3 + SELS_3 + SELM_3; // set ACLK = DCO; SMCLK source= DCO, MCLK = DCO
    CSCTL3 = DIVA_0 + DIVS_0 + DIVM_0; // set all dividers to /1
    CSCTL0_H = 0x01; // Lock Register
    return(1); // cause cstart_init_copy_ramfunc to execute
    }

**Attention** This is a public forum