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.

RTOS/OMAP-L138: C6748 DSP: dynamic creating of a UART device using DEV_createDevice fails.

Part Number: OMAP-L138
Other Parts Discussed in Thread: OMAPL138, INA219, TPS65070

Tool/software: TI-RTOS

Hello!

I have to expand an existing project at the C674xDSP of an OMAP-L138 SOC.
My job is to use the on chip UART2 in some cases, not always.
The activation of the UART must be done during run time - so I can't use the static creation of the UART channels via the configuration tool.
The on chip UART2 must be created and deleted perhaps a long time after the system was started.
So I tried to modify the UART example from here
  ...\pspdrivers_01_30_01\packages\ti\pspiom\examples\evmOMAPL138\uart\
but using the dynamic creation of the UART device instead of the example's static creation.
My problem is, that the function DEV_createDevice() never returns SYS_OK but always returns 0x07 (SYS_EMODE).
So the next step function calls of GIO_create() to open Rx and Tx channels also will fail.
 
At the SOC's GPP is running QNX, but the GPP doesn't touch the UART2.
The DSP project is using the packages below:
  DSPBIOS 5.41.03.17
  PSP drivers 01.30.01
  OMAP-L138 DSP package 1.00.00.08
  EDMA3lld package 01.11.00.03

Is there anyone who reviews my code snipe and can tell me whats wrong there in my parameters or in my creation sequence?
Thanks to all!


#include <std.h>
#include <stdio.h>
#include <string.h>
#include <gio.h>
#include <log.h>
#include <tsk.h>
#include <stdio.h>
#include <pwrm.h>
#include <pwrmL138.h>
#include "ti/pspiom/uart/Uart.h"
#include "ti/sdo/edma3/drv/edma3_drv.h"
#include "ti/pspiom/platforms/evmOMAPL138/Uart_evmInit.h"

/*
 * Internal references
 */
static Void genericUartTest(Void);

/*
 * External references
 */
extern LOG_Obj    trace;
extern EDMA3_DRV_Handle hEdma[];/* EDMA handle (Required in EDMA mode) */
extern EDMA3_DRV_Result edma3init();

typedef struct uart2debug_t
  {
  int                 dev_createDevice_result;
  EDMA3_DRV_Result    edmaResult;
  GIO_Handle          gio_create_uart2rx_result;
  GIO_Handle          gio_create_uart2tx_result;
  } uart2debug_t;
uart2debug_t uart2debug;

/*
 * UART0 device params. To be filled in uart0_dev_init function which
 * is called before driver creation
 */
Uart_Params   uart2Params =
  {
  TRUE,                      /* cacheEnable                    */
  TRUE,                      /* fifoEnable                     */
  Uart_OpMode_DMAINTERRUPT,  /* opMode                         */
  FALSE,                     /* loopbackEnabled                */
  Uart_BaudRate_115_2K,      /* baudRate                       */
  Uart_NumStopBits_1,        /* stopBits                       */
  Uart_CharLen_8,            /* charLen                        */
  Uart_Parity_NONE,          /* parity                         */
  Uart_RxTrigLvl_1,          /* rxThreshold                    */
  {                          /* fc                             */
      Uart_FcType_NONE,
      Uart_FcParam_NONE
  },
  0,                         /* edmaRxTC                       */
  0,                         /* edmaTxTC                       */
  9,                         /* hwiNumber                      */
  0xffffffff,                /* polledModeTimeout              */
  1,                         /* softTxFifoThreshold            */
  FALSE,                     /* PSC control disabled           */
  Uart_pllDomain_0           /* PLL domain used by the driver  */
  }; /* uart2Params */

/*
 * Starting message printing string
 * Note: Buffer alignement is required only when working in DMA Mode.
 */
#pragma DATA_ALIGN(uart2TestStringStart, 128);
static Int8 uart2TestStringStart[128];

/* Tx memory buffer */
#pragma DATA_ALIGN(Uart2_TxBuffer, 128);
static Int8  Uart2_TxBuffer[1024];

/* UART handle for input channel */
GIO_Handle hUart2_IN;

/* UART handle for output channel */
GIO_Handle hUart2_OUT;

/**
 * \brief    Initialisation function.
 *           This function initializes the UART driver and also the required
 *           parameters for the creation of the device.
 *
 * \param    None
 *
 * \return   None
 */
void user_uart2_init()
  {
  uart2debug.edmaResult      = 0;

  if (NULL == hEdma[0])
    { /* this branch was never passed... */
    uart2debug.edmaResult = edma3init();
    if (EDMA3_DRV_SOK != uart2debug.edmaResult)
      {
      /* Report EDMA Error */
      LOG_printf(&trace,"\r\nEDMA3 : edma3init() failed\r\n");
      }
    else
      {
      LOG_printf(&trace,"\r\nEDMA3 : edma3init() passed\r\n");
      }
    }
  else
    { /* this branch was always passed... */
    LOG_printf(&trace,"\r\nEDMA3 : edma3init() don't need\r\n");
    }

  // Uart_init();
  uart2Params = Uart_PARAMS;
  uart2Params.hwiNumber = 9;
  uart2Params.opMode = Uart_OpMode_DMAINTERRUPT;
  uart2Params.rxThreshold = Uart_RxTrigLvl_1;
  uart2Params.softTxFifoThreshold = 1;
  Uart_init();

  /* enable the EDMA in the PSC module  */
  PWRM_setDependency(PWRM_RSRC_EDMA3_CC_0);
  PWRM_setDependency(PWRM_RSRC_EDMA3_TC_0);
  PWRM_setDependency(PWRM_RSRC_EDMA3_TC_1);
  PWRM_setDependency(PWRM_RSRC_EDMA3_TC_2);
  } /* user_uart2_init() */

DEV_Attrs uart2devattrs =
  {
  2,               /* .devid = UART2 */
  &uart2Params,    /* .params        */
  DEV_IOMTYPE,     /* .type          */
  NULL             /* .devp          */
  }; /* uart2devattrs */

static void Uart_createdev(void)
  {
  memset(&uart2debug, 0x00, sizeof(uart2debug));
  uart2debug.dev_createDevice_result =
    DEV_createDevice("/UART2", &Uart_IOMFXNS, (Fxn)user_uart2_init, &uart2devattrs);
  if (SYS_OK != uart2debug.dev_createDevice_result)
    { /* function DEV_createDevice() returned 0x07 here (may be SYS_EMODE ?): */
    LOG_printf(&trace, "DEV_createDevice() failed\n");
    }
  else
    { /* this branch was never passed... */
    LOG_printf(&trace, "DEV_createDevice() done\n");
    }

  // if (SYS_OK == uart2debug.dev_createDevice_result)
    {
    GIO_Attrs       gioAttrs      = GIO_ATTRS;
    Int32           echoTskStatus = 0;
    Uart_ChanParams chanParams    = {NULL};
   
    /* Initialize channel attributes.                                         */
    gioAttrs.nPackets = 2;
   
    chanParams.hEdma = hEdma[0];
   
    /* Initialize pinmux and evm related configurations                       */
    configureUart();
   
    /* Initialize UART Currently is been used to display a string              */
    uart2debug.gio_create_uart2tx_result = hUart2_OUT = GIO_create("/UART2", IOM_OUTPUT, NULL,           &chanParams, &gioAttrs);
    uart2debug.gio_create_uart2rx_result = hUart2_IN  = GIO_create("/UART2", IOM_INPUT,  &echoTskStatus, &chanParams, &gioAttrs);
   
    if (NULL == hUart2_IN)
      { /* function GIO_create() always returned NULL here: */
      LOG_printf(&trace, "GIO_createDevice(Rx) failed\n");
      }
    else
      { /* this branch was never passed... */
      LOG_printf(&trace, "GIO_createDevice(Rx) done\n");
      }
    if (NULL == hUart2_OUT)
      { /* function GIO_create() always returned NULL here: */
      LOG_printf(&trace, "GIO_createDevice(Tx) failed\n");
      }
    else
      { /* this branch was never passed... */
      LOG_printf(&trace, "GIO_createDevice(Tx) done\n");
      }
   
    if ((NULL != hUart_IN) && (NULL != hUart_OUT))
      {
      /* Run UART sample application */
      genericUartTest();
   
      /* Exit                                                               */
      SYS_exit(0);
      }
    ShowmemCmdapd(THDUART2HPIMSGQDEV_ID_, (farp_t)(&uart2debug), sizeof(uart2debug), dchar2word('L', 'D'));
    return;
    }
  } /* Uart_createdev() */

/**
 * \brief   Generic read write test
 *
 *          This Function is called to test generic UART test.In this function
 *          basic read/write functionality is tested.
 *
 * \param   None
 *
 * \return  None
 */
