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.

CC1310: UART_close() adds 2mA current

Part Number: CC1310


I am working on a CC1310 based board (own design), trying to optimize current consumption.

When application is in low power mode, only the radio wakes up once in a while.

Other tasks is stopped with Semaphore_pend(semC, BIOS_WAIT_FOREVER); This works fin.

Before entering low power mode I want to setup peripherals to consume minimal power.

When I close my UART by calling UART_close(), current rises with 2mA...

I have set all unused pins to PIN_INPUT_DIS | PIN_GPIO_OUTPUT_DIS | PIN_NOPULL.

After calling UART_close(), I set RX/TX pins to the above too.

1: UART_close()

2: Set pins inactive

-> 2mA added current.

Why is this happening?

I can't find an application note going through "best practice" to lower power consumption. 

Thanks

Kaare

  • Kaare,

    Are you using pull-up or pull-down resistors?

    Derrick
  • No PU on TX/RX.
    And I initiate the pins to disabled both input and output mode (if this makes sense).
    Even if I had PU, they should not draw any current.

    Kaare
  • Kaare,

    Could you vaguely describe the physical UART bus?

    It may be possible that you have leak current.

    Thanks,
    Derrick
  • - Try to strip down the code to the minimum with only UART as a task. If that still is a issue, try to run the code on a launchpad (known good hardware) and see if you still have a issue. If so, please post the example project that shows the issue.
  • TX/RX is connected directly to a GSM module TX/RX (SIM868).
    No pullups.

    I am still not sure where the leak current should come from, when I have disabled the CC1310 pin.
    How can a disabled pin leak 1 or 2 mA?
    Have I disabled it properly by using PIN_INPUT_DIS and PIN_GPIO_OUTPUT_DIS?
  • I will try this later today.
  • Kaare,

    What results did you see when using a LaunchPad & minimum code?

    Derrick
  • Hi Derrick

    I am working on it right now. I have minimized the application code on my target (not launchpad), and only starts up my RF task. Not initiating any other peripherals.

    Then I get a current of 640 uA when radio is OFF. So my UART problem is not present. I still don't know what causes it, but I will roll in my application step by step, and observe when it happens.

    The 640 uA is still way too high, but I am reading the documentation on the power policy, and how to use it. Right now I can't find exactly where the power policy is set.

    My application is based on the "rfSynchronizedPacketRx" example project.

    Using the power policy and maybe the pin park functionality is what I want.

    The 640 uA indicates that it is still in idle state, and not standby.

    Kaare

  • Kaare,

    Are you referring to the Power config structure in the CC1310_LAUNCHXL.c file?

    const PowerCC26XX_Config PowerCC26XX_config = {
        .policyInitFxn      = NULL,
        .policyFxn          = &PowerCC26XX_standbyPolicy,
        .calibrateFxn       = &PowerCC26XX_calibrate,
        .enablePolicy       = true,
        .calibrateRCOSC_LF  = true,
        .calibrateRCOSC_HF  = true,
    };

     It may be possible that something (maybe a peripheral driver) has set a power constraint to prevent standby mode.

    Derrick

  • What could this peripheral driver be? Simple GPIO?
    I only use the radio, and in this simple example, a few GPIO, set up like below.

    A charge pin used to enable/disable a FET on the board.
    The RX/TX pins set to input/output (not used in normal application. Only used for test of this issue)
    And then some unused pins, also for test, to be sure no pins can sink/source any current.

    No UART, I2C etc is setup.


    const PIN_Config BoardGpioInitTable[] = {

    CC1310DK_7XD_CHARGE_EN | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,

    // CC1310DK_7XD_UART_TX | PIN_INPUT_EN | PIN_GPIO_LOW | PIN_PULLUP, /* UART TX pin at inactive level */

    IOID_15 | PIN_INPUT_EN | PIN_NOPULL, // RX
    IOID_14 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, // TX

    IOID_1 | PIN_INPUT_DIS| PIN_GPIO_OUTPUT_DIS | PIN_NOPULL,
    IOID_2 | PIN_INPUT_DIS| PIN_GPIO_OUTPUT_DIS | PIN_NOPULL,
    IOID_3 | PIN_INPUT_DIS| PIN_GPIO_OUTPUT_DIS | PIN_NOPULL,
    IOID_4 | PIN_INPUT_DIS| PIN_GPIO_OUTPUT_DIS | PIN_NOPULL,
    IOID_22 | PIN_INPUT_DIS| PIN_GPIO_OUTPUT_DIS | PIN_NOPULL,
    IOID_23 | PIN_INPUT_DIS| PIN_GPIO_OUTPUT_DIS | PIN_NOPULL,

    PIN_TERMINATE
    };
  • Hi Derrick

    OK, I have now tried to include my application initialization step by step, after I have stripped it down to only the RF task, waking up every 5 seconds to receive a package.

    Stripped down to this, I can get a current that is "non'measurable" = in the uA range. Great!

    Then I add each init functions one by one, and following this scheme:

    1. Program device

    2. Stop debugger

    3. Detach debugger

    4. Power cycle

    5. Application starts up, in RF SYNC mode (Radio ON 100% time)

    6. RF task gets synced, and enters SYNCED mode = wake up every 5 seconds

    7. When entering SYNCED mode, I stop my application task (which does nothing in this stripped down version).

    I do NOT do anything to re-init any peripherals when stopping the application task. 

    Add init Buttons (digital input). Still OK

    Add LED init = digital output = still OK

    Add I2C init and read external EEPROM = still OK

    Add UART init, but never use it = 1,2 mA !!! 

    It seems like the RTOS handles GPIO and I2C OK. I don't need to do anything with the ports.

    But the UART will keep "something" awake. Or?

    If I call the UART_close(), it will add 2-2.5 mA extra.

    I have tried to re-init the UART RX/TX pins to "everything", but nothing seems to have any influence

    So: The question is, how do I close down the UART properly?

    I init the UART like this (almost copy from the original TI example)

    static void uartTaskFunction(UArg arg0, UArg arg1)
    {
    UART_Params uartParams;
    UART_init();

    /* Create a UART with data processing off. */
    UART_Params_init(&uartParams);
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readReturnMode = UART_RETURN_FULL;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.baudRate = 115200;

    // uartParams.readMode = UART_MODE_BLOCKING;

    uartParams.readMode = UART_MODE_CALLBACK;
    uartParams.readCallback = (UART_Callback) readCallback;

    // uartParams.writeMode = UART_MODE_CALLBACK;
    uartParams.writeCallback = (UART_Callback) uart_write_cb;
    uartParams.writeMode = UART_MODE_BLOCKING;// Then we don't have to take care of waiting TX to finish before next TX

    uart = UART_open(Board_UART0, &uartParams);

  • I have done some more testing, after reading some other users's issue with the UART and standby mode:

    I tried using UART_control(Board_UART0, UART_CMD_RXDISABLE, NULL); in stead of the UART_close().

    This was the exact same result as if using UART_close(): 1,2 mA

     

    Then I tried setting up the UART to CALLBACK and not BLOCKING for the Tx.

    And called UART_readCancel().

    Same result, no standby...

     

    I really can't find out why the UART keeps the RTOS from entering standby?

  • More info:

    I have found out that the issue is caused by the UART RX in UART_MODE_CALLBACK, because there is no timeout in this mode.
    When I set it to UART_MODE_BLOCKING, it enters standby.

    I tried different methods.
    UART_readCancel() should cancel the current read command (UART_read() ). But it still does not enter standby.

    I think the question is as simple as:
    How do I make the UART enter standby, when RX is waiting for a en RX byte?

    Copy from TI doc, which tells that I should call the UART_readCancel() to enter standby when using CALLBACK mode.

    But it does not work:

    General timeout

    A timeout value can only be specified for reads and writes in UART_MODE_BLOCKING. If a timeout occurs during a read when in UART_MODE_BLOCKING, the number of bytes received will be returned and the UART_Object.status will be set to UART_TIMED_OUT. After a read timeout, RX will remain on, but device is allowed to enter standby. For more details see Power Management chapter below.

    In UART_MODE_CALLBACK there is no timeout and the application must call UART_readCancel() or UART_writeCancel() to abort the operation.

    Note
    A new read or write will reset the UART_Object.status to UART_OK. Caution must be taken when doing parallell reads and writes.

    Power Management

    The TI-RTOS power management framework will try to put the device into the most power efficient mode whenever possible. Please see the technical reference manual for further details on each power mode.

    The UARTCC26XX driver is setting a power constraint during operation to keep the device out of standby. When the operation has finished, the power constraint is released. The following statements are valid:

    • After UART_open(): the device is still allowed to enter standby.
    • During UART_read(): the device cannot enter standby.
    • After an RX error (overrun, break, parity, framing): device is allowed to enter standby.
    • After a successful UART_read(): The device is allowed to enter standby, but RX remains on.
      • Note: Device might enter standby while a byte is being received if UART_read() is not called again after a successful read. This could result in corrupt data being received.
      • Note: Application thread should typically either issue another read after UART_read() completes successfully, or call UART_readCancel() to disable RX and thus assuring that no data is received while entering standby.
    • After UART_read() times out in UART_MODE_BLOCKING: The device is allowed to enter standby, but RX remains on.
      • Note: Device might enter standby while a byte is being received if UART_read() is not called again after a timeout. This could result in corrupt data being received.
      • Note: Application thread should typically either issue another read after UART_read() times out to continue reception.
    • During UART_write(): the device cannot enter standby.
    • After UART_write() succeeds: the device can enter standby.
    • If UART_writeCancel() is called: the device can enter standby.
    • After write timeout: the device can enter standby.


    br
    Kaare

  • What SDK are you currently working off?

    Is it possible for you to try running a stripped down version of the "uartecho" where you simple open and close the driver, then try go in to sleep (calling Task_Sleep(BIOS_WAIT_FOREVER)). ?

    Also, could you post your "UARTCC26XX_HWAttrsV2" setup from the board file?
  • SDK version 1.30.0.06

    It is the uart echo demo I have used in my stripped down test. When I use the uart setup from there, it works, because it is not setup for CALLBACK.
    But when I use CALLBACK, it does not enter standby.

    Just after UART_open(), I call the UART_read() which initiates the first wait for an RX byte.
    If I don't make this call, it also enters standby, even if it set up as CALLBACK.
    This indicates very good, that it is the pending READ command that holds the RTOS from entering standby.

    The documentation tells me that I should just run the UART_readCancel, and the the command should be canceld, and standby entered.
    But this simply does not happen...


    const UARTCC26XX_HWAttrsV2 uartCC26XXHWAttrs[CC1310DK_7XD_UARTCOUNT] = {
    {
    .baseAddr = UART0_BASE,
    .powerMngrId = PowerCC26XX_PERIPH_UART0,
    .intNum = INT_UART0_COMB,
    .intPriority = ~0,
    .swiPriority = 0,
    .txPin = CC1310DK_7XD_UART_TX,
    .rxPin = CC1310DK_7XD_UART_RX,
    .ctsPin = PIN_UNASSIGNED,
    .rtsPin = PIN_UNASSIGNED
    }
    };
  • Could you try doing the same test using the latest SDK version?

    There have been a lot of work done on the power manager so it would be interesting to see if this makes any difference. I ran the modified uartecho example of the newest SDK and I was not able to observe this problem.
  • I will try that.
    In the doc for updating SDK version, it says:

    If you are upgrading from a version of the SDK 1.40 or older to a version greater than 1.40 you will also need to add ${COMPILER_FLAGS} to the advanced settings for the XDC Tools.

    It is not 100% clear to me where I shoudl insert the "${COMPILER_FLAGS}.
    It just says inthe "Advanced settings".
    There is a section called "Advanced options". Is this the place? And where should I insert it?

    Or is it in the "Package Repositories" section?
  • I get this error after installing new SDK / XDC tools, and made a Clean and Rebuild:
    I can't google a usable answer... Can you help with this?

    I also tried installing the newest CCS V7.3, but with same result.

    gmake[2]: *** [build-1212975679-inproc] Error 1
    gmake[1]: *** No rule to make target 'build-1212975679', needed by 'configPkg/linker.cmd'.
    gmake[1]: Target 'configPkg/linker.cmd' not remade because of errors.
    gmake: *** [all] Error 2

    I placed the "${COMPILER_FLAGS} in the "Package repositories":



  • Try adding the compiler flags under the "Additional compiler options" under XDCtools->Advanced Options and see if that solves your problem.

  • OK, it removed the error, but added 18 new... I always fear when updating to newer versions...

    First, it claims that device family is not set. The rest of the errors may be caused by this.

    I have copied screenshots of the error description and how ${COMPILER_FLAGS} is inserted.

  • If you have not already, add "DeviceFamily_CC13X0" to your predefined symbols under "ARM Compiler->Predefined symbols", that should take care of the device family error.

    If this does not solve all the errors, can you post screenshots of the XDCtools, ARM compiler and ARM linker flag summary?
  • I added the device family, and then 17 errors :)

    Screenshots attached. But the linker flags is not present (see screenshot). I can find it in the application projects, but not in the "tirtos_builds-...." project.

  • The "--define=--define DeviceFamily_CC13X0" strikes me as odd. I would expect it to be simply --define=DeviceFamily_CC13X0.

    Can you try edit the flags so that the compiler flags are "--define=DeviceFamily_CC13X0"?
    Also, for the XDCtools flag, change "-DDEVICE_FAMILY=cc13x0" to "-DDeviceFamily_CC13X0".

    If it is possible, could you maybe export and share the project with me and I could have a go at getting it up and running on my own machine?
  •  Ah, Compiler define was inserted wrong. My bad. CCS is not my daily tool...

    Still errors, though. but not so many.

    Changed the XDCtools flag as you told, but no change.

    If necessary, I can send you the workspace.

  • Try to go in under "ARM Compiler->Processor Options" and change the target processor to 7M3 (if it is already, try changing it to something else then change it back again).

    If you want, you can send me your workspace and I'll have a look, just let me know in a PM.
  • 7M3 was selected. Changing between other types and back does no good.
    How can I send a PM?
  • I have sent you a connection request here on the forum!
  • Thanks for help making my project compile in the new environments !
    But.... It did not solve my problem: It still don't enter standby when I have called UART_read(), even if I call the UART_readCancel().

    TI documentation tells that this is the way to do it, and it makes sense. But I can't make it work...

    See below.

    Any other suggestions?




    br
    Kaare

  • GOT IT !!!

    UART_readCancel() actually works, even though it looked like it didn't.

    But it is important to know that calling this function will force a call to the read callback function! This is not mentioned anywhere.

    In my simple read callback function I did the following:

    - Read the received byte

    - Call UART_read()

    But when I call UART_readCancel, the callback is called, with size = 0 bytes.

    And then I start a new read command = no standby.

    New callback:

    - If size = 0 bytes, do nothing

    - If size is as expected, read and start new read

    I think TI should write in the documentation, that readCancel() forces a callback call, and maybe make a better UART example. The UART examples are really simple.

    I can now move on to finalize my application :)

    Kaare

  • Glad that you were able to get it to work!

    As far as I can see, the documentation actually specifies that the readCancel will call the callback no matter what.

    "This function cancels an asynchronous UART_read() operation and is only applicable in UART_MODE_CALLBACKUART_readCancel() calls the registered RX callback function no matter how many bytes were received. It is the application's responsibility to check the count argument in the callback function and handle cases where only a subset of the bytes were received."

    Is this full text not present in your documentation? In that case, where di you find the documentation? 

  • I have found explanations and documentation on different forums, E2E posts, and here:

    http://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/tirtos/2_20_00_06/exports/tirtos_full_2_20_00_06/products/tidrivers_full_2_20_00_08/docs/doxygen/html/_u_a_r_t_8h.html#a51ed7e94d5b409ca1fcb2d65c5a25c3c

    See my post 1/12 07:04 in this thread.

    where did you find the documentation you have copied the explanation from?

    I would be happy to read it :)

    br

    Kaare

  • I copied the explanation out of the SDK documentation. Typically, I would recommend you look there for documentation.

    You can find this in the SDK folder under "docs/Documentation_Overview.html" and navigate to TI-Drivers (or what ever else you might need to look into). There is often two levels to the drivers, UART for example has an UART.h and CC26XXUART.h level. The first is the top level skeleton, while the second one is the actual device specific implementation (in this case, CC13XX and CC26XX uses the same driver).

    I recommend to look in to both headers when you are looking for a feature. There are some cases where some of the top-level functions are not supported bu the device specific driver. Also, the device specific header can contain some information on device specific behavior that is not mentioned in the top-level.

    Happy reading :)