Troubleshooting the Open UART interface on the SL6087

Hey,

I’m having trouble with the UART interface on the SL6087. Prototype code created from the UART demo code that streams data over UART2 on the Q2687 causes an exception reset on the SL6087 after a few seconds of streaming data. I know that wise folks on the forum suggest using FCM over UART access, but I need CTS flow control to manage data to the walnut sized buffer on a slave device and data transfer rate is an issue.

I’m using an SL6087 with version 7.45 firmware. Data is sent over UART2, in mode, at 115200 baud. Have I missed something? Any ideas?

Thanks,
David

Code in question:

#include <string.h>

#include "adl_global.h"

#include "wm_uart.h"

#include "adl_AppliInit.h"
#include "adl_event.h"
#include "adl_traces.h"
#include "adl_OpenDevice.h"
#include "wm_list.h"
#include "adl_port.h"
#include "adl_str.h"
#include "adl_at.h"
#include "adl_CmdHandler.h"
#include "adl_RspHandler.h"

/***************************************************************************/
/*  Local functions                                                        */
/***************************************************************************/

/* callbacks declaration */
static void uart_OnError( void* user_data, void* ev_param);
static void uart_OnSigStateChange( void* user_data,  psUartCbOssc_t psSigState );
static void uart_OnRxDataAvailable( void* user_data, void* ev_param);
static void uart_OnTxComplete( void* user_data, psUartCbOtxC_t psOnTxParam );

/***************************************************************************/
/*  Mandatory variables                                                    */
/*-------------------------------------------------------------------------*/
/*  wm_apmCustomStackSize                                                  */
/*-------------------------------------------------------------------------*/
/***************************************************************************/
const u16 wm_apmCustomStackSize = 1024*3;

/***************************************************************************/
/*  Local constants                                                      */
/***************************************************************************/
#define RX_EVENT_WAIT_MASK      1 //corresponding to RX DATA AVAILABLE
#define TX_EVENT_WAIT_MASK      2 //corresponding to TX COMPLETE

#define INIT_TX_RX_MASK TX_EVENT_WAIT_MASK

#define DATA_MAX 512


/* callback table */
static const sGCbDesc_t uartCbTab[] =
{
     /* user data */                      /* callbacks */
   { (void*)UART_CB_ON_TX_COMPLETE,       (pGEvtNotif_t)&uart_OnTxComplete    },
   { (void*)-1L                ,          NULL                                },
   { (void*)UART_CB_ON_RX_DATA_AVAILABLE, &uart_OnRxDataAvailable             },
   { (void*)UART_CB_ON_SIG_STATE_CHANGE,  (pGEvtNotif_t)&uart_OnSigStateChange},
   { (void*)UART_CB_ON_ERROR,             &uart_OnError                       },
   { (void*)-1L,                          NULL                                }
};

sUartFlowCtrl_t Fc;


/***************************************************************************/
/*  Local variables                                                        */
/***************************************************************************/
static sGItfCont_t uart_itf;
static s32         uart_handle;

int	dataTextPos = 0;
// data buffer prototype
char 	dataText[] =
"1B2A606c00000030aaaaaa924aaaaaaaaaaaaaaaaaaaaaaaeb6aaab76f7b5000";

/***************************************************************************/
/* Uart Callbacks                                                          */
/***************************************************************************/
void uart_OnTxComplete( void* user_data, psUartCbOtxC_t psOnTxParam )
{
    /* reset all : no more data to be send here */
    psOnTxParam->buf = NULL;
    psOnTxParam->len = 0;

    /* set Tx event */
    adl_atSendResponse ( ADL_AT_UNS, "TxComplete");
}

void uart_OnRxDataAvailable (void* user_data, void* ev_param)
{
   adl_atSendResponse ( ADL_AT_UNS, "RxDataAvailable");
}

void uart_OnSigStateChange (void* user_data,  psUartCbOssc_t psSigState)
{
    char 				temptext[100];
	memset(temptext, 0x00, sizeof(temptext));
	sprintf(temptext, "EVENT : SIG CHANGE delta %x  state %x",psSigState->delta,psSigState->state);

	adl_atSendResponse ( ADL_AT_UNS, temptext);
}

void uart_OnError (void* user_data, void* ev_param)
{
    char 				temptext[100];
	memset(temptext, 0x00, sizeof(temptext));
	sprintf(temptext, "EVENT : ERROR %x",(u32)ev_param);

	adl_atSendResponse ( ADL_AT_UNS, temptext);
}