static Void genericUartTest(Void)
  {
  Ptr     buf    = NULL;
  Int     status = 0;
  size_t  len    = 0;
  Int8   *str    = NULL;

  LOG_printf(&trace," Starting UART sample application \n\r");

  str = "UART Demo Starts:  INPUT a file of size 1000 bytes";

  /* Copy to start string to Cache aligned buffer                           */
  len = strlen(str);
  memcpy(uartTestStringStart,str,len);

  buf = uartTestStringStart;

  status = GIO_submit(hUart2_OUT,IOM_WRITE, buf, &len, NULL);

  if(!((status == IOM_COMPLETED)||(status == IOM_PENDING)))
  {
      LOG_printf(&trace, "\r\n Error from GIO_write for UART Test string\n");
  }

  buf = Uart_TxBuffer;
  len = 1000u;
  status = GIO_submit(hUart2_IN,IOM_READ,buf,&len,NULL);

  if (!((status == IOM_COMPLETED)||(status == IOM_PENDING)))
  {
      LOG_printf(&trace, "\r\n Error from GIO_read for 1000 bytes read\n");
  }

  buf = Uart_TxBuffer;
  len = 1000u;
  status = GIO_submit(hUart2_OUT,IOM_WRITE,buf,&len,NULL);

  if (!((status == IOM_COMPLETED) || (status == IOM_PENDING)))
  {
      LOG_printf(&trace, "\r\n Error from GIO_write for 1000 bytes write\n");
  }

  LOG_printf(&trace, "UART sample application completed \n\r ");
  } /* genericUartTest */

  • Hi,

    I've notified the RTOS team. Their feedback will be posted here.

    Best Regards,
    Yordan
  • Hi Uwe,

    From the implementation of DEV_createDevice(), I see the only way it can return SYS_EMODE is if it is returning an error from the underlying uart driver's mdBindDev() function. I think this corresponds to uartMdBindDev() in pspdrivers_01_30_01\packages\ti\pspiom\uart\src\Uart.c. Could it be that you have already initialized/used Uart2 (perhaps via static config) elsewhere? Otherwise, you may wish to try stepping into this code in CCS to find out where it exactly went wrong.

    Best regards,
    Vincent
  • Hi Vincent,
    thanks for your tips!
    The static DSP configuration doesn't use any UARTS.
    The GPP RTOS QNX also doesn't know that there is a UART at the address 0x01D0D000. The GPP uses on chip UART0 only.

    I reviewed the function uartMdBindDev() in pspdrivers_01_30_01\packages\ti\pspiom\uart\src\Uart.c.
    The followig conditions may result in returning IOM_EBADMODE:
      condition (1) (TRUE == Uart_module.inUse[devId]) /* this instance is already in use */
        The code lines below I've moved from my function user_uart2_init() to the function Uart_createdev() which
        is calling DEV_createDevice(). So these lines are executed now before the DEV_createDevice() call occurs.
          uart2Params = Uart_PARAMS;
          uart2Params.hwiNumber = 9;
          uart2Params.opMode = Uart_OpMode_DMAINTERRUPT;
          uart2Params.rxThreshold = Uart_RxTrigLvl_1;
          uart2Params.softTxFifoThreshold = 1;
          Uart_init();
          uart2debug.dev_createDevice_result =
            DEV_createDevice("/UART2", &Uart_IOMFXNS, (Fxn)user_uart2_init, &uart2devattrs);
        Calling the function Uart_init() from pspiom\uart\src\Uart.c is clearing the array Uart_module.inUse[].
        Since calling now this initialization before calling DEV_createDevice()
        the condition (1) should never be TRUE.
      condition (2) (Uart_DriverState_DELETED != instHandle->devState) /* this instance is already created elsewhere, its not deleted */
        Calling the function Uart_init() is filling the structures for all instances with 0.
        Since the enum Uart_DriverState_DELETED is 0 the condition (2) should also never be TRUE.
      condition (3) (0 == params->hwiNumber) /* invalid parameter */
        Since calling now my initialization lines before calling DEV_createDevice() this register should
        be already set to 9 and the condition (3) should never be TRUE.
      condition (4) (IOM_COMPLETED != uartValidateParams(params)) /* invalid parameter */
        Since calling now my initialization line
          uart2Params = Uart_PARAMS;
        before calling DEV_createDevice() these registers should contain valid data only
        and so the condition (4) should always be FALSE.

    To review the function DEV_createDevice() was not possible for me because I didn't
    found any source code of this function anywhere in my folders
      bios_5_41_03_17\packages\ti\bios\
      pspdrivers_01_30_01\packages\ti\pspiom

    May be that there is something wrong with the parameters or arguments
     I hand over to the function DEV_createDevice()?

    Does the power management have any impact to creation of a UART device?
     In pspdrivers_01_30_01\packages\ti\pspiom\uart\src\Uart.c there is returned this failure
     in relation to PWRM functions.


    Best regards,

    Uwe

  • Hi Uwe,

    Your parameters seem fine based on the code I see in uartValidateParams().

    Are you using the PWRM module to manage power? '7 'can be returned by PWRM_setDependency as PWRM_ENOTSUPPORTED (see ti/bios/include/pwrm.h), which may be pointing to PWRM not being configured correctly. Please read up on section 1.6 in pspdrivers_01_30_01\docs\OMAPL138\OMAPL138_BIOSPSP_Userguide.pdf as it contains information on Power Management and how to enable the PWRM module in the TCF file.

    Best regards
    Vincent
  • Hi Vincent,

    sorry for the days I didn't response to your latest post.

    I made the modifications below:

    (1) In my application code's structure uart2params I changed

        the PLL domain from Uart_pllDomain_0 to Uart_pllDomain_1 (since using UART2)

    (2) In the PSP's UART device driver uart.c now I ignore the results of calling the

        functions PWRM_setDependency() and PWRM_releaseDependency().

        Both functions return the 0x07 always (by the way, calls of the function

        PWRM_setDependency() for the EDMA in my application code's function

        user_uart2_init() also return 0x07 always).

        However, now the the PSP's functions uartMdBindDev() and uartMdUnBindDev()

        don't store anymore the return value of PWRM_setDependency() and PWRM_releaseDependency()

        calls into the variable retVal. Since I made this retVal keeps the value IOM_COMPLETED,

        uartMdBindDev() / uartMdUnBindDev() continue regular,

        and my application is able to access the UART via the APIs GIO_create(),

        GIO_delete(), GIO_submit() in EDMA-mode and Interrupt-mode both.

     

    Do you know what may cause the return value 0x07 when calling the

        functions PWRM_setDependency() and PWRM_releaseDependency()?

        I've not found the source code of this functions in the DSPBIOS folders.

        Does ignoring of the failure indication 0x07 have any impact to the UARTs,

        to the SOC's PLL, to the SOC's power management, ...?

     

    Best regards,

    Uwe

     

  • Hi Uwe,

    Did you read section 1.6 in pspdrivers_01_30_01\docs\OMAPL138\OMAPL138_BIOSPSP_Userguide.pdf as I suggested? It talks about the BIOS_PWRM_ENABLE flag. Depending on whether you set this flag or not, you either have to modify the tcf file to enable PWRM module in the TCF file, or just use the BIOSPSP PSC driver. I wouldn't have expected you to have to make changes to the UART driver code itself.

    As I mentioned in my previous message, 0x7 means PWRM_ENOTSUPPORTED.  The BIOS API guide (in <BIOS installation dir>/docs/spru403s.pdf) P.359 defines this as "The operation failed because resource tracking is not enabled." So please make sure if you do pass the BIOS_PWRM_ENABLE flag to the compiler that you also modify the tcf file of your application accordingly to enable PWRM and resource tracking.

    Best regards,

    Vincent

  • Hi Vincent,

    I agree with you that any modification in the UART driver's code should not be the way to get my application running. It was a just a temporary modification as a way for me to try to understand what happens here and to find the point to leverage this problem. I would prefer any modification in my application's code to avoid the error result of DEV_createDevice() function.

    However, you gave the tip to check if the PWRM module is enabled. I'm sorry that I've not yet mentioned that my tcf file disables the DSP-BIOS's power management PWRM. The power resource manager is set to

    bios.PWRM.ENABLE = 0;

    I tried to use the settings from the UART sample tcf file

    bios.PWRM.ENABLE = 1;

    bios.PWRM.RESOURCETRACKING = 1;

    bios.PWRM.SCALING = 1;

    But with this tcf setting my application doesn't start any more at our current target board. I guess the reason for this behavior is the different power supply at our board. LogicPD's SOM-M1 module is using the ICs TPS65070 with INA219 for power supply and monitoring. Our SOM-RP1 is using LTC3545 (5.0V -> 1.8V, 3.3V) and LTC3542 (5.0V -> 1.2V). Since using these both power supply ICs without any I2C interfaces I guess the DSP-BIOS's PWRM APIs don't run. So I had to fall back to the tcf setting

    "bios.PWRM.ENABLE = 0".

    Our target boards are in the field since seven years and I can't suggest any hardware modifications to my management now. The previous versions of application software over the last years where running without the DSP-BIOS power resource manager PWRM. So I must find a way to run the UART2 also without the PWRM module.

     

    To force the UART driver using the PSP's PSC APIs instead of DSP-BIOS's PWRM I tried to build the UART driver without the BIOS_PWRM_ENABLE flag. Now the header file UartLocal.h denied the built of the UART driver with the flag combination of CHIP_C6748 or CHIP_OMAPL138 without the BIOS_PWRM_ENABLE flag (UartLocal.h, line 25). To avoid this I changed the preprocessor command from

    #error "Use Bios PWRM module only for the SoC"

    to

    #warn "Use Bios PWRM module only for the SoC"

    Now the built is done, DEV_createDevice() and GIO_create() are running without returning any error, and I can transmit/receive chars via UART2.

     

    But I think the guys who wrote the header file UartLocal.h had a reason to deny the built of OMAPL138 SoC without the PWRM module. In the "OMAPL138 BIOS PSP User Guide" at page 21, chapter "1.6.1 Module clock gating" there is also a note to use the BIOS power management PWRM only...

    Can you find out what was the reason for doing this?

    Does bypassing this denial in the UART driver's header file result in any other trouble anywhere else?

    I can't step through the PWRM module's functions because this source code is not available for me. Is there any way to bypass the I2C access to the power supply / monitoring by the PWRM module? May be around tcf settings "bios.PWRM.RESOURCETRACKING" and/or "bios.PWRM.SCALING"?

     

    Thank you for your patience,

    Uwe

     

  • Hi Uwe,

    Thanks for clarifying your use-case. This thread covers the same issue (it refers to the SPI driver, but the story is the same with UART):

    It sounds like the driver was simply not validated in that mode, but others have been down the same path, FWIW. That is probably the better alternative given your system has been working with PWRM disabled.

    Best regards,

    Vincent

  • There was a suggested answer and since there has been no active on this thread for more than a week, the suggested answer was marked as verify. Please feel free to select the "Reject Answer" button and reply with more details.
  • Hi Vincent,

    the UART driver's code, build without the BIOS_PWRM_ENABLE flag, is running now in our lab without any problems around the power management.  So I think I am going on without a formal validation of that mode and we can close this thread.

    There is only still some trouble around lost characters on the receiver channel in EDMA-mode.

    If there are received less characters than the buffer's size allows and the timeout for successive characters occured I've not yet found a way to get an information how many characters were received before the timeout aborted the GIO_submit() / GIO_read() call. If the GIO_submit() / GIO_read() call returns IOM_COMPLETED the function received the number of characters according to the given limit. In this case the length-parameter is set to the given max number of characters and everything is fine. But in the case of the GIO_submit() / GIO_read() call returns IOM_ETIMEOUT or IOM_ETIMEOUTUNREC the length-parameter is set to the 0 always by the DSP-BIOS's GIO_submit() function - altough there are received some characters less than the length-parameter allowed and altough these characters are stored in the buffer.

    The return value IOM_ETIMEOUTUNREC is caused by the DSP-BIOS's GIO_submit() function. In the case when the GIO_submit() function's call to GIO->SEMPEND() function timed out the length-parameter is set to 0 always. Aftwe that the GIO_submit() function calls the mini driver's mdControlChan function with the command ID IOM_CHAN_TIMEDOUT. Because the UART's mini driver doesn't know this command ID the mini driver's  mdControlChan function returns IOM_ENOTIMPL. This results in the DSP-BIOS's GIO_submit() function is returning IOM_ETIMEOUTUNREC... It's not fine but I can deal with with this behavior. Another thing is that the DMA and the UART keep still active and there is not performed any operation to stop the IO. My application layer's work around is to call GIO_control() with the command ID Uart_IOCTL_CANCEL_CURRENT.

    However, my problem in any case is that I have to process all received characters - also in the case of timeout. Since the baud rate is 230400 for a single character receive the CPU load would be increased. So I prefer the DMA mode or at least the FIFO mode of the UART driver. But how to get an information how many bytes are received before the timeout occured?

    I've just tried to modify the UART driver's source code. So I've add the command ID IOM_CHAN_TIMEDOUT to the driver's function uartMdControlChan(). If this command ID is parsed I stop the current IO by running a sequence according to that one if the buffer full event occured. Here I have the access to the number of characters received before, but from the mini driver's point of view there is no way to give this information up to the DSP_BIOS's GIO_submit() function or up to the application layer. Of course, the better way would be to keep the UART driver "as is" and to get the number of received charactes to the application via another way...

     

     Best regards,

    Uwe

  • Hi Uwe,

    Glad to hear you got the UART code to build and resolved your original issue with DEV_createDevice().

    For this other issue regarding lost characters, could you please start a new thread? This would expedite its resolution and help others refer to it later.


    Thanks,

    Vincent