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.

CC3220SF: Jump to internal flash

Part Number: CC3220SF
Other Parts Discussed in Thread: CC3200, , ENERGIA

Hello!

I develop my own secondary bootloader, and I'd like to know what preparations I should do first before I jump to another memory sector?

Now I write new application binary data to the beggining of the second bank of internal flash (0x01080000), it is written correct;

I'd like to jump there, but getting faultISR;

I do it like this:

void (*foo)(void) = (void (*)(void)) FLASH_ADDR;
foo();

But I suppose I have to call some functions disabling peripherial or smth else (I am using freertos too);

Could anyone help me with this?

Regards, Boris

  • Boris,

    That code works if FLASH_ADDR is valid instruction. I see no error when jumping to a function in flash. For a test, I set FLASH_ADDR = main() address, and it works.

    What fault you have in faultISR? Is it UNDEF, INVSTAT? Check 0xe000ed28 for fault code. Chapter 3 has good info. Search FAULTSTAT.

    Your secondary bootloader, how it write to flash? Have you used memory browser to see if the memory at FLASH_ADDR correct? I think that you did not write flash correctly, so MCU fault on bad instruction.

    -CE

  • Hello Engineer!

    Thanks for your reply!

    I have 0x00020000 in CFSR at 0xed28, that means INVSTAT, as I understand.

    I tried to jump to vector table and to the main of written application, but both attemps led to fault ISR with same INVSTAT;

    I compared once again binaries from IAR and from Internal flash, they are absolutely same;

    Also if I jump to my secondary bootloader's main, jump is successfull, but the I get faultISR with INVSTAT.

    Does it give any food for thought?

    Regards , Boris

  • I guess, there are some stack and interrupt vector manipulations needed, but actually I don't know how to do it, espeacially using SDK;

    I mean, even if I have new vector at 0x01080000, first I have to set it, right?

    Regards, Boris

  • Yes, the vector should be there.

    My jump-code looks like this now:

    uint32_t *addr = (uint32_t *) FLASH_ADDR;
    IntMasterDisable();
    void (*foo)(void) = (void (*)(void)) (addr[1]);
    __set_SP(addr[0]);
    IntVTableBaseSet((uint32_t) addr);
    foo();

    stack top is on addr[0];

    reset handler is on addr[1];

    Still getting some fault but not in my code, but in some place of written application.

    FAULTSTAT is

    0x8200

    0x0000

    I also tried to use __arm functions, may be it is about privillege, but compiler says I can't use them for this core (???)

    So issue is still not sloved

  • Hi Boris,

    How are you compiling and linking the program you loading with your bootloader? Have you made sure to configure the linker for your program so that it restricts the memory region available to the second bank of flash? If you don't do so, then the linker will use the full internal flash space when placing objects, which would result in invalid references when you load the code into a memory region it doesn't expect to be in.

    There is an example of an application bootloader in the CC3200 SDK. There is the bootmgr example, as well as a easier to understand dynamic_lib_loader example. If you look at the dynamic_lib_loader example, you'll see how it performs much of the functionality that you are looking to do, except that it is loading code to another section of RAM instead of to flash. Copying the principles of that but then performing writes to flash instead of a simple file read to RAM should be a good starting point for your bootloader.

    Regards,

    Michael

  • Hi Boris,

    You can also check code of this simple bootlaoder for Energia at CC3220SF. It loads content of file into RAM and jumps there for execution.

    Jan

  • Hello Jan!

    Thank you very much, this assembly insertion helped me.

    But only if I do jump before I start Freertos

    /* Start the FreeRTOS scheduler */
    vTaskStartScheduler();

    If I try to jump from thread, it fails.

    What additional steps should be done to jump from RTOS-thread safe?

    Regards, Boris

  • Hi Boris,

    Sorry, I have no experience with such use-case. Do you have disabled interrupts before you jumping to enter point?

    Jan

  • Hi Boris,

    Thanks for testing and providing the new info about the scheduler.

    If the jump succeeding before vTaskStartScheduler(); but fails after the scheduler is started, it would seem like having the scheduler running while you are jumping to and executing your loaded code is something that your code should avoid. Of course, in a freeRTOS-based application, having the scheduler run is required for the SimpleLink NWP host driver to run correctly, so that it can process the async events. Without starting the scheduler, it would not be possible for the sl_Fs* filesystem functions to work, so you can't load your code.

    It seems like this FreeRTOS scheduler + bootloader jumping issue is one well-discussed in the FreeRTOS forum:

    https://www.freertos.org/FreeRTOS_Support_Forum_Archive/December_2015/freertos_Best_way_to_stop_the_scheduler_when_leaving_bootloader_to_go_to_main_application_5db393e3j.html

    There are some good tips there that you can try using, such as halting the scheduler before jumping, or disabling the RTOS tick interrupt.

    Other than that, you could also write a no-RTOS bootloader, which would be able to avoid any FreeRTOS-related issues. Once your no-RTOS bootloader loads your program, then you can jump to the main() of your FreeRTOS program where it will run and setup its environment and scheduler as normal.

    As the sort of fixes and workarounds that you will need to avoid this issue are specific to FreeRTOS, I am not able to offer further advise as to how to implement your bootloader. Only TIRTOS is directly supported by this forum. 

    Let me know if you need more clarification on the points I have brought up in my post, or if you have questions on the CC3220 specifics such as how to read/write to the internal flash.

    Regards,

    Michael

  • At the moment my func is

    void jump_to_application(void)
    {
    typedef void (*p_function)(void);
    
    uint32_t jump_address = *(volatile uint32_t*)(FLASH_ADDR + 4);
    
    p_function p_jump_function = (p_function) jump_address;
    
    /* Stop interrupts */
    IntMasterDisable();
    
    IntMasterDisable();
    
    /* Disable all interrupts (NVIC_ISER) */
    for (int i = 0; i < 8; i++)
    {
    static uint32_t register_address;
    register_address = 0xE000E180u + i * 4;
    *(volatile uint32_t *)(register_address) = 0xFFFFFFFFu;
    }
    
    /* Clear pending bits (NVIC_ICER) */
    for (int i = 0; i < 8; i++)
    {
    static uint32_t register_address;
    register_address = 0xE000E280u + i * 4;
    *(volatile uint32_t *)(register_address) = 0xFFFFFFFFu;
    }
    
    /* Enable interrupts */
    IntMasterEnable();
    
    /* Set control */
    __set_CONTROL(0);
    
    /* Set stack */
    __set_MSP(*(volatile uint32_t*) FLASH_ADDR);
    
    /* Perform actual jump */
    p_jump_function();
    }

    It is based on https://sourceforge.net/p/freertos/discussion/382005/thread/baebd509/?limit=25

    Works well from main, but still fails from thread

    Regards, Boris

  • Hello Michael!

    Is it possible to use sl_Fs without RTOS?

    It seems like sl_task should be created to use this functionality, is there some way to avoid RTOS?

    Regards, Boris

  • Well, in my case the reason was not-stopping Systick.

    Now my code works and I close this thread.

    void jump_to_application(void)
    {
        typedef void (*p_function)(void);
      
        uint32_t jump_address = *(volatile uint32_t*)(FLASH_ADDR + 4);
      
        p_function p_jump_function = (p_function) jump_address;
    
        /* Stop interrupts */
        IntMasterDisable();
        
        /* Disable Systick */
        *(volatile uint32_t*) (0xE000E010) = 0;
        
        /* Disable all interrupts (NVIC_ISER) */
        for (int i = 0; i < 8; i++)
        {
          static uint32_t register_address;
          register_address = 0xE000E180u + i * 4;
          *(volatile uint32_t *)(register_address) = 0xFFFFFFFFu;
        }
        
        /* Clear pending bits (NVIC_ICER) */
        for (int i = 0; i < 8; i++)
        {
          static uint32_t register_address;
          register_address = 0xE000E280u + i * 4;
          *(volatile uint32_t *)(register_address) = 0xFFFFFFFFu;
        }
    
        /* Enable interrupts */
        IntMasterEnable();
        
        /* Set control */
        __set_CONTROL(0);
    
        /* Set stack */
        __set_MSP(*(volatile uint32_t*) FLASH_ADDR);
    
        /* Perform actual jump */
        p_jump_function();
    }

    Regards, Boris