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.

CC2745R10-Q1: CC2745R10-Q1 : When the SPI communication method is changed from polling to DMA, data cannot be sent.

Part Number: CC2745R10-Q1
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hello, TI,

When the SPI communication method is changed from polling to DMA, data cannot be sent.

(Environment)
Software Product: SimpleLink Low Power F3 SDK (8.30.00.11_ea)
Board: CC2745R10-Q1 Development Platform

In the above environment, the SPI communication method was changed from polling to DMA.

(Changes(Sysconfig))
SERIAL INTERFACES -> SPI ->
Min DMA Transfer Size: 977 → 0
DMA Interrupt Priority: 7 → 6

After making the above changes and debugging each,
Before the change (polling): When trying to send 51 bytes of data, 51 bytes of data is sent. (Data transmission successful)
After the change (DMA): When trying to send 51 bytes of data, 35 bytes of data is sent. (Data transmission failed)

Why does this result?

Regards,

Sho

  • The above problem (35 bytes of data are sent) occurs when the board is operating alone (on-chip).
    When debugging with IAR, 51 bytes of data can be sent.

  • Hello,

    Thank you for reaching out! We will take a look at your issue and get back to you ASAP! 

    Best Regards,

    Tarek D

  • Hello,

    Thank you for reaching out and sorry for the delay! What status code are you receiving, after calling SPI_transfer() ?

    Best Regards,

    Tarek

  • Hello, Tarek,

    Thank you.
    Regarding SPI_transfer(), I haven't called it.
    The status code is returning true.

    Regards,

    Sho

  • > The above problem (35 bytes of data are sent) occurs when the board is operating alone (on-chip).
    > When debugging with IAR, 51 bytes of data can be sent.

    Regarding the above phenomenon,
    When sending 14 bytes, during debug execution: 14 bytes sent When board alone (on-chip) operation: no sending
    When sending 51 bytes, during debug execution: 51 bytes sent When board alone (on-chip) operation: 35 bytes sent
    When sending 99 bytes, during debug execution: 99 bytes sent When board alone (on-chip) operation: 83 bytes sent
    In each case, the length of the sent data is 16 bytes shorter, and the clock for 16 bytes is not running.

  • Hello Sho,

    This is certainly strange behavior. What are you setting the SPI frame format to? Could you try setting it to SPI_POL0_PHA1 and see if the problem persists?

    Best Regards,

    Tarek D

  • Hello, Tarek,

    The SPI frame format is already set to SPI_POL0_PHA1.
    I tried changing it to SPI_POL0_PHA0, but the results seem to be almost the same.
    (35 bytes of data are sent)

    Regards,

    Sho

  • Hello Sho,

    Could you share all the SPI parameters you are passing? And possibly a code snippet of how you're using SPI?

    Best Regards,

    Tarek

  • First, the SPI parameters passed are as follows:

    transferMode: SPI_MODE_BLOCKING
    bitRate: 1000000
    dataSize: 8
    frameFormat: SPI_POL0_PHA1

    Regards,

    Sho

  • Below is a code snippet showing how to use SPI:

    static SPI_Params sts_SPI_DRV_spiParams;
    static SPI_Handle sts_SPI_DRV_spiHandle;
    static SPI_Transaction sts_SPI_DRV_transaction;
    
    #define D_NULL_                         ( NULL )
    #define mcS4_SPI_DRV_SPI_SPI_MASTER     (SPI_CONTROLLER)
    #define mcU4_SPI_DRV_SPI_TIMEOUT        ((uint32_t)1000U)
    #define mcU4_SPI_DRV_SPI_BAUDRATE       ((uint32_t)1000000U)
    #define mcU4_SPI_DRV_SPI_DATASIZE       ((uint32_t)8U)   
    
    
    
    uint8_t u1g_SPI_DRV_init( void )
    {
        uint8_t u1t_initRslt = 0x01;
        util_memset( &pu1s_SPI_DRV_txBuf[0], 0x00, ( 1027 ) );
        util_memset( &pu1s_SPI_DRV_rxBuf[0], 0x00, ( 1027 ) );
        sts_SPI_DRV_transaction.rxBuf = (void*)pu1s_SPI_DRV_rxBuf;
        
        SPI_init();
        SPI_Params_init( &sts_SPI_DRV_spiParams );
        
        vos_SPI_DRV_spiParams_set();
        sts_SPI_DRV_spiHandle = SPI_open( CONFIG_SPI_INDEX_COUNT, &sts_SPI_DRV_spiParams);
        
        if( ( SPI_Handle )D_NULL_ != sts_SPI_DRV_spiHandle ){
            SPI_close( sts_SPI_DRV_spiHandle );
        }
        else
        {
            u1t_initRslt = 0x02;
        }
    
        return ( u1t_initRslt );
    }
    
    static void vos_SPI_DRV_spiParams_set( void )
    {
    	sts_SPI_DRV_spiParams.transferMode        = SPI_MODE_BLOCKING;
    /*	sts_SPI_DRV_spiParams.transferTimeout     = mcU4_SPI_DRV_SPI_TIMEOUT; */
    	sts_SPI_DRV_spiParams.transferCallbackFxn = D_NULL_;
    	sts_SPI_DRV_spiParams.mode                = mcS4_SPI_DRV_SPI_SPI_MASTER;
    	sts_SPI_DRV_spiParams.bitRate             = mcU4_SPI_DRV_SPI_BAUDRATE;
    	sts_SPI_DRV_spiParams.dataSize            = mcU4_SPI_DRV_SPI_DATASIZE;
    	sts_SPI_DRV_spiParams.frameFormat         = SPI_POL0_PHA1;
    
    	return;
    	}
    
    bool bog_SPI_DRV_transferFrame( void )
    {
       bool bot_result = false;
    
        vos_SPI_DRV_spiParams_set();
        sts_SPI_DRV_spiHandle = SPI_open(0, &sts_SPI_DRV_spiParams);
        
        if( ( SPI_Handle )D_NULL_ != sts_SPI_DRV_spiHandle ){
            bot_result = SPI_transfer( sts_SPI_DRV_spiHandle, &sts_SPI_DRV_transaction );
            SPI_close( sts_SPI_DRV_spiHandle );
        }
        
        return ( bot_result );
    }

    Regards,

    Sho

  • Hello, Tarek,

    Is the investigation progressing?
    If you know anything at all, please let me know.

    Compared to when debugging with IAR,
    when the board is running alone (on-chip),
    there is 16 bytes less data sent (the clock stops midway),
    so I think there is something suspicious about the initialization.

    Regards,

    Sho

  • Hello,

    M apologies for the delay! Could you attempt changing the power policy from standbyPolicy to doWFI? To do this:

    1- Go to the syscfg file inside your project

    2- Go to the Power section of the TI Drivers

    3- Change the power policy from standbyPolicy to doWFI

    This may not be a permanent fix, but will help us in further diagnosing this issue.

    Best Regards,

    Tarek D

  • Hello, Tarek,

    The power policy has been changed from PowerCC27XX_standbyPolicy to PowerCC27XX_doWFI.

    The results were the same:
    IAR Debug : 51bytes
    Standalone (on-chip) : 35 bytes

    ----------------------------------------------------------------------------------------------------

    IAR Debug

      

    ----------------------------------------------------------------------------------------------------

    Standalone (on-chip)

      

    Please let me know if there is any additional information you would like.

    Regards,

    Sho

  • Hello Sho,

    Thank you for providing this info! This indeed is very strange behavior. As a test, could you test the out of box SPI examples found inside the SDK? Also, could you provide some more code snippets, so that we can further analyze what's going on?

    Best Regards,

    Tarek D

  • Hello, Tarek,

    We will perform testing using the SPI sample included in the SDK.
    What kind of code snippets will be required?
    Will the code snippets for initialization, parameter setting, and transfer be sufficient?

    Regards,

    Sho

  • Hello Sho,

    I am using SimpleLink F3 SDK v9.11.00.18 with the spicontroller example on a LP-EM-CC2745R10-Q1 with IAR ARM v9.60.3 and am not observing the issue you are reporting.  Please note that the CC2745R10-Q1 was not fully supported in the SimpleLink F3 SDK until v8.40 according to the SDK Release Notes.  I am providing spicontroller.c and spicontroller.syscfg for your reference.  Please consider upgrading your SimpleLink F3 SDK and provide additional comments if my example does not adequately configured to demonstrate the issue

    /*
     * Copyright (c) 2018-2024, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *     notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *     notice, this list of conditions and the following disclaimer in the
     *     documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *     its contributors may be used to endorse or promote products derived
     *     from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*
     *  ======== spicontroller.c ========
     */
    #include <stddef.h>
    #include <stdint.h>
    #include <string.h>
    
    /* POSIX Header files */
    #include <pthread.h>
    #include <semaphore.h>
    #include <unistd.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/SPI.h>
    #include <ti/display/Display.h>
    
    /* Driver configuration */
    #include "ti_drivers_config.h"
    
    #define THREADSTACKSIZE (1024)
    
    #define SPI_MSG_LENGTH (32)
    #define CONTROLLER_MSG ("Hello from controller, msg#: ")
    
    #define MAX_LOOP (10)
    
    #ifdef DeviceFamily_CC35XX
        #define CONFIG_GPIO_LED_0 GPIO_INVALID_INDEX
        #define CONFIG_GPIO_LED_1 GPIO_INVALID_INDEX
    #endif
    
    static Display_Handle display;
    
    unsigned char controllerRxBuffer[SPI_MSG_LENGTH];
    unsigned char controllerTxBuffer[SPI_MSG_LENGTH];
    
    /* Semaphore to block controller until peripheral is ready for transfer */
    sem_t controllerSem;
    
    /*
     *  ======== controllerThread ========
     *  Controller SPI sends a message to peripheral while simultaneously receiving a
     *  message from the peripheral.
     */
    void *controllerThread(void *arg0)
    {
        SPI_Handle controllerSpi;
        SPI_Params spiParams;
        SPI_Transaction transaction;
        uint32_t i;
        bool transferOK;
        int32_t status;
    
        /*
         * Create synchronization semaphore; the controller will wait on this semaphore
         * until the peripheral is ready.
         */
        status = sem_init(&controllerSem, 0, 0);
        if (status != 0)
        {
            Display_printf(display, 0, 0, "Error creating controllerSem\n");
    
            while (1) {}
        }
    
        /* Open SPI as controller (default) */
        SPI_Params_init(&spiParams);
        spiParams.frameFormat = SPI_POL0_PHA1;
        /* See device-specific technical reference manual for supported speeds */
        spiParams.bitRate     = 1000000;
        controllerSpi         = SPI_open(CONFIG_SPI_CONTROLLER, &spiParams);
        if (controllerSpi == NULL)
        {
            Display_printf(display, 0, 0, "Error initializing controller SPI\n");
            while (1) {}
        }
        else
        {
            Display_printf(display, 0, 0, "Controller SPI initialized\n");
        }
    
        /* Copy message to transmit buffer */
        strncpy((char *)controllerTxBuffer, CONTROLLER_MSG, SPI_MSG_LENGTH);
    
        for (i = 0; i < MAX_LOOP; i++)
        {
    
            /* Initialize controller SPI transaction structure */
            controllerTxBuffer[sizeof(CONTROLLER_MSG) - 1] = (i % 10) + '0';
            memset((void *)controllerRxBuffer, 0, SPI_MSG_LENGTH);
            transaction.count = SPI_MSG_LENGTH;
            transaction.txBuf = (void *)controllerTxBuffer;
            transaction.rxBuf = (void *)controllerRxBuffer;
    
            /* Toggle user LED, indicating a SPI transfer is in progress */
            GPIO_toggle(CONFIG_GPIO_LED_1);
    
            /* Perform SPI transfer */
            transferOK = SPI_transfer(controllerSpi, &transaction);
            if (transferOK)
            {
                Display_printf(display, 0, 0, "Controller received: %s", controllerRxBuffer);
            }
            else
            {
                Display_printf(display, 0, 0, "Unsuccessful controller SPI transfer");
            }
    
            /* Sleep for a bit before starting the next SPI transfer  */
            sleep(3);
        }
    
        SPI_close(controllerSpi);
    
        Display_printf(display, 0, 0, "\nDone");
    
        return (NULL);
    }
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        pthread_t thread0;
        pthread_attr_t attrs;
        struct sched_param priParam;
        int retc;
        int detachState;
    
        /* Call driver init functions. */
        Display_init();
        GPIO_init();
        SPI_init();
    
        /* Configure the LED pins */
        GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
        GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        /* Open the display for output */
        display = Display_open(Display_Type_UART, NULL);
        if (display == NULL)
        {
            /* Failed to open display driver */
            while (1) {}
        }
    
        /* Turn on user LED */
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
    
        Display_printf(display, 0, 0, "Starting the SPI controller example");
        Display_printf(display,
                       0,
                       0,
                       "This example requires external wires to be "
                       "connected to the header pins. Please see the Readme.html and Board.html for details.\n");
    
        /* Create application threads */
        pthread_attr_init(&attrs);
    
        detachState = PTHREAD_CREATE_DETACHED;
        /* Set priority and stack size attributes */
        retc        = pthread_attr_setdetachstate(&attrs, detachState);
        if (retc != 0)
        {
            /* pthread_attr_setdetachstate() failed */
            while (1) {}
        }
    
        retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
        if (retc != 0)
        {
            /* pthread_attr_setstacksize() failed */
            while (1) {}
        }
    
        /* Create controller thread */
        priParam.sched_priority = 1;
        pthread_attr_setschedparam(&attrs, &priParam);
    
        retc = pthread_create(&thread0, &attrs, controllerThread, NULL);
        if (retc != 0)
        {
            /* pthread_create() failed */
            while (1) {}
        }
    
        return (NULL);
    }
    

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/538/spicontroller.syscfg

    Regards,
    Ryan

  • Hello, Ryan

    ●Upgrade from SDK v8.30 to SDK v9.10
     I upgraded from SimpleLink Low Power F3 SDK v8.30.00.11_ea to SimpleLink Low Power F3 SDK v9.10.00.83.
     At the same time, I upgraded from IAR ARM v9.50.2 to IAR ARM v9.60.3.
     After that, I made the following changes in Sysconfig.

     (Changes(Sysconfig))
      SERIAL INTERFACES -> SPI ->
      Min DMA Transfer Size: 977 → 0
      DMA Interrupt Priority: 7 → 6

     The result was the same as before, changing from 51 to 35 bytes after changing to DMA.
     For reference, I am sending you the Sysconfig used with SDK v8.30 and SDK v9.10.
     (Are there any other items that need to be set in Sysconfig?
     Have there been any more setting items (SPI/DMA) since upgrading the SDK?)

    ●Code snippet
     Is there a code snippet for what kind of processing?

    ●SPILPF3DMA.h file reference
     Driver include
     The SPI header file should be included in an application as follows:
     #include <ti/drivers/SPI.h>
     #include <ti/drivers/spi/SPILPF3DMA.h>
     #include <ti/drivers/dma/UDMALPF3.h>
     Awareness that the above includes are necessary
     It is included in the location where SPI_transfer() is performed
     Is this correct?

    Regards,

    Sho

    Sysconfig SDK 8.30 NG (DMA)

    /**
     * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
     * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
     * @cliArgs --device "CC2745R10RHAQ1" --part "Default" --package "RHA" --rtos "freertos" --product "simplelink_lowpower_f3_sdk@8.30.00.11_ea"
     * @v2CliArgs --device "CC2745R10-Q1" --package "VQFN (RHA)" --rtos "freertos" --product "simplelink_lowpower_f3_sdk@8.30.00.11_ea"
     * @versions {"tool":"1.21.0+3721"}
     */
    scripting.excludeFromBuild("FreeRTOSConfig.h");
    
    /**
     * Import the modules used in this configuration.
     */
    const FreeRTOS              = scripting.addModule("/freertos/FreeRTOS");
    const idleHooks             = scripting.addModule("/freertos/idleHooks", {}, false);
    const idleHooks1            = idleHooks.addInstance();
    const idleHooks2            = idleHooks.addInstance();
    const idleHooks3            = idleHooks.addInstance();
    const ble                   = scripting.addModule("/ti/ble5stack/ble");
    const CCFG                  = scripting.addModule("/ti/devices/CCFG");
    const AESCBC                = scripting.addModule("/ti/drivers/AESCBC", {}, false);
    const AESCBC1               = AESCBC.addInstance();
    const AESCCM                = scripting.addModule("/ti/drivers/AESCCM", {}, false);
    const AESCCM1               = AESCCM.addInstance();
    const AESCCM2               = AESCCM.addInstance();
    const AESCMAC               = scripting.addModule("/ti/drivers/AESCMAC", {}, false);
    const AESCMAC1              = AESCMAC.addInstance();
    const AESCTR                = scripting.addModule("/ti/drivers/AESCTR", {}, false);
    const AESCTR1               = AESCTR.addInstance();
    const AESCTRDRBG            = scripting.addModule("/ti/drivers/AESCTRDRBG");
    const AESCTRDRBG1           = AESCTRDRBG.addInstance();
    const AESECB                = scripting.addModule("/ti/drivers/AESECB", {}, false);
    const AESECB1               = AESECB.addInstance();
    const AESECB2               = AESECB.addInstance();
    const AESECB3               = AESECB.addInstance();
    const AESGCM                = scripting.addModule("/ti/drivers/AESGCM", {}, false);
    const AESGCM1               = AESGCM.addInstance();
    const BatteryMonitor        = scripting.addModule("/ti/drivers/BatteryMonitor");
    const Board                 = scripting.addModule("/ti/drivers/Board");
    const CAN                   = scripting.addModule("/ti/drivers/CAN", {}, false);
    const CAN1                  = CAN.addInstance();
    const CryptoKeyKeyStore_PSA = scripting.addModule("/ti/drivers/CryptoKeyKeyStore_PSA");
    const ECDH                  = scripting.addModule("/ti/drivers/ECDH", {}, false);
    const ECDH1                 = ECDH.addInstance();
    const ECDH2                 = ECDH.addInstance();
    const ECDSA                 = scripting.addModule("/ti/drivers/ECDSA", {}, false);
    const ECDSA1                = ECDSA.addInstance();
    const GPIO                  = scripting.addModule("/ti/drivers/GPIO", {}, false);
    const GPIO3                 = GPIO.addInstance();
    const GPIO4                 = GPIO.addInstance();
    const GPIO5                 = GPIO.addInstance();
    const GPIO6                 = GPIO.addInstance();
    const GPIO7                 = GPIO.addInstance();
    const GPIO8                 = GPIO.addInstance();
    const GPIO9                 = GPIO.addInstance();
    const GPIO10                = GPIO.addInstance();
    const GPIO11                = GPIO.addInstance();
    const GPIO12                = GPIO.addInstance();
    const GPIO13                = GPIO.addInstance();
    const GPIO14                = GPIO.addInstance();
    const GPIO15                = GPIO.addInstance();
    const GPIO16                = GPIO.addInstance();
    const LGPTimer              = scripting.addModule("/ti/drivers/LGPTimer", {}, false);
    const LGPTimer1             = LGPTimer.addInstance();
    const LGPTimer2             = LGPTimer.addInstance();
    const NVS                   = scripting.addModule("/ti/drivers/NVS", {}, false);
    const NVS1                  = NVS.addInstance();
    const NVS2                  = NVS.addInstance();
    const RCL                   = scripting.addModule("/ti/drivers/RCL");
    const RNG                   = scripting.addModule("/ti/drivers/RNG", {}, false);
    const RNG1                  = RNG.addInstance();
    const SHA2                  = scripting.addModule("/ti/drivers/SHA2", {}, false);
    const SHA21                 = SHA2.addInstance();
    const SPI                   = scripting.addModule("/ti/drivers/SPI", {}, false);
    const SPI1                  = SPI.addInstance();
    const TRNG                  = scripting.addModule("/ti/drivers/TRNG", {}, false);
    const TRNG1                 = TRNG.addInstance();
    const TRNG2                 = TRNG.addInstance();
    const TRNG3                 = TRNG.addInstance();
    const Watchdog              = scripting.addModule("/ti/drivers/Watchdog", {}, false);
    const Watchdog1             = Watchdog.addInstance();
    const Settings              = scripting.addModule("/ti/posix/freertos/Settings");
    
    /**
     * Write custom configuration values to the imported modules.
     */
    FreeRTOS.assertsEnabled = true;
    
    idleHooks1.$name                = "CONFIG_IdleHookFunction_0";
    idleHooks1.idleHookFunctionName = "WdgM_idleFunc";
    
    idleHooks2.idleHookFunctionName = "Power_idleFunc";
    idleHooks2.$name                = "CONFIG_IdleHookFunction_2";
    
    idleHooks3.idleHookFunctionName = "Gpio_drv_idleFunc";
    idleHooks3.$name                = "CONFIG_IdleHookFunction_1";
    
    ble.deviceName                            = "Peripheral Role";
    ble.addressMode                           = "ADDRMODE_RP_WITH_RANDOM_ID";
    ble.maxBonds                              = 10;
    ble.bondMITMProtection                    = false;
    ble.bondIOCaps                            = "GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT";
    ble.keyDistList                           = ["GAPBOND_KEYDIST_CENCKEY","GAPBOND_KEYDIST_CIDKEY","GAPBOND_KEYDIST_CLINK","GAPBOND_KEYDIST_CSIGN","GAPBOND_KEYDIST_PENCKEY","GAPBOND_KEYDIST_PIDKEY","GAPBOND_KEYDIST_PLINK","GAPBOND_KEYDIST_PSIGN"];
    ble.allowDebugKeys                        = false;
    ble.eraseBondWhileInConn                  = true;
    ble.disableDisplayModule                  = true;
    ble.paramUpdateReq                        = "GAP_UPDATE_REQ_ACCEPT_ALL";
    ble.sendParamsUpdateReq                   = false;
    ble.numOfAdvSets                          = 1;
    ble.L2CAPCOC                              = true;
    ble.L2CAPCOCpsmId                         = 131;
    ble.L2CAPCOCmaxMTU                        = 512;
    ble.L2CAPCOCnofCredits                    = 65435;
    ble.L2CAPCOCcreditsThreshold              = 100;
    ble.L2CAPCOPeerPsmId                      = 131;
    ble.L2CAPCOCmaxMPS                        = 255;
    ble.maxPDUSize                            = 255;
    ble.maxConnNum                            = 5;
    ble.radioConfig.codeExportConfig.$name    = "ti_devices_radioconfig_code_export_param0";
    ble.adcNoiseConfig.codeExportConfig.$name = "ti_devices_radioconfig_code_export_param1";
    ble.advSet1.$name                         = "ti_ble5stack_broadcaster_advertisement_set0";
    ble.advSet1.advParam1.$name               = "ti_ble5stack_broadcaster_advertisement_params0";
    ble.advSet1.advData1.$name                = "ti_ble5stack_broadcaster_advertisement_data0";
    ble.advSet1.scanRes1.$name                = "ti_ble5stack_broadcaster_advertisement_data1";
    scripting.suppress("The example app code handles 2 advertisement sets\\. Please make sure to update the example app code according to the configured number of sets\\.", ble, "numOfAdvSets");
    
    CCFG.overrideHfxtCapArray = true;
    CCFG.hfxtCapArrayQ1       = 0x27;
    CCFG.hfxtCapArrayQ2       = 0x27;
    CCFG.enableHFXTComp       = false;
    CCFG.ccfgTemplate.$name   = "ti_devices_CCFG_CCFGCC27XXTemplate0";
    
    AESCBC1.$name = "CONFIG_AESCBC_0";
    
    AESCCM1.$name = "CONFIG_AESCCM_0";
    
    AESCCM2.$name = "CONFIG_AESCCM_1";
    
    AESCMAC1.$name = "CONFIG_AESCMAC_0";
    
    AESCTR1.$name = "CONFIG_AESCTR_0";
    
    AESCTRDRBG1.$name = "CONFIG_AESCTRDRBG_0";
    
    AESECB1.$name = "CONFIG_AESECB_1";
    
    AESECB2.$name = "CONFIG_AESECB_0";
    
    AESECB3.$name = "CONFIG_AESECB_2";
    
    AESGCM1.$name = "CONFIG_AESGCM_0";
    
    Board.generateInitializationFunctions = false;
    
    CAN1.$name                            = "CONFIG_CAN_0";
    CAN1.nomBitRate                       = 500000;
    CAN1.canFDEnable                      = true;
    CAN1.brsEnable                        = true;
    CAN1.dataBitRate                      = 2000000;
    CAN1.rejectNonMatching                = true;
    CAN1.can.$assign                      = "CAN0";
    CAN1.can.txPin.$assign                = "DIO17_A8";
    CAN1.can.rxPin.$assign                = "DIO18_A7";
    CAN1.txPinInstance.mode               = "Output";
    CAN1.txPinInstance.initialOutputState = "High";
    CAN1.txPinInstance.$name              = "CONFIG_CAN_GPIO_DIO17_A8_19_CAN_0_TX";
    CAN1.rxPinInstance.interruptTrigger   = "Falling Edge";
    CAN1.rxPinInstance.$name              = "CONFIG_CAN_GPIO_DIO18_A7_20_CAN_0_RX";
    
    ECDH1.$name = "CONFIG_ECDH_0";
    
    ECDH2.$name = "CONFIG_ECDH_1";
    
    ECDSA1.$name = "CONFIG_ECDSA_0";
    
    GPIO3.$name           = "CONFIG_GPIO_DIO_12_14_WD";
    GPIO3.mode            = "Output";
    GPIO3.outputStrength  = "Low";
    GPIO3.gpioPin.$assign = "DIO12";
    
    GPIO4.$name           = "CONFIG_GPIO_DIO_11_13";
    GPIO4.mode            = "Output";
    GPIO4.outputStrength  = "Low";
    GPIO4.gpioPin.$assign = "DIO11";
    
    GPIO5.$name            = "CONFIG_GPIO_DIO_0_3";
    GPIO5.outputStrength   = "Low";
    GPIO5.interruptTrigger = "Falling Edge";
    GPIO5.gpioPin.$assign  = "DIO0";
    
    GPIO6.$name           = "CONFIG_GPIO_DIO_21_A4_23";
    GPIO6.mode            = "Output";
    GPIO6.outputStrength  = "Low";
    GPIO6.gpioPin.$assign = "DIO21_A4";
    
    GPIO7.outputStrength   = "Low";
    GPIO7.$name            = "CONFIG_GPIO_DIO_1_4";
    GPIO7.interruptTrigger = "Falling Edge";
    GPIO7.gpioPin.$assign  = "DIO1";
    
    GPIO8.$name           = "CONFIG_GPIO_DIO_2_5";
    GPIO8.mode            = "Output";
    GPIO8.outputStrength  = "Low";
    GPIO8.gpioPin.$assign = "DIO2";
    
    GPIO9.$name              = "CONFIG_GPIO_DIO_7_10";
    GPIO9.mode               = "Output";
    GPIO9.initialOutputState = "High";
    GPIO9.outputStrength     = "Low";
    GPIO9.gpioPin.$assign    = "DIO7";
    
    GPIO10.mode            = "Output";
    GPIO10.$name           = "CONFIG_GPIO_DIO_16_16";
    GPIO10.outputStrength  = "Low";
    GPIO10.gpioPin.$assign = "DIO16";
    
    GPIO11.$name           = "CONFIG_GPIO_DIO_19_A6_21";
    GPIO11.mode            = "Output";
    GPIO11.outputStrength  = "Low";
    GPIO11.gpioPin.$assign = "DIO19_A6";
    
    GPIO12.$name           = "CONFIG_GPIO_DIO_20_A5_22";
    GPIO12.mode            = "Output";
    GPIO12.outputStrength  = "Low";
    GPIO12.gpioPin.$assign = "DIO20_A5";
    
    GPIO13.$name           = "CONFIG_GPIO_DIO_22_A3_24";
    GPIO13.mode            = "Output";
    GPIO13.outputStrength  = "Low";
    GPIO13.gpioPin.$assign = "DIO22_A3";
    
    GPIO14.$name           = "CONFIG_GPIO_DIO_27_A1_32";
    GPIO14.mode            = "Output";
    GPIO14.outputStrength  = "Low";
    GPIO14.gpioPin.$assign = "DIO27_A1";
    
    GPIO15.$name           = "CONFIG_GPIO_DIO_28_A0_33";
    GPIO15.mode            = "Output";
    GPIO15.outputStrength  = "Low";
    GPIO15.gpioPin.$assign = "DIO28_A0";
    
    GPIO16.mode            = "Output";
    GPIO16.outputStrength  = "Low";
    GPIO16.$name           = "CONFIG_GPIO_DIO_15_15";
    GPIO16.gpioPin.$assign = "DIO15";
    
    LGPTimer1.$name = "CONFIG_LGPTIMER_0";
    
    LGPTimer2.$name = "CONFIG_LGPTIMER_1";
    
    NVS1.$name                    = "CONFIG_NVS_APP_DATA";
    NVS1.internalFlash.$name      = "ti_drivers_nvs_NVSLPF30";
    NVS1.internalFlash.regionBase = 0xE0000;
    NVS1.internalFlash.regionSize = 0x4000;
    
    NVS2.$name                    = "CONFIG_NVS_NVM_DATA";
    NVS2.internalFlash.$name      = "ti_drivers_nvs_NVSLPF31";
    NVS2.internalFlash.regionSize = 0x4000;
    NVS2.internalFlash.regionBase = 0xE4000;
    
    RNG1.$name = "CONFIG_RNG_0";
    
    SHA21.$name = "CONFIG_SHA2_0";
    
    SPI1.$name                          = "CONFIG_SPI_0";
    SPI1.minDmaTransferSize             = 0;
    SPI1.dmaInterruptPriority           = "6";
    SPI1.spi.$assign                    = "SPI0";
    SPI1.spi.sclkPin.$assign            = "DIO3";
    SPI1.spi.dmaRxChannel.$assign       = "DMA_CH1";
    SPI1.spi.dmaTxChannel.$assign       = "DMA_CH0";
    SPI1.spi.pociPin.$assign            = "DIO5";
    SPI1.spi.picoPin.$assign            = "DIO4";
    SPI1.sclkPinInstance.outputStrength = "Low";
    SPI1.picoPinInstance.outputStrength = "Low";
    
    TRNG1.$name = "CONFIG_TRNG_0";
    
    TRNG2.$name = "CONFIG_TRNG_1";
    
    TRNG3.$name = "CONFIG_TRNG_2";
    
    Watchdog1.$name  = "CONFIG_WDGM_PARAMS";
    Watchdog1.period = 60000;
    
    /**
     * References between modules
     */
    CCFG.defaultLfoscCompProfile = null;
    
    /**
     * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
     * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
     * re-solve from scratch.
     */
    LGPTimer1.timer.$suggestSolution = "LGPT1";
    LGPTimer2.timer.$suggestSolution = "LGPT0";
    

    Sysconfig SDK 9.10 NG (DMA)

    /**
     * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
     * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
     * @cliArgs --device "CC2745R10RHAQ1" --part "Default" --package "RHA" --rtos "freertos" --product "simplelink_lowpower_f3_sdk@9.10.00.83"
     * @v2CliArgs --device "CC2745R10-Q1" --package "VQFN (RHA)" --rtos "freertos" --product "simplelink_lowpower_f3_sdk@9.10.00.83"
     * @versions {"tool":"1.23.1+4034"}
     */
    scripting.excludeFromBuild("FreeRTOSConfig.h");
    
    /**
     * Import the modules used in this configuration.
     */
    const FreeRTOS       = scripting.addModule("/freertos/FreeRTOS");
    const idleHooks      = scripting.addModule("/freertos/idleHooks", {}, false);
    const idleHooks1     = idleHooks.addInstance();
    const idleHooks2     = idleHooks.addInstance();
    const idleHooks3     = idleHooks.addInstance();
    const ble            = scripting.addModule("/ti/ble/ble");
    const CCFG           = scripting.addModule("/ti/devices/CCFG");
    const AESCBC         = scripting.addModule("/ti/drivers/AESCBC", {}, false);
    const AESCBC1        = AESCBC.addInstance();
    const AESCCM         = scripting.addModule("/ti/drivers/AESCCM", {}, false);
    const AESCCM1        = AESCCM.addInstance();
    const AESCCM2        = AESCCM.addInstance();
    const AESCMAC        = scripting.addModule("/ti/drivers/AESCMAC", {}, false);
    const AESCMAC1       = AESCMAC.addInstance();
    const AESCTR         = scripting.addModule("/ti/drivers/AESCTR", {}, false);
    const AESCTR1        = AESCTR.addInstance();
    const AESECB         = scripting.addModule("/ti/drivers/AESECB", {}, false);
    const AESECB1        = AESECB.addInstance();
    const AESECB2        = AESECB.addInstance();
    const AESECB3        = AESECB.addInstance();
    const AESGCM         = scripting.addModule("/ti/drivers/AESGCM", {}, false);
    const AESGCM1        = AESGCM.addInstance();
    const BatteryMonitor = scripting.addModule("/ti/drivers/BatteryMonitor");
    const Board          = scripting.addModule("/ti/drivers/Board");
    const CAN            = scripting.addModule("/ti/drivers/CAN", {}, false);
    const CAN1           = CAN.addInstance();
    const DMA            = scripting.addModule("/ti/drivers/DMA");
    const ECDH           = scripting.addModule("/ti/drivers/ECDH", {}, false);
    const ECDH1          = ECDH.addInstance();
    const ECDH2          = ECDH.addInstance();
    const ECDSA          = scripting.addModule("/ti/drivers/ECDSA", {}, false);
    const ECDSA1         = ECDSA.addInstance();
    const GPIO           = scripting.addModule("/ti/drivers/GPIO", {}, false);
    const GPIO3          = GPIO.addInstance();
    const GPIO4          = GPIO.addInstance();
    const GPIO5          = GPIO.addInstance();
    const GPIO6          = GPIO.addInstance();
    const GPIO7          = GPIO.addInstance();
    const GPIO8          = GPIO.addInstance();
    const GPIO9          = GPIO.addInstance();
    const GPIO10         = GPIO.addInstance();
    const GPIO11         = GPIO.addInstance();
    const GPIO12         = GPIO.addInstance();
    const GPIO13         = GPIO.addInstance();
    const GPIO14         = GPIO.addInstance();
    const GPIO15         = GPIO.addInstance();
    const GPIO16         = GPIO.addInstance();
    const LGPTimer       = scripting.addModule("/ti/drivers/LGPTimer", {}, false);
    const LGPTimer1      = LGPTimer.addInstance();
    const LGPTimer2      = LGPTimer.addInstance();
    const NVS            = scripting.addModule("/ti/drivers/NVS", {}, false);
    const NVS1           = NVS.addInstance();
    const NVS2           = NVS.addInstance();
    const RCL            = scripting.addModule("/ti/drivers/RCL");
    const RNG            = scripting.addModule("/ti/drivers/RNG", {}, false);
    const RNG1           = RNG.addInstance();
    const SHA2           = scripting.addModule("/ti/drivers/SHA2", {}, false);
    const SHA21          = SHA2.addInstance();
    const SPI            = scripting.addModule("/ti/drivers/SPI", {}, false);
    const SPI1           = SPI.addInstance();
    const TRNG           = scripting.addModule("/ti/drivers/TRNG", {}, false);
    const TRNG1          = TRNG.addInstance();
    const TRNG2          = TRNG.addInstance();
    const TRNG3          = TRNG.addInstance();
    const Watchdog       = scripting.addModule("/ti/drivers/Watchdog", {}, false);
    const Watchdog1      = Watchdog.addInstance();
    const Settings       = scripting.addModule("/ti/posix/freertos/Settings");
    
    /**
     * Write custom configuration values to the imported modules.
     */
    FreeRTOS.assertsEnabled = true;
    FreeRTOS.heapSize       = 0x0000A000;
    
    idleHooks1.$name                = "CONFIG_IdleHookFunction_0";
    idleHooks1.idleHookFunctionName = "WdgM_idleFunc";
    
    idleHooks2.$name                = "CONFIG_IdleHookFunction_1";
    idleHooks2.idleHookFunctionName = "Gpio_drv_idleFunc";
    
    idleHooks3.$name                = "CONFIG_IdleHookFunction_2";
    idleHooks3.idleHookFunctionName = "Power_idleFunc";
    
    ble.L2CAPCOC                              = true;
    ble.deviceName                            = "Peripheral Role";
    ble.addressMode                           = "ADDRMODE_RP_WITH_RANDOM_ID";
    ble.maxRLSize                             = 10;
    ble.maxPDUSize                            = 255;
    ble.maxBonds                              = 10;
    ble.bondIOCaps                            = "GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT";
    ble.allowDebugKeys                        = false;
    ble.eraseBondWhileInConn                  = true;
    ble.disableDisplayModule                  = true;
    ble.paramUpdateReq                        = "GAP_UPDATE_REQ_ACCEPT_ALL";
    ble.sendParamsUpdateReq                   = false;
    ble.numOfAdvSets                          = 1;
    ble.L2CAPCOCpsmId                         = 131;
    ble.L2CAPCOCmaxMTU                        = 512;
    ble.L2CAPCOCmaxMPS                        = 255;
    ble.L2CAPCOCnofCredits                    = 65435;
    ble.L2CAPCOCcreditsThreshold              = 100;
    ble.L2CAPCOPeerPsmId                      = 131;
    ble.maxConnNum                            = 5;
    ble.bondMITMProtection                    = false;
    ble.keyDistList                           = ["GAPBOND_KEYDIST_CENCKEY","GAPBOND_KEYDIST_CIDKEY","GAPBOND_KEYDIST_CLINK","GAPBOND_KEYDIST_CSIGN","GAPBOND_KEYDIST_PENCKEY","GAPBOND_KEYDIST_PIDKEY","GAPBOND_KEYDIST_PLINK","GAPBOND_KEYDIST_PSIGN"];
    ble.radioConfig.codeExportConfig.$name    = "ti_devices_radioconfig_code_export_param0";
    ble.adcNoiseConfig.codeExportConfig.$name = "ti_devices_radioconfig_code_export_param1";
    ble.bleCsConfig.codeExportConfig.$name    = "ti_devices_radioconfig_code_export_param2";
    ble.advSet1.$name                         = "ti_ble_broadcaster_advertisement_set0";
    ble.advSet1.advParam1.$name               = "ti_ble_broadcaster_advertisement_params0";
    ble.advSet1.advData1.$name                = "ti_ble_broadcaster_advertisement_data0";
    ble.advSet1.scanRes1.$name                = "ti_ble_broadcaster_advertisement_data1";
    scripting.suppress("The example app code handles 2 advertisement sets\\. Please make sure to update the example app code according to the configured number of sets\\.", ble, "numOfAdvSets");
    
    CCFG.overrideHfxtCapArray = true;
    CCFG.hfxtCapArrayQ1       = 0x27;
    CCFG.hfxtCapArrayQ2       = 0x27;
    CCFG.enableHFXTComp       = false;
    CCFG.pAppVtorStr          = "0x00000000";
    CCFG.ccfgTemplate.$name   = "ti_devices_CCFG_CCFGCC27XXTemplate0";
    
    AESCBC1.$name = "CONFIG_AESCBC_0";
    
    AESCCM1.$name = "CONFIG_AESCCM_0";
    
    AESCCM2.$name = "CONFIG_AESCCM_1";
    
    AESCMAC1.$name = "CONFIG_AESCMAC_0";
    
    AESCTR1.$name = "CONFIG_AESCTR_0";
    
    AESECB1.$name = "CONFIG_AESECB_0";
    
    AESECB2.$name = "CONFIG_AESECB_1";
    
    AESECB3.$name = "CONFIG_AESECB_2";
    
    AESGCM1.$name = "CONFIG_AESGCM_0";
    
    Board.generateInitializationFunctions = false;
    
    CAN1.$name                            = "CONFIG_CAN_0";
    CAN1.nomBitRate                       = 500000;
    CAN1.canFDEnable                      = true;
    CAN1.rejectNonMatching                = true;
    CAN1.brsEnable                        = true;
    CAN1.dataBitRate                      = 2000000;
    CAN1.can.$assign                      = "CAN0";
    CAN1.can.txPin.$assign                = "DIO17_A8";
    CAN1.can.rxPin.$assign                = "DIO18_A7";
    CAN1.txPinInstance.$name              = "CONFIG_CAN_GPIO_DIO17_A8_19_CAN_0_TX";
    CAN1.txPinInstance.mode               = "Output";
    CAN1.txPinInstance.initialOutputState = "High";
    CAN1.rxPinInstance.$name              = "CONFIG_CAN_GPIO_DIO18_A7_20_CAN_0_RX";
    CAN1.rxPinInstance.interruptTrigger   = "Falling Edge";
    
    ECDH1.$name = "CONFIG_ECDH_0";
    
    ECDH2.$name = "CONFIG_ECDH_1";
    
    ECDSA1.$name = "CONFIG_ECDSA_0";
    
    GPIO3.mode            = "Output";
    GPIO3.outputStrength  = "Low";
    GPIO3.$name           = "CONFIG_GPIO_DIO_12_14";
    GPIO3.gpioPin.$assign = "DIO12";
    
    GPIO4.$name           = "CONFIG_GPIO_DIO_11_13";
    GPIO4.outputStrength  = "Low";
    GPIO4.gpioPin.$assign = "DIO11";
    
    GPIO5.$name            = "CONFIG_GPIO_DIO_0_3";
    GPIO5.interruptTrigger = "Falling Edge";
    GPIO5.gpioPin.$assign  = "DIO0";
    
    GPIO6.$name           = "CONFIG_GPIO_DIO_21_A4_23";
    GPIO6.mode            = "Output";
    GPIO6.outputStrength  = "Low";
    GPIO6.gpioPin.$assign = "DIO21_A4";
    
    GPIO7.$name            = "CONFIG_GPIO_DIO_1_4";
    GPIO7.interruptTrigger = "Falling Edge";
    GPIO7.gpioPin.$assign  = "DIO1";
    
    GPIO8.mode            = "Output";
    GPIO8.outputStrength  = "Low";
    GPIO8.$name           = "CONFIG_GPIO_DIO_2_5_WD";
    GPIO8.gpioPin.$assign = "DIO2";
    
    GPIO9.$name              = "CONFIG_GPIO_DIO_7_10";
    GPIO9.mode               = "Output";
    GPIO9.outputStrength     = "Low";
    GPIO9.initialOutputState = "High";
    GPIO9.gpioPin.$assign    = "DIO7";
    
    GPIO10.$name              = "CONFIG_GPIO_DIO_16_16";
    GPIO10.mode               = "Output";
    GPIO10.outputStrength     = "Low";
    GPIO10.initialOutputState = "High";
    GPIO10.gpioPin.$assign    = "DIO16";
    
    GPIO11.mode               = "Output";
    GPIO11.outputStrength     = "Low";
    GPIO11.$name              = "CONFIG_GPIO_DIO_19_A6_21";
    GPIO11.initialOutputState = "High";
    GPIO11.gpioPin.$assign    = "DIO19_A6";
    
    GPIO12.$name           = "CONFIG_GPIO_DIO_20_A5_22";
    GPIO12.mode            = "Output";
    GPIO12.outputStrength  = "Low";
    GPIO12.gpioPin.$assign = "DIO20_A5";
    
    GPIO13.$name           = "CONFIG_GPIO_DIO_22_A3_24";
    GPIO13.mode            = "Output";
    GPIO13.outputStrength  = "Low";
    GPIO13.gpioPin.$assign = "DIO22_A3";
    
    GPIO14.$name           = "CONFIG_GPIO_DIO_27_A1_32";
    GPIO14.mode            = "Output";
    GPIO14.outputStrength  = "Low";
    GPIO14.gpioPin.$assign = "DIO27_A1";
    
    GPIO15.$name           = "CONFIG_GPIO_DIO_28_A0_33";
    GPIO15.mode            = "Output";
    GPIO15.outputStrength  = "Low";
    GPIO15.gpioPin.$assign = "DIO28_A0";
    
    GPIO16.$name           = "CONFIG_GPIO_DIO_15_15";
    GPIO16.mode            = "Output";
    GPIO16.outputStrength  = "Low";
    GPIO16.gpioPin.$assign = "DIO15";
    
    LGPTimer1.$name = "CONFIG_LGPTIMER_0";
    
    LGPTimer2.$name = "CONFIG_LGPTIMER_1";
    
    NVS1.$name                    = "CONFIG_NVS_APP_DATA";
    NVS1.internalFlash.$name      = "ti_drivers_nvs_NVSLPF30";
    NVS1.internalFlash.regionBase = 0xE0000;
    NVS1.internalFlash.regionSize = 0x4000;
    
    NVS2.$name                    = "CONFIG_NVS_NVM_DATA";
    NVS2.internalFlash.$name      = "ti_drivers_nvs_NVSLPF31";
    NVS2.internalFlash.regionBase = 0xE4000;
    NVS2.internalFlash.regionSize = 0x4000;
    
    RNG1.$name = "CONFIG_RNG_0";
    
    SHA21.$name = "CONFIG_SHA2_0";
    
    SPI1.$name                          = "CONFIG_SPI_0";
    SPI1.dmaInterruptPriority           = "6";
    SPI1.minDmaTransferSize             = 0;
    SPI1.spi.$assign                    = "SPI0";
    SPI1.spi.sclkPin.$assign            = "DIO3";
    SPI1.spi.dmaRxChannel.$assign       = "DMA_CH1";
    SPI1.spi.dmaTxChannel.$assign       = "DMA_CH0";
    SPI1.spi.pociPin.$assign            = "DIO5";
    SPI1.spi.picoPin.$assign            = "DIO4";
    SPI1.sclkPinInstance.outputStrength = "Low";
    SPI1.picoPinInstance.outputStrength = "Low";
    
    TRNG1.$name = "CONFIG_TRNG_0";
    
    TRNG2.$name = "CONFIG_TRNG_1";
    
    TRNG3.$name = "CONFIG_TRNG_2";
    
    Watchdog1.period = 60000;
    Watchdog1.$name  = "CONFIG_WDGM_PARAMS";
    
    /**
     * References between modules
     */
    CCFG.defaultLfoscCompProfile = null;
    
    /**
     * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
     * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
     * re-solve from scratch.
     */
    LGPTimer1.timer.$suggestSolution = "LGPT1";
    LGPTimer2.timer.$suggestSolution = "LGPT0";
    

  • Min DMA Transfer Size: 977 → 0

    977 is not the default in SysConfig, so I assume this was custom for your application.

    Your previous code excerpt is innocuous but I am just now noticing the SPI_close immediately after SPI_transfer.  Can you please insert a delay in between those two APIs?

    Is there any indication that other features such as BLE or CAN which are enabled in your SysConfig and must be used in your project are interfering with the SPI transfer?  Or do you believe that the SPI code you've provided alone is enough to create the error?

     #include <ti/drivers/spi/SPILPF3DMA.h>
     #include <ti/drivers/dma/UDMALPF3.h>

    These are not necessary to include in your application, however you could try copying both <sdk_directory>/source/ti/drivers/spi/SPILPF3DMA.c and <sdk_directory>/source/ti/drivers/dma/UDMALPF3.c into your project to further debug the APIs and determine if any errors are being observed.

    Regards,
    Ryan

  • Hello, Ryan

    I inserted a 100ms sleep between SPI_transfer and SPI_close,
    but the result was the same as before, changing from 51 bytes to 35 bytes.

    Since I'm not using CAN, there's no room for interrupts.

    Since I'm using FreeRTOS, which prioritizes BLE task processing over SPI tasks,
    it's possible that the BLE task will interrupt during the SPI task.
    (However, although I'm looking at task switching this time, another task has not interrupted the SPI task (communication).)

    Regards,

    Sho

  • Hello Sho,

    Thanks for testing.  You could also test only opening SPI once and not opening/closing repeatedly.

    As this behavior cannot be replicated by TI, below are some options:

    • Replicate the issue by adding spicontroller to a BLE example, with whatever change causes the problem to exist, and send us the project for further review
    • Send a minimal feature application project which demonstrates the behavior
    • Debug SPILPF3DMA.c/UDMALPF3.c and report your findings
    • Use SPI polling in your project
    • Use SPI DMA with 16 bytes of padding

    Regards,
    Ryan

  • Hello, Ryan

    UDMALPF3.c
    I was able to run it without any problems.

    SPILPF3DMA.c
    Debug execution was successful.
    On-chip execution stopped within SPILPF3DMA_hwiFxn().

    - SPILPF3DMA_hwiFxn() is executed twice in both on-chip and debug execution.
    - SPILPF3DMA_hwiFxn() is executed immediately after the data transfer starts and during the data transfer (both on-chip and debug execution).
    - In on-chip execution, the second SPILPF3DMA_hwiFxn() execution stops midway.
    - In debug execution, the second SPILPF3DMA_hwiFxn() execution does not stop midway.
    - In on-chip execution, the execution stops before line 422 of SPILPF3DMA.c.

    It seems like another interrupt is occurring where processing stops in SPILPF3DMA_hwiFxn().
    What kind of interrupt processing could be occurring at this point?

    Regards,

    Sho

    SPILPF3DMA.c.

    /*
     * Copyright (c) 2022-2024, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    #include <stdbool.h>
    #include <stddef.h>
    #include <stdint.h>
    
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(inc/hw_memmap.h)
    #include DeviceFamily_constructPath(inc/hw_ints.h)
    #include DeviceFamily_constructPath(inc/hw_spi.h)
    #include DeviceFamily_constructPath(inc/hw_types.h)
    #include DeviceFamily_constructPath(driverlib/udma.h)
    #include DeviceFamily_constructPath(inc/hw_evtsvt.h)
    
    #include <ti/drivers/dma/UDMALPF3.h>
    #include <ti/drivers/dpl/DebugP.h>
    #include <ti/drivers/dpl/HwiP.h>
    #include <ti/drivers/dpl/SemaphoreP.h>
    #include <ti/drivers/dpl/SwiP.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/SPI.h>
    #include <ti/drivers/spi/SPILPF3DMA.h>
    
    /* Headers required for intrinsics */
    #if defined(__TI_COMPILER_VERSION__)
        #include <arm_acle.h>
    #elif defined(__GNUC__)
        #include <arm_acle.h>
    #elif defined(__IAR_SYSTEMS_ICC__)
        #include <intrinsics.h>
    #else
        #error "Unsupported compiler"
    #endif
    
    #define MAX_DMA_TRANSFER_AMOUNT (1024)
    
    #define SPI_DATASIZE_8      (8)
    #define SPI_DATASIZE_16     (16)
    #define PARAMS_DATASIZE_MIN SPI_DATASIZE_8
    #define PARAMS_DATASIZE_MAX SPI_DATASIZE_16
    
    /* API Function Prototypes */
    void SPILPF3DMA_close(SPI_Handle handle);
    int_fast16_t SPILPF3DMA_control(SPI_Handle handle, uint_fast16_t cmd, void *arg);
    void SPILPF3DMA_init(SPI_Handle handle);
    SPI_Handle SPILPF3DMA_open(SPI_Handle handle, SPI_Params *params);
    static void SPILPF3DMA_swiFxn(uintptr_t arg0, uintptr_t arg1);
    bool SPILPF3DMA_transfer(SPI_Handle handle, SPI_Transaction *transaction);
    void SPILPF3DMA_transferCancel(SPI_Handle handle);
    
    /* Local Function Prototypes */
    static void blockingTransferCallback(SPI_Handle handle, SPI_Transaction *msg);
    static void configNextTransfer(SPILPF3DMA_Object *object, SPILPF3DMA_HWAttrs const *hwAttrs);
    static void csnCallback(uint_least8_t);
    static void flushFifos(SPILPF3DMA_HWAttrs const *hwAttrs);
    static inline uint32_t getDmaChannelNumber(uint32_t channelBitMask);
    static bool initHw(SPI_Handle handle);
    static void initIO(SPI_Handle handle);
    static void finalizeIO(SPI_Handle handle);
    static void setIOStandbyState(SPI_Handle handle);
    static inline void primeTransfer(SPI_Handle handle);
    static inline void releaseConstraint(uint32_t txBufAddr);
    static inline void setConstraint(uint32_t txBufAddr);
    static inline void spiPollingTransfer(SPI_Handle handle, SPI_Transaction *transaction);
    static int spiPostNotify(unsigned int eventType, uintptr_t eventArg, uintptr_t clientArg);
    static inline bool spiBusy(SPILPF3DMA_Object *object, SPILPF3DMA_HWAttrs const *hwAttrs);
    static inline void disableSPI(uint32_t baseAddr);
    static inline void enableSPI(SPI_Handle handle);
    static inline bool isSPIEnabled(SPI_Handle handle);
    static inline void enableInterrupt(uint32_t baseAddr, uint32_t irqs);
    static inline void disableInterrupt(uint32_t baseAddr, uint32_t irqs);
    static inline void clearInterrupt(uint32_t baseAddr, uint32_t irqs);
    static void enableDMA(uint32_t baseAddr, uint32_t dmaFlags);
    static void disableDMA(uint32_t baseAddr, uint32_t dmaFlags);
    static inline uint32_t getInterruptStatus(uint32_t baseAddr, bool masked);
    static bool configSPI(uint32_t baseAddr,
                          uint32_t freq,
                          uint32_t format,
                          uint32_t mode,
                          uint32_t bitRate,
                          uint32_t dataSize,
                          uint32_t dsample);
    static int32_t dataPutNonBlocking(uint32_t baseAddr, uint32_t frame);
    static void dataGet(uint32_t baseAddr, uint32_t *frame);
    static bool isSPIbusy(uint32_t baseAddr);
    
    /* RX FIFO over flowed, data was lost */
    #define SPI_INT_RXOF   (SPI_MIS_RXOVF_SET)
    /* RX FIFO trigger level was passed */
    #define SPI_INT_RXFF   (SPI_MIS_RX_SET)
    /* TX FIFO trigger level was passed */
    #define SPI_INT_TXFF   (SPI_MIS_TX_SET)
    /* Transfer complete, HW is idle */
    #define SPI_INT_IDLE   (SPI_MIS_IDLE_SET)
    /* Subset of SPI interrupts used by this driver */
    #define SPI_INT_SUBSET (SPI_INT_TXFF | SPI_INT_RXFF | SPI_INT_RXOF | SPI_INT_IDLE)
    /* All SPI interrupts */
    #define SPI_INT_ALL \
        (SPI_INT_SUBSET | SPI_MIS_TXEMPTY_SET | SPI_MIS_PER_SET | SPI_MIS_RTOUT_SET | SPI_MIS_DMARX_SET | SPI_MIS_DMATX_SET)
    
    /* DSAMPLE default value limits based bit rate */
    #define DSAMPLE_MED_BITRATE  4000000
    #define DSAMPLE_HIGH_BITRATE 8000000
    
    /* Sampling delay value */
    #define DSAMPLE_MAX_CYCLES 0xF0000U
    
    /* Maximum serial clock divider value */
    #define SERIAL_CLK_DIVIDER_MAX 0x3FFU
    
    /* SPI function table for SPILPF3DMA implementation */
    const SPI_FxnTable SPILPF3DMA_fxnTable = {SPILPF3DMA_close,
                                              SPILPF3DMA_control,
                                              SPILPF3DMA_init,
                                              SPILPF3DMA_open,
                                              SPILPF3DMA_transfer,
                                              SPILPF3DMA_transferCancel};
    
    static const uint32_t mode[] = {
        /* SPI_CONTROLLER */
        SPI_CTL1_MS_CONTROLLER,
        /* SPI_PERIPHERAL */
        SPI_CTL1_MS_PERIPHERAL,
    };
    
    /* Mapping SPI frame format from generic driver to driverlib */
    static const uint32_t frameFormat[] = {
        /* SPI_POL0_PHA0 */
        (SPI_CTL0_FRF_MOTOROLA_3WIRE | SPI_CTL0_SPO_LO | SPI_CTL0_SPH_FIRST),
        /* SPI_POL0_PHA1 */
        (SPI_CTL0_FRF_MOTOROLA_3WIRE | SPI_CTL0_SPO_LO | SPI_CTL0_SPH_SECOND),
        /* SPI_POL1_PHA0 */
        (SPI_CTL0_FRF_MOTOROLA_3WIRE | SPI_CTL0_SPO_HI | SPI_CTL0_SPH_FIRST),
        /* SPI_POL1_PHA1 */
        (SPI_CTL0_FRF_MOTOROLA_3WIRE | SPI_CTL0_SPO_HI | SPI_CTL0_SPH_SECOND),
        /* SPI_TI */
        (SPI_CTL0_FRF_TI_SYNC),
        /* SPI_MW */
        (SPI_CTL0_FRF_MICROWIRE),
    };
    
    /*
     * These lookup tables are used to configure the DMA channels for the
     * appropriate (8bit/16bit) transfer sizes.
     */
    static const uint32_t dmaTxConfig[] = {UDMA_MODE_PINGPONG | UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE |
                                               UDMA_ARB_4,
                                           UDMA_MODE_PINGPONG | UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE |
                                               UDMA_ARB_4};
    
    static const uint32_t dmaRxConfig[] = {UDMA_MODE_PINGPONG | UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
                                               UDMA_ARB_4,
                                           UDMA_MODE_PINGPONG | UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 |
                                               UDMA_ARB_4};
    
    static const uint32_t dmaNullConfig[] = {UDMA_MODE_PINGPONG | UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE |
                                                 UDMA_ARB_4,
                                             UDMA_MODE_PINGPONG | UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE |
                                                 UDMA_ARB_4};
    
    /*
     *  ======== SPILPF3DMA_close ========
     */
    void SPILPF3DMA_close(SPI_Handle handle)
    {
        SPILPF3DMA_Object *object         = handle->object;
        SPILPF3DMA_HWAttrs const *hwAttrs = handle->hwAttrs;
    
        /* Disable the SPI */
        disableSPI(hwAttrs->baseAddr);
    
        HwiP_destruct(&(object->hwi));
    
        SwiP_destruct(&(object->swi));
    
        if (object->transferMode == SPI_MODE_BLOCKING)
        {
            SemaphoreP_destruct(&(object->transferComplete));
        }
    
        finalizeIO(handle);
    
        Power_releaseDependency(hwAttrs->powerID);
    
        Power_unregisterNotify(&object->spiPostObj);
    
        object->isOpen = false;
    }
    
    /*!
     *  ======== SPILPF3DMA_control ========
     *  @brief  Function for setting control parameters of the SPI driver
     *          after it has been opened.
     *
     *  @pre    SPILPF3DMA_open() has to be called first.
     *          Calling context: Hwi, Swi, Task
     *
     *  @param  handle A SPI handle returned from SPILPF3DMA_open()
     *
     *  @param  cmd  The command to execute, supported commands are:
     *  | Command                                   | Description                  |
     *  |-------------------------------------------|------------------------------|
     *  | ::SPILPF3DMA_CMD_RETURN_PARTIAL_ENABLE  | Enable RETURN_PARTIAL        |
     *  | ::SPILPF3DMA_CMD_RETURN_PARTIAL_DISABLE | Disable RETURN_PARTIAL       |
     *  | ::SPILPF3DMA_CMD_SET_CSN_PIN            | Re-configure chip select pin |
     *  | ::SPILPF3DMA_CMD_SET_MANUAL             | Enable manual start mode     |
     *  | ::SPILPF3DMA_CMD_CLR_MANUAL             | Disable manual start mode    |
     *  | ::SPILPF3DMA_CMD_MANUAL_START           | Perform a manual start       |
     *  | ::SPILPF3DMA_CMD_SET_SAMPLE_DELAY       | Set a custom DSAMPLE value   |
     *
     *  @param  *arg  Pointer to command arguments.
     *
     *  @return ::SPI_STATUS_SUCCESS if success, or error code if error.
     */
    int_fast16_t SPILPF3DMA_control(SPI_Handle handle, uint_fast16_t cmd, void *arg)
    {
        SPILPF3DMA_Object *object         = handle->object;
        SPILPF3DMA_HWAttrs const *hwAttrs = handle->hwAttrs;
        uint_least8_t pinIndex;
        uint_least8_t sampleDelay;
    
        /* Initialize return value */
        int ret = SPI_STATUS_ERROR;
    
        /* Perform command */
        switch (cmd)
        {
            case SPILPF3DMA_CMD_RETURN_PARTIAL_ENABLE:
                /* Enable RETURN_PARTIAL if peripheral mode is enabled */
    
                if (object->mode == SPI_PERIPHERAL)
                {
                    object->returnPartial = SPILPF3DMA_retPartEnabledIntNotSet;
                    ret                   = SPI_STATUS_SUCCESS;
                }
                else
                {
                    /* Partial return not available in controller mode. */
                    ret = SPI_STATUS_ERROR;
                }
                break;
    
            case SPILPF3DMA_CMD_RETURN_PARTIAL_DISABLE:
                GPIO_setInterruptConfig(object->csnPin, GPIO_CFG_INT_DISABLE);
                object->returnPartial = SPILPF3DMA_retPartDisabled;
                ret                   = SPI_STATUS_SUCCESS;
                break;
    
            case SPILPF3DMA_CMD_SET_CSN_PIN:
                pinIndex = *((uint_least8_t *)arg);
    
                if (pinIndex == GPIO_INVALID_INDEX)
                {
                    /* If trying to disable the CS pin, forward to the CLEAR_CS command and break */
                    ret = SPILPF3DMA_control(handle, SPILPF3DMA_CMD_CLEAR_CSN_PIN, NULL);
                    break;
                }
    
                /* Reset the previous CS pin and configure the new one */
                GPIO_resetConfig(object->csnPin);
                object->csnPin = pinIndex;
                GPIO_setConfigAndMux(object->csnPin, GPIO_CFG_INPUT, hwAttrs->csnPinMux);
    
                ret = SPI_STATUS_SUCCESS;
                break;
    
            case SPILPF3DMA_CMD_CLEAR_CSN_PIN:
                /* If the CS pin is assigned, reset and unassign it */
                if (object->csnPin != GPIO_INVALID_INDEX)
                {
                    GPIO_resetConfig(object->csnPin);
                    object->csnPin = GPIO_INVALID_INDEX;
                }
                ret = SPI_STATUS_SUCCESS;
                break;
    
            case SPILPF3DMA_CMD_SET_MANUAL:
                /* If a transaction is queued, do not modify */
                if (object->headPtr == NULL)
                {
                    object->manualStart = true;
                    ret                 = SPI_STATUS_SUCCESS;
                }
                break;
    
            case SPILPF3DMA_CMD_CLR_MANUAL:
                /* If a transaction is queued, do not modify */
                if (object->headPtr == NULL)
                {
                    object->manualStart = false;
                    ret                 = SPI_STATUS_SUCCESS;
                }
                break;
    
            case SPILPF3DMA_CMD_MANUAL_START:
                if (object->headPtr != NULL && object->manualStart)
                {
                    enableSPI(handle);
                    enableDMA(hwAttrs->baseAddr, SPI_DMACR_TXEN | SPI_DMACR_RXEN);
                    UDMALPF3_channelEnable(hwAttrs->rxChannelBitMask | hwAttrs->txChannelBitMask);
                    ret = SPI_STATUS_SUCCESS;
                }
                break;
    
            case SPILPF3DMA_CMD_SET_SAMPLE_DELAY:
                sampleDelay = *((uint_least8_t *)arg);
    
                if (object->mode == SPI_CONTROLLER && sampleDelay <= (DSAMPLE_MAX_CYCLES >> SPI_CLKCFG1_DSAMPLE_S))
                {
                    /* Cache the value so it is persistent across standby */
                    object->dsample = sampleDelay << SPI_CLKCFG1_DSAMPLE_S;
    
                    HWREG(hwAttrs->baseAddr + SPI_O_CLKCFG1) &= ~SPI_CLKCFG1_DSAMPLE_M;
                    HWREG(hwAttrs->baseAddr + SPI_O_CLKCFG1) |= object->dsample;
                    ret = SPI_STATUS_SUCCESS;
                }
                break;
    
            default:
                /* This command is not defined */
                ret = SPI_STATUS_UNDEFINEDCMD;
                break;
        }
    
        return (ret);
    }
    
    /*
     *  ======== SPILPF3DMA_hwiFxn ========
     */
    static void SPILPF3DMA_hwiFxn(uintptr_t arg)
    {
        uint32_t freeChannel;
        uint32_t intStatus;
        SPI_Transaction *completedList;
        size_t *transferSize;
        volatile uDMAControlTableEntry *rxDmaTableEntry;
        volatile uDMAControlTableEntry *txDmaTableEntry;
        SPILPF3DMA_Object *object         = ((SPI_Handle)arg)->object;
        SPILPF3DMA_HWAttrs const *hwAttrs = ((SPI_Handle)arg)->hwAttrs;
        uint8_t i;
        uintptr_t key;
    
        intStatus = getInterruptStatus(hwAttrs->baseAddr, true);
        clearInterrupt(hwAttrs->baseAddr, intStatus);
    
        if (intStatus & SPI_MIS_RXOVF_SET)
        {
            if (object->headPtr != NULL)
            {
                /*
                 * RX overrun during a transfer; mark the current transfer
                 * as failed & cancel all remaining transfers.
                 */
                object->headPtr->status = SPI_TRANSFER_FAILED;
    
                SPILPF3DMA_transferCancel((SPI_Handle)arg);
            }
            else
            {
                disableSPI(hwAttrs->baseAddr);
    
                /* Disable DMA and clear DMA interrupts */
                disableDMA(hwAttrs->baseAddr, SPI_DMACR_TXEN | SPI_DMACR_RXEN);
                UDMALPF3_channelDisable(hwAttrs->rxChannelBitMask | hwAttrs->txChannelBitMask);
                UDMALPF3_clearInterrupt(hwAttrs->rxChannelBitMask | hwAttrs->txChannelBitMask);
                disableInterrupt(hwAttrs->baseAddr, SPI_INT_ALL);
                clearInterrupt(hwAttrs->baseAddr, SPI_INT_ALL);
    
                /* Clear out the FIFO by resetting SPI module and re-initting */
                flushFifos(hwAttrs);
            }
        }
        else
        {
            UDMALPF3_clearInterrupt(hwAttrs->rxChannelBitMask | hwAttrs->txChannelBitMask);
    
            /*
             * We check both channels for completion; this is done in case the
             * second channel finishes while we are still configuring the first.
             */
            for (i = 0; i < 2; i++)
            {
                if (object->headPtr == NULL)
                {
                    /* When i was 0, we finished the last transaction */
                    break;
                }
    
                if (object->activeChannel == UDMA_PRI_SELECT)
                {
                    transferSize = &object->priTransferSize;
    
                    rxDmaTableEntry = hwAttrs->dmaRxTableEntryPri;
                    txDmaTableEntry = hwAttrs->dmaTxTableEntryPri;
                }
                else
                {
                    transferSize = &object->altTransferSize;
    
                    rxDmaTableEntry = hwAttrs->dmaRxTableEntryAlt;
                    txDmaTableEntry = hwAttrs->dmaTxTableEntryAlt;
                }
    
                /*
                 * The SPI TX FIFO continuously requests the DMA to fill it if there
                 * is space available.  If there are no more frames to put in the
                 * FIFO we run into a situation where DMA TX will cause undesired
                 * interrupts.  To prevent many undesired interrupts disable DMA_TX
                 * if there are no more frames to load into the FIFO & there are no
                 * pending queued transactions.
                 */
                if (UDMALPF3_channelDone(hwAttrs->txChannelBitMask) &&
                    (txDmaTableEntry->control & UDMA_MODE_M) == UDMA_MODE_STOP &&
                    object->framesQueued == object->headPtr->count && object->headPtr->nextPtr == NULL)
                {
                    disableDMA(hwAttrs->baseAddr, SPI_DMACR_TXEN);
                    UDMALPF3_clearInterrupt(hwAttrs->txChannelBitMask);
                }
    
                if ((rxDmaTableEntry->control & UDMA_MODE_M) == UDMA_MODE_STOP && *transferSize != 0)
                {
                    object->framesTransferred += *transferSize;
                    freeChannel           = object->activeChannel;
                    object->activeChannel = (freeChannel == UDMA_PRI_SELECT) ? UDMA_ALT_SELECT : UDMA_PRI_SELECT;
    
                    /*
                     * Set the channel's transfer size to 0; 0 lets
                     * configNextTransfer() know that there is a free channel.
                     */
                    *transferSize = 0;
    
                    if ((object->framesQueued) < (object->headPtr->count) ||
                        (object->framesTransferred) < (object->headPtr->count))
                    {
                        /*
                         * In this case we need to reconfigure the channel to
                         * continue transferring frames. configNextTransfer() will
                         * continue queueing frames for the current transfer or
                         * start the following transaction if necessary.
                         */
                        configNextTransfer(object, hwAttrs);
                        enableDMA(hwAttrs->baseAddr, SPI_DMACR_TXEN | SPI_DMACR_RXEN);
                        UDMALPF3_channelEnable(hwAttrs->rxChannelBitMask | hwAttrs->txChannelBitMask);
                    }
                    else
                    {
                        key                     = HwiP_disable();
                        /*
                         * All data has been transferred for the current
                         * transaction. Set status & move the transaction to
                         * object->completedList. This is required because
                         * object->headPtr is moved to the following transaction.
                         * Also, transaction callbacks are executed in the driver
                         * SWI which will be posted later.
                         */
                        object->headPtr->status = SPI_TRANSFER_COMPLETED;
    
                        if (object->completedTransfers == NULL)
                        {
                            /* List is empty; just add the transaction */
                            object->completedTransfers = object->headPtr;
                            completedList              = object->completedTransfers;
                        }
                        else
                        {
                            /* Traverse to the last element */
                            completedList = object->completedTransfers;
                            while (completedList->nextPtr != NULL)
                            {
                                completedList = completedList->nextPtr;
                            }
    
                            /* Store the completed transaction at end of list */
                            completedList->nextPtr = object->headPtr;
    
                            /*
                             * Make sure we are pointing to the end of the list;
                             * we need to clear references in completed transfer
                             * after we move object->headPtr forward.
                             */
                            completedList = completedList->nextPtr;
                        }
    
                        /* Move the object->headPtr to the next transaction */
                        object->headPtr = object->headPtr->nextPtr;
    
                        /* Clear references in completed transfer */
                        completedList->nextPtr = NULL;
    
                        /* Update object variables for the following transfer. */
                        object->framesQueued      = (object->activeChannel == UDMA_PRI_SELECT) ? object->priTransferSize
                                                                                               : object->altTransferSize;
                        object->framesTransferred = 0;
    
                        HwiP_restore(key);
    
                        if (object->headPtr != NULL)
                        {
                            /* Reconfigure channel for following transaction */
                            configNextTransfer(object, hwAttrs);
                            enableDMA(hwAttrs->baseAddr, SPI_DMACR_TXEN | SPI_DMACR_RXEN);
                            UDMALPF3_channelEnable(hwAttrs->rxChannelBitMask | hwAttrs->txChannelBitMask);
                        }
                        else
                        {
                            /* No more queued transfers; disable DMA & SPI */
                            disableDMA(hwAttrs->baseAddr, SPI_DMACR_TXEN | SPI_DMACR_RXEN);
    
                            /*
                             * For this driver implementation the peripheral is kept
                             * active until either a FIFO-overrun occurs or
                             * SPI_transferCancel() is executed.
                             */
                        }
    
                        /* Post driver SWI to execute transaction callbacks */
                        SwiP_post(&(object->swi));
                    }
                }
            }
        }
    }

  • I am surprised by your SPILPF3DMA.c file as it does not indicate containing the SimpleLink F3 SDK v9.10 workarounds for the UDMA_01 errata.  Can you please confirm your findings using the SPILPF3DMA.c source from F3 SDK v9.10 or v9.11?

    Regards,
    Ryan

  • Hello, Ryan

    I will share the results of my research using the SPILPF3DMA.c source code from F3 SDK v9.10.

    When I checked the operation of SPILPF3DMA with SDK v9.10,
    SPILPF3DMA_hwiFxn was executed two or three times in IAR Debug,
    but SPILPF3DMA_hwiFxn was not executed after the second time in Standalone (on-chip) mode.

    When I checked the operation of SPILPF3DMA with SDK v8.30,
    SPILPF3DMA_hwiFxn was executed the second time even in Standalone (on-chip) mode.

    Regards,

    Sho

  • Hi Sho,

    Can you please provide a project from which I can replicate this?  We can use the private messenger if you are concerned about accessibility.

    Regards,
    Ryan

  • Hello, Ryan

    For now, I'll share the results of my additional investigation.
    Using SPI_DMA with 16 bytes of padding
    Changing the data transfer size from 51 bytes to 64 bytes → 64 bytes sent in debug mode, 48 bytes sent on-chip
    I also checked the register values during on-chip execution
    I confirmed that spi0rxtrg is being used in DMACH0(1)SEL (not uart1txtrg).

    Please wait a moment for the project

    Regards,

    Sho

  • I'm currently preparing to send my project.
    It would be difficult to send the entire project, so I'm thinking of sending just a part of it.
    (I'm thinking of removing the BLE functionality and sending just the SPI functionality.)
    Is that okay?

    Regards,

    Sho

  • The most lightweight project which still demonstrates the issue would be preferred.

    Thanks,
    Ryan