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.

TMS320F28069: TMS320F28069 Going into Low Power Mode

Part Number: TMS320F28069
Other Parts Discussed in Thread: CONTROLSUITE

As the title suggests, I'm using the TMS320F28069 MCU.

A rough description of my code is as follows: when the device is powered on, it goes directly to GetMode. From there, it goes to flash. At the start of flash, a secondary bootloader (which I wrote) determines whether to load code to the other flash sectors (this secondary bootloader is kept in a sector that's never erased) or it continues with the code that's already in flash. If new code needs to be loaded, it goes to SCI boot mode. From there, a modified version of the C2000 Serial Firmware Upgrader is used to load the f28069_flash_kernel to RAM. From there, the f28069_flash_kernel loads the new code into flash. Both C2000 Serial Firmware Upgrader and f28069_flash_kernel was obtained from controlSUITE.

During testing of my secondary bootloader, I want to physical disconnect the serial cable between the computer and the MCU while the f28069_flash_kernel is trying to load to flash. This is done because my secondary bootloader must always be available upon bootup to load code to flash. Thus, there should be no way to prevent loading code to flash. My secondary bootloader is located in sector A only and the rest of the code is in the other flash sectors.

I was able to execute this test repeatedly without issue. However, in one recent test, the MCU went to low power mode. I tried to download the code using Code Composer and the JTAG port. However, when I attempt to do, it said it was in lower power mode and wouldn't allow me to re-download the code.

I tried power cycling the board, but it still went into low power mode. This indicates to me there must be something in flash that's setting it to low power mode.

Based on all this, I have the following questions:

1. When it's in low power mode, should I just force the GPIO pins to a certain state, cycle power, and then try to re-load using the JTAG? Or would it be enough to just pull the XRS pin high?

2. There's nothing in my secondary bootloader code that manipulates the low power mode registers. See my main.c below. Again, this is entirely in sector A (I checked the disassembly before this problem happened to verify that). However, as I mentioned, if it goes to low power mode even after a power cycle there must be something in flash that's setting it to one of the low power modes. How is this possible? Any advice would be greatly appreciated.

/**********************************************************************

* File: Main.c

* Devices: TMS320F2806x

**********************************************************************/

#define MAIN_C

#include "main.h" // Main include file

#include <F2806x_Device.h> // F2806x header file peripheral address definitions

#include "DynaLinkBegin.h"

#include <Flash2806x_API_Library.h>

#pragma CODE_SECTION(bootloaderStart,"bootStart")

#pragma CODE_SECTION(CsmUnlock_Bootloader,"bootStart")

#pragma CODE_SECTION(SCI_Init_Bootloader,"bootStart")

#pragma CODE_SECTION(SCI_Autobaud_Bootloader,"bootStart")

#pragma CODE_SECTION(main,"bootStart")

#pragma CODE_SECTION(sci_msg_boot,"bootStart")

#pragma CODE_SECTION(sci_xmit_boot,"bootStart")

void bootloaderStart(void);

Uint16 CsmUnlock_Bootloader(void);

void SCI_Init_Bootloader(void);

Uint16 SCI_Autobaud_Bootloader(void);

void sci_msg_boot(Uint16 p, unsigned char *msg);

void sci_xmit_boot(Uint16 p, unsigned char a);

extern void SciBoot(void);

 

//Defined in Passwords.asm

// CSM Key values

Uint16 PRG_key0;

Uint16 PRG_key1;

Uint16 PRG_key2;

Uint16 PRG_key3;

Uint16 PRG_key4;

Uint16 PRG_key5;

Uint16 PRG_key6;

Uint16 PRG_key7;

void main(void)

{

bootloaderStart();

DynalinkMain();

} //end of main()

/*------------------------------------------------------------------

CsmUnlock_Bootloader

Unlock the code security module (CSM)

Parameters:

Return Value:

STATUS_SUCCESS CSM is unlocked

STATUS_FAIL_UNLOCK CSM did not unlock

Notes:

-----------------------------------------------------------------*/

Uint16 CsmUnlock_Bootloader()

{

volatile Uint16 temp;

// Load the key registers with the current password

// These are defined in Example_Flash2806x_CsmKeys.asm

asm(" EALLOW");

CsmRegs.KEY0 = PRG_key0;

CsmRegs.KEY1 = PRG_key1;

CsmRegs.KEY2 = PRG_key2;

CsmRegs.KEY3 = PRG_key3;

CsmRegs.KEY4 = PRG_key4;

CsmRegs.KEY5 = PRG_key5;

CsmRegs.KEY6 = PRG_key6;

CsmRegs.KEY7 = PRG_key7;

asm(" EDIS");

// Perform a dummy read of the password locations

// if they match the key values, the CSM will unlock

temp = CsmPwl.PSWD0;

temp = CsmPwl.PSWD1;

temp = CsmPwl.PSWD2;

temp = CsmPwl.PSWD3;

temp = CsmPwl.PSWD4;

temp = CsmPwl.PSWD5;

temp = CsmPwl.PSWD6;

temp = CsmPwl.PSWD7;

// If the CSM unlocked, return succes, otherwise return

// failure.

if ((CsmRegs.CSMSCR.all & 0x0001) == 0)

return STATUS_SUCCESS;

else

return STATUS_FAIL_CSM_LOCKED;

}

 

/*------------------------------------------------------------------

SCI_Init_Bootloader

Initiallization for SCI.

Parameters:

Return Value:

Notes:

Custom SCI intialization that's intendend to make sure the

autobaud and caret transmission can occur. It's also needed in

order to successfully branch to the SCI boot mode in ROM.

-----------------------------------------------------------------*/

void SCI_Init_Bootloader()

{

asm(" EALLOW");

//Enable SCI-A clocks.

SysCtrlRegs.PCLKCR0.bit.SCIAENCLK=1;

SysCtrlRegs.LOSPCP.all = 0x0002;

//Reset SCI FIFO Transmit Register.

SciaRegs.SCIFFTX.all = 0x8000;

// 1 stop bit, No parity, 8-bit character

SciaRegs.SCICCR.all = 0x0007;

//Enable TX and RX.

SciaRegs.SCICTL1.all = 0x0003;

//Disable TX and RX interrupts and flags.

SciaRegs.SCICTL2.all = 0x0000;

//SCI reset while maintaining TX and RX enable.

SciaRegs.SCICTL1.all = 0x0023;

// Enable pull-ups on SCI-A pins

// GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0;

// GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0;

GpioCtrlRegs.GPAPUD.all &= 0xCFFFFFFF;

// Enable the SCI-A pins

// GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1;

// GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1;

GpioCtrlRegs.GPAMUX2.all |= 0x05000000;

// Input qual for SCI-A RX is asynch

GpioCtrlRegs.GPAQSEL2.bit.GPIO28 = 3;

 

SciaRegs.SCIHBAUD = 0x0000;

SciaRegs.SCILBAUD = 0x0000;

SciaRegs.SCIFFRX.all = 0x201F;

SciaRegs.SCIFFCT.all = 0x0000;

 

 

SysCtrlRegs.WDCR = 0x0068; // Disable watchdog.

SysCtrlRegs.CLKCTL.bit.INTOSC1OFF = 0; //Turn on Internal Oscillator 1

SysCtrlRegs.CLKCTL.bit.OSCCLKSRCSEL = 0; // Clk Src = INTOSC1

SysCtrlRegs.CLKCTL.bit.XCLKINOFF = 1; // Turn off XCLKIN

SysCtrlRegs.CLKCTL.bit.XTALOSCOFF = 1; // Turn off XTALOSC

SysCtrlRegs.CLKCTL.bit.INTOSC2OFF = 1; // Turn off INTOSC2

//Make sure PLL isn't running in Limp mode.

if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0) {

EALLOW;

// OSCCLKSRC1 failure detected. PLL running in limp mode.

// Re-enable missing clock logic.

SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1;

EDIS;

// Replace this line with a call to an appropriate

// SystemShutdown(); function.

__asm(" ESTOP0");

// Uncomment for debugging purposes

}

// DIVSEL MUST be 0 before PLLCR can be changed from

// 0x0000. It is set to 0 by an external reset XRSn

// This puts us in 1/4

SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;

// Change the PLLCR

if (SysCtrlRegs.PLLCR.bit.DIV != 18) {

// Before setting PLLCR turn off missing clock detect logic

SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;

SysCtrlRegs.PLLCR.bit.DIV = 18;

// Optional: Wait for PLL to lock.

// During this time the CPU will switch to OSCCLK/2 until

// the PLL is stable. Once the PLL is stable the CPU will

// switch to the new PLL value.

//

// This time-to-lock is monitored by a PLL lock counter.

//

// Code is not required to sit and wait for the PLL to lock.

// However, if the code does anything that is timing critical,

// and requires the correct clock be locked, then it is best to

// wait until this switching has completed.

// Wait for the PLL lock bit to be set.

while (SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1) {

// Uncomment to service the watchdog

// ServiceDog();

}

SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0;

}

SysCtrlRegs.PLLSTS.bit.DIVSEL = 2;

asm(" EDIS");

}

