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.

Calling the bootloader I2C update handler from TI-RTOS application

My config: using TM4C123BH, IAR v6.70, TI-RTOS 2.0.0.22, TivaWare 2.1.0.12573c

I'm using a custom bootloader based on TivaWare in my FLASH area 0x0000000-0x00001FFF. The application starts at 0x00002000. The boot up is working fine, the bootloader detects a valid application and starts the application with TI-RTOS. TI-RTOS also is working fine (I'm using GPIO, ADC, I2C Master, I2C Slave, Timers, Hwi and Swi, Semaphores, Events, Gates, 6 different Tasks). For firmware update I need to call the bootloader from my application. The command for firmware update is received by the I2C slave interface. I jump to the bootloader using the following code:

        // We must make sure we turn off SysTick and its interrupt before entering
        // the boot loader!
        ROM_SysTickIntDisable();
        ROM_SysTickDisable();

        // Disable all processor interrupts.  Instead of disabling them
        // one at a time, a direct write to NVIC is done to disable all
        // peripheral interrupts.
        HWREG(NVIC_DIS0) = 0xffffffff;
        HWREG(NVIC_DIS1) = 0xffffffff;

        // Load the stack pointer from the bootloader's vector
        __set_MSP( *((volatile uint32_t*)0x00 ));

        // Return control to the boot loader.  This is a call to the
        // SVC UpdateHandler in the boot loader and should never return.
        // If it does, very bad things will likely happen.
        (*((void (*)(void))(*(uint32_t *)0x2c)))();

The bootloader call also works, it is displayed by a GPIO (LED). But the update handler using the I2C slave interface stucks. The I2C address byte is acknowledged, but further data will not acknowledged any I get a timeout.

If I start the bootloader update handler without TI-RTOS application, everything is working fine. So I guess, something must be disabled in the application before the bootloader is called. Any ideas?

  • A couple questions and suggestions:

    1. Do you have access to the source code for the bootloader? Can you review it to see what assumptions it makes about the environment it runs in?

    2. Calling the bootloader will run on the current stack. Is this stack in an area not used by the bootloader?

    3. Per #1, does the bootloader assume interrupts are enabled? Does it re-enable interrupts?

    4. Does the bootloader completely initialize the I2C peripheral? This might be an issue since you are using the TI-RTOS drivers which may have set the I2C peripheral up in a different way. The bootloader might assume the peripherals are in their POR values.

    5. Does the bootloader use any C runtime functions?

    Mark

  • Hi Mark,

    thank you for your reply.

    1. Do you have access to the source code for the bootloader? Can you review it to see what assumptions it makes about the environment it runs in?

    Yes. I’m using the bootloader which comes with the TivaWare and added some code to MyInitFunc(). In this function only ADC and GPIO’s are used.

    2. Calling the bootloader will run on the current stack. Is this stack in an area not used by the bootloader?

    No, immediately before the jump to the bootloader is called, the stack is changed to the bootloader stack:

    __set_MSP( *((volatile uint32_t*)0x00 ));

    This intrinsic function loads the Main Stack Pointer from Address 0x00. The following line calls the UpdateHandler() via the bootloader vector 0x2c.

    (*((void (*)(void))(*(uint32_t *)0x2c)))();

    3. Per #1, does the bootloader assume interrupts are enabled? Does it re-enable interrupts?

    The bootloader doesn’t use interrupts as I know. I disabled the interrupts to avoid any unpredictable situation after exit from TI-RTOS.

    4. Does the bootloader completely initialize the I2C peripheral? This might be an issue since you are using the TI-RTOS drivers which may have set the I2C peripheral up in a different way. The bootloader might assume the peripherals are in their POR values.

    I’ve changed the initialization of the I2C peripheral to get it running. If I start the bootloader direct from Reset, the I2C communication is working fine. Here my I2C initialization in the bootloader:

        //
        // Enable the clocks to the I2C and GPIO modules.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
     
        //
        // Configure the GPIO pins for hardware control, open drain with pull-up,
        // and enable them.
        //
        ROM_GPIOPinConfigure(GPIO_PB2_I2C0SCL);
        ROM_GPIOPinConfigure(GPIO_PB3_I2C0SDA);
        ROM_GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
        ROM_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
        ROM_GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_STRENGTH_8MA_SC, GPIO_DIR_MODE_HW | GPIO_PIN_TYPE_OD);
     
        //
        // Enable the I2C Slave Mode.
        //
        HWREG(I2C0_BASE + I2C_O_MCR) |= I2C_MCR_SFE;
     
        //
        // Setup the I2C Slave Address.
        //
        HWREG(I2C0_BASE + I2C_O_SOAR) = I2C_SLAVE_ADDR;
     
        //
        // Enable the I2C Slave Device on the I2C bus.
        //
        HWREG(I2C0_BASE + I2C_O_SCSR) = I2C_SCSR_DA;

     

    TI-RTOS doesn’t support I2C slave mode. So I have used nearly the same I2C initialization in TI-RTOS:

        // The I2C0 peripheral must be enabled before use.
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
     
        // Configure the pin muxing for I2C0 functions on port B2 and B3.
        GPIOPinConfigure(GPIO_PB2_I2C0SCL);
        GPIOPinConfigure(GPIO_PB3_I2C0SDA);
     
        // Select the I2C function for these pins.  This function will also
        // configure the GPIO pins pins for I2C operation, setting them to
        // open-drain operation with weak pull-ups.
        GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
        GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
        GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_STRENGTH_8MA_SC, GPIO_DIR_MODE_HW | GPIO_PIN_TYPE_OD);
     
        // Configure and turn on the I2C0 slave interrupt.  The I2CSlaveIntEnableEx()
        // gives you the ability to only enable specific interrupts. For this case
        // we are only interrupting when the slave device receives data.
        I2CSlaveIntEnableEx(I2C0_BASE, I2C_SLAVE_INT_DATA);
     
        // Enable the I2C0 slave module.
        I2CSlaveEnable(I2C0_BASE);
     
        // Set the slave address to SLAVE_ADDRESS.
        I2CSlaveInit(I2C0_BASE, SLAVE_ADDRESS);
     
        // Create a Swi with default priority (15)
        swiI2C0SlaveInt = Swi_create(I2C0SlaveIntHandler, NULL, &eb);
        if (swiI2C0SlaveInt == NULL) {
            System_printf("Swi create failed");
        }
     
        // Register interrupt handler for I2C0 interrupt
        Hwi_Params_init(&hwiParams);
        hwiParams.arg = 0;
        hwi0 = Hwi_create(INT_I2C0, hwiFxnI2C0SlaveIntHandler, &hwiParams, &eb);
        if (hwi0 == NULL) {
            System_printf("Hwi create failed");

     5. Does the bootloader use any C runtime functions?

    I don’t know. What do you mean?

    Juergen

  • Juergen,

    Sorry - I read this originally and thought you had solved the problem when you said

    "I’ve changed the initialization of the I2C peripheral to get it running. "

    Does this mean your problem solved, or is this just something you had already done? Let me know if you need more help - I'll probably have to find somebody more familiar with the bootloader code. Are you using the code documented in SW-TM4C-BOOTLDR-2.1.0.12753.pdf?

    Mark

  • Hi Mark,

    meanwhile I found the reason for the bootloader crash. An RTOS Timer was still running. After I've stopped this Timer, everthing was ok.

    Thanks.

    Jürgen

  • Hi Mark

    can you send me the whole source code from your project?

    I have to do something like you and have no idea how to initialize the I2C slave and process the data in the main function. I use TI-RTOS too.

    Thanks

    Manuel

  • Manuel,

    This is an old thread that has been closed. Can you please create a new thread with details about the issue? Also, please include versions of TI-RTOS and CCS that you are using.

    Thanks,
    Vikram