void printer_TimerHandler(u8 ID, void * Context )
{
	char 				temptext[100];
	u8					tempChars[100];
	u32					serialDataLength = 16;

	memset(temptext, 0x00, sizeof(temptext));
	memset(tempChars, 0x00, sizeof(tempChars));

	memcpy(temptext, &dataText[dataTextPos], (serialDataLength * 2));
	wm_hexatoibuf (tempChars, temptext );

	sprintf(temptext, "\r\nPrinting line: %d\r\n",dataTextPos);
	adl_atSendResponse ( ADL_AT_UNS, temptext);

	memset(temptext, 0x00, sizeof(temptext));
	memcpy(temptext, &dataText[dataTextPos], (serialDataLength * 2));
	adl_atSendResponse ( ADL_AT_UNS, temptext);

    if ( -1 != uart_itf.write(uart_handle, tempChars, serialDataLength) )
	{
	dataTextPos =dataTextPos + (serialDataLength * 2);
	} else {
		adl_atSendResponse ( ADL_AT_UNS, "ERROR write !");
	}
	if (dataTextPos < 64) 	adl_tmrSubscribe ( FALSE, 2, ADL_TMR_TYPE_TICK, printer_TimerHandler );
}

void adl_main( adl_InitType_e InitType )
{
   sUartSettings_t Settings;
   psGItfCont_t    pinterface;
   sUartEvent_t    events;
   sUartLc_t       lc;

   adl_atSendResponse ( ADL_AT_UNS, "Program start\r\n" );

   adl_atSendResponsePort(ADL_AT_RSP,ADL_PORT_UART2,"UART 2\r\n");

   /* Device */
   Settings.capabilities = NULL;
   Settings.identity = "UART2";
   Settings.role = UART_ROLE_NM;
   /* Events */
   events.user_data = (void*)0;
   events.valid_cb = UART_CB_ON_ALL;
   memcpy((u8*)events.cb_list, (u8*)uartCbTab, 6*sizeof(sGCbDesc_t));
   Settings.event_handlers = &events;
   //Settings.event_handlers = NULL;

   /* To retrieve the UART SP Interface */
   Settings.interface = &pinterface;

   /* Line Coding */
   lc.valid_fields = UART_LC_ALL;
   lc.rate         = (eUartRate_t)(UART_RATE_USER_DEF | 115200 );
   lc.stop         = UART_STOP_BIT_1;
   lc.parity       = UART_PARITY_NONE;
   lc.data         = UART_DATALENGTH_8;

   Settings.line_coding = &lc;

   /*------------------*/
   /* open UART device */
   /*------------------*/
   uart_handle = adl_OpenDevice( DF_UART_CLID, &Settings);
   if(0 < uart_handle)
   {
      adl_atSendResponse ( ADL_AT_UNS, "UART successfully opened" );

      /* Locally store the uart interface */
      uart_itf = *pinterface;

      /* Flow control IO control setting */
      Fc.op   = G_IOC_OP_SET;
      Fc.type = UART_FC_RTS_CTS;

      if( uart_itf.io_control( uart_handle, IOC_UART_FC, (void*) &Fc) )
      {
    	  uart_itf.close( uart_handle );
    	  adl_atSendResponse ( ADL_AT_UNS, "ERROR : IOCTL FC Set");
    	  uart_handle = 0;
      }
      /*
      switch( uart_itf.io_control( uart_handle, IOC_UART_EH, (void*) &events) )
      {
      case CH_STATUS_ERROR:
    	  uart_itf.close( uart_handle );
    	  adl_atSendResponse ( ADL_AT_UNS, "ERROR : CH_STATUS_ERROR");
    	  uart_handle = 0;
    	  break;
      case CH_STATUS_NORMAL:
    	  adl_atSendResponse ( ADL_AT_UNS, "Flow control events subscribed");
    	  break;
      default:
    	  adl_atSendResponse ( ADL_AT_UNS, "default");
    	  break;
      }
      */
   }
   else
   {
      adl_atSendResponse ( ADL_AT_UNS, "Uart_Open : ERROR UART is not opened" );
   }
   adl_tmrSubscribe ( FALSE, 50, ADL_TMR_TYPE_100MS, printer_TimerHandler );
}

CTS Flow control should work with FCM - you should just need to enable it with the appropriate AT command before switching to Data mode…

Argh! AT commands make me feel dirty. Why can’t Open UART just work?!? Baud rates are also now difficult to modify. But it works and will serve till I can find out what is wrong.

awneil, thanks, I owe you a beer. :smiley:

D