/*------------------------------------------------------------------

SCI_Autobaud_Bootloader

Parameters:

Return Value:

Notes:

This will determine the baudrate at which SCI transmission will

occur. This is needed because carets will transmitted prior

to going to SCI boot mode in ROM.

-----------------------------------------------------------------*/

Uint16 SCI_Autobaud_Bootloader()

{

Uint16 byteData;

Uint16 timeOut;

Uint32 j;

Uint32 timePeriodBL = 60000000;

// Must prime baud register with >= 1

SciaRegs.SCILBAUD = 1;

// Prepare for autobaud detection

// Set the CDC bit to enable autobaud detection

// and clear the ABD bit

SciaRegs.SCIFFCT.bit.CDC = 1;

SciaRegs.SCIFFCT.bit.ABDCLR = 1;

// Wait until we correctly read an

// 'A' or 'a' and lock

timeOut = 0;

while ((SciaRegs.SCIFFCT.bit.ABD != 1) && (timeOut == 0))

{

for (j=0;(j<timePeriodBL) && (SciaRegs.SCIFFCT.bit.ABD != 1);j++){};

if (j >= timePeriodBL) {timeOut = 1;}

}

// After autobaud lock, clear the ABD and CDC bits

SciaRegs.SCIFFCT.bit.ABDCLR = 1;

SciaRegs.SCIFFCT.bit.CDC = 0;

if(timeOut == 0)

{

while ((SciaRegs.SCIRXST.bit.RXRDY != 1) && (timeOut == 0))

{

for (j=0;(j<timePeriodBL) && (SciaRegs.SCIRXST.bit.RXRDY != 1);j++){};

if (j >= timePeriodBL) {timeOut = 1;}

}

if(timeOut == 0)

{

byteData = SciaRegs.SCIRXBUF.bit.RXDT;

SciaRegs.SCITXBUF = byteData;

}

}

return timeOut;

}

void bootloaderStart()

{

Uint16 Status;

Uint16 byteData;

Uint16 autoBaudStatus = 1;

Uint16 timeOut;

Uint32 j;

Uint32 timePeriodBLS = 60000000;

Status = CsmUnlock_Bootloader();

if (Status == STATUS_SUCCESS) {

//Initialization prior to SCI_Boot

SCI_Init_Bootloader();

//Perform autobaud.

autoBaudStatus = SCI_Autobaud_Bootloader();

if (autoBaudStatus == 0)

{

byteData = 0x0000;

//Wait for a caret. If it's recieved in a certain period

//of time, then go to SCI_Boot in Boot ROM.

sci_msg_boot(0, "^");

timeOut = 0;

while ((SciaRegs.SCIRXST.bit.RXRDY != 1) && (timeOut == 0))

{

for (j=0;(j<timePeriodBLS) && (SciaRegs.SCIRXST.bit.RXRDY != 1);j++)

{

sci_msg_boot(0, "^");

};

if (j >= timePeriodBLS) {timeOut = 1;}

}

if (timeOut == 0)

{

byteData = SciaRegs.SCIRXBUF.bit.RXDT;

//If a caret has been recieved, go to SCI_Boot in Boot ROM.

if (byteData == 0x005E)

{

SciBoot();

asm(" EDIS");

}

}

}

}

}

void sci_msg_boot(Uint16 p, unsigned char *msg)

{

unsigned char *ptr;

ptr = msg;

while (*ptr != '\0')

{

sci_xmit_boot(p, *ptr);

ptr++;

}

}

void sci_xmit_boot(Uint16 p, unsigned char a)

{

if (p == 0)

{

// while (SciaRegs.SCICTL2.bit.TXRDY == 0) // ready to put another character in transmit buffer

while (SciaRegs.SCICTL2.bit.TXEMPTY == 0) // ready to put another character in transmit buffer

{

// wait for previous character to finish transmitting

// change to interrupt driven, if this takes too long

}

SciaRegs.SCITXBUF = (a & 0x00FF);

}

else if (p == 1)

{

// a= 0x55;

// while (ScibRegs.SCICTL2.bit.TXRDY == 0)

while (ScibRegs.SCICTL2.bit.TXEMPTY == 0)

{

// wait for previous character to finish transmitting

}

ScibRegs.SCITXBUF = (a & 0x00FF);

}

else

{

// bad port selected

}

}

  • You should change the device's boot mode pins so that the boot loader will loop waiting for input... then connect to the device.

    Do note that there is a chance that the flash programming could be interrupted while programming the password locations. In that case the device would become permanently locked.

    Regards,
    Cody

  • Cody

    Thanks for the response, that worked.

    I'm still not sure what caused it to go in to low power mode. I suppose it's possible that it might have been interrupted while programming the password locations. However, it's hard to prove this.

    There is a low power mode function in the code. What I'll do is place it in Sectors B-H. That way, in case programming is interrupted, it will reduce the probably of that function executing on accident.

    Syed

  • Syed, Great! I'm glad you have your device working!

    it's very possible that an instruction was only halfway programmed and was corrupted therefore causing this poor device state. I imagine that low power mode is one of several way the device could get stuck in a state in which it cannot communicate through JTAG.

    One thing you could do to help mitigate this risk is to program a unique code or checksum that your boot loader checks for before branching to application code. The closer this checksum is to being the last thing programmed the better.

    Regards,
    Cody