Configure UART to originate Requests/act like master

I have a UART terminal device that had flow control aspect to it.

My logic written in Java works great from PC and reads from terminal device board just fine. Same logic from FASTRACK Supreme in AT is posing Supreme as a slave device (request shows up as response). What Can I do to make the AT application configure UART as master to originate or send out requests. I know it is around CTS/RTS setting but not exactly what. I would appreciate the help.

s32             handle;
	sUartSettings_t Settings;
	psGItfCont_t    pinterface;
	sUartEvent_t    events;
	sUartLc_t       lc;
	sUartFlowCtrl_t Fc;

	TRACE (( 1, "uart_open(UART%c,%d)",identity[4], speed ));
	/* Device */
	Settings.capabilities = NULL;
	Settings.identity = identity;
	Settings.role = UART_ROLE_DCE;
	/* 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;

	/* 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 | 2400 );
	lc.stop         = UART_STOP_BIT_1;
	lc.parity       = UART_PARITY_EVEN;
	lc.data         = UART_DATALENGTH_7;

	Settings.line_coding = &lc;

	/*------------------*/
	/* open UART device */
	/*------------------*/
	if( 0 < (handle = adl_OpenDevice( DF_UART_CLID, &Settings)) )
	{
		TRACE(( 1, "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;
		//Fc.type = UART_FC_NONE;

		if( uart_itf.io_control( handle, IOC_UART_FC, (void*) &Fc) )
		{
			uart_itf.close( handle );
			TRACE((1, "ERROR : IOCTL FC Set"));
			handle = 0;
		}


		sUartSsIoc_t sigSetting;
		sigSetting.op = G_IOC_OP_SET;
		sigSetting.sig_id = UART_SIG_CTS;
		sigSetting.state = UART_SIG_CTS;
		if( uart_itf.io_control( handle, IOC_UART_SS, (void*) &sigSetting) ) {
			TRACE((1, "ERROR : IOCTL CTS Set"));
		}

	}
	else
	{
		TRACE(( 1, "Uart_Open : ERROR UART is not opened" ));
	}
	return handle;

I get following errors and data is not being transmitted from FASTRACK to my terminal device:

10/01/29,02:43:10:140 LLH 1 EVENT : SIG CHANGE delta 4 state 0

Thanks,
Haiden

Hi Haiden

I received your email.

I had to dig the code up again, as the project is on standby at the moment :slight_smile:
I’m attaching a piece of my code, which shows the setup of my uart2, and the way I can control my RTS/CTS pin.
Hope it helps.

I’m using a Q2687, by the way, on a custom made pcb and not a Fastrack.
I needed the feature to control receive/transmit on a RS485 transceiver SN65HVD1781 connected to uart2.

Can you describe your project?

[attachment=0]SerialTask2.zip[/attachment]

Regards
Palsson

Looks like there is an issue with your ZIP file.

My project involves reading data from a custom PCB using Fastrack Supreme embedded Open AT application.

Can you please repost your ZIP file?

Thanks,
Haiden

Hi again

Funny.
The link works fine for me.

Try again…

I can download the file but can’t unzip it with any of the unzip tools? See if you send it to my email or post the contents here.
Thanks,
Haiden

zip-file is broken. (unexpected end of file)

Strange!

I’ll post the code here:

/*
 * SerialTask2.c
 *
 *  Created on: 16-07-2009
 *      Author: Palsson
 */

// ADL interface global header
#include "adl_global.h"
#include "wm_uart.h"
#include "utils/ringbuf.h"
#include "Global.h"


#define	UART2_PORT_TYPE		ADL_AT_PORT_TYPE(ADL_AT_UART2,FALSE)
#define	SERIAL2_BUFFER_SIZE	1024

adl_ioDefs_t rs485TermPin;
s32 uart2PortHandler;
u8 serial2Buffer[SERIAL2_BUFFER_SIZE];
ascii serial2WorkingBuffer[SERIAL2_BUFFER_SIZE];
tRingBufObject s2RingBufObject;
s32 dataReadyEvent;
s32 txDoneEvent;
xMessageStructure s2MsgPackage;

#define	TEST_LNG	23
static const ascii* testString = "Testing RS485 Interface";
u8 rs485Testing;
adl_ctxID_e rs485TaskID;
extern u8 globalTesting;

static sUartSsIoc_t ioCtrlSend,ioCtrlRecv;
static sGItfCont_t serial2Interface;

#define	RECV_ENABLE(_X_)	serial2Interface.io_control( _X_, IOC_UART_SS, (void*) &ioCtrlRecv)
#define	SEND_ENABLE(_X_)	serial2Interface.io_control( _X_, IOC_UART_SS, (void*) &ioCtrlSend)

#define	SendString(_X_)		adl_atSendResponse(ADL_AT_PORT_TYPE(ADL_AT_UART1,ADL_AT_RSP),_X_)

extern adl_ioDefs_t myIODefs[NUM_OF_GPIO];
extern s32 ioHandle;
extern s32 semaphoreRingBuf;

static void CallBack_OnTxComplete( void* user_data, psUartCbOtxC_t psOnTxParam );
static void CallBack_OnRxDataAvailable (void* user_data, void* ev_param);

/* Call-back table */
static const sGCbDesc_t uartCbTab[] =
{
     /* user data */                      /* Call-backs */
   { (void*)UART_CB_ON_TX_COMPLETE,       (pGEvtNotif_t)&CallBack_OnTxComplete		},
   { (void*)-1L,                          (pGEvtNotif_t)NULL                   		},
   { (void*)UART_CB_ON_RX_DATA_AVAILABLE, (pGEvtNotif_t)&CallBack_OnRxDataAvailable	},
   { (void*)-1L,                          (pGEvtNotif_t)NULL                   		},
   { (void*)-1L,                          (pGEvtNotif_t)NULL                   		},
   { (void*)-1L,                          (pGEvtNotif_t)NULL                   		}
};


/***************************************************************************/
/* Uart Callbacks                                                          */
/***************************************************************************/
static void CallBack_OnTxComplete( void* user_data, psUartCbOtxC_t psOnTxParam ){
    /* set Tx event */
    adl_eventSet( dataReadyEvent, TX_EVENT_WAIT_MASK );
	return;
}

static void CallBack_OnRxDataAvailable (void* user_data, void* ev_param){
    /* set Rx event */
	adl_eventSet(dataReadyEvent, RX_EVENT_WAIT_MASK);
	return;
}

u16 Serial2_CompareTestString(){
	u16 ringBufLength,workerLength;

	memset(serial2WorkingBuffer,0,SERIAL2_BUFFER_SIZE);
	ringBufLength = RingBufUsed(&s2RingBufObject);
	RingBufRead(&s2RingBufObject,(u8*)serial2WorkingBuffer,ringBufLength);
	RingBufFlush(&s2RingBufObject);
	serial2WorkingBuffer[ringBufLength] = 0;
	workerLength = wm_strlen(serial2WorkingBuffer);

	if(wm_strncmp(serial2WorkingBuffer,testString,TEST_LNG) != OK){
		SendString("RS485 - ERROR String Compare\n\r");
	}else{
		SendString("RS485 - OK String Compare\n\r");
	}
	return workerLength;
}

u16 Serial2_CreateSample(){
	u16 ringBufLength,workerLength;

	SendString("Serial2_CreateSample\n\r");

	memset(serial2WorkingBuffer,0,SERIAL2_BUFFER_SIZE);
	wm_sprintf(serial2WorkingBuffer,"<sample><runningHours><00:00></runningHours><message>");
	workerLength = wm_strlen(serial2WorkingBuffer);
	ringBufLength = RingBufUsed(&s2RingBufObject);
	RingBufRead(&s2RingBufObject,(u8*)&serial2WorkingBuffer[workerLength],ringBufLength);
	RingBufFlush(&s2RingBufObject);

	workerLength = workerLength + ringBufLength;
	wm_sprintf(&serial2WorkingBuffer[workerLength],"</message></sample>");
	workerLength = strlen(serial2WorkingBuffer);
	return workerLength;
}

void Serial2_PortHandlerStart(){
	u16 sampleLength;
	u16 nb_read;
	ascii chr[2];

	rs485TaskID = adl_ctxGetID();

	for(;;){
		if(rs485Testing||globalTesting){
			SEND_ENABLE(uart2PortHandler);
			serial2Interface.write(uart2PortHandler,(u8*)testString,TEST_LNG);
			if(adl_eventWait(dataReadyEvent,TX_EVENT_WAIT_MASK,NULL,ADL_EVENT_WAIT_ANY,ADL_EVENT_NO_TIMEOUT) == OK){
				adl_eventClear (dataReadyEvent, TX_EVENT_WAIT_MASK, NULL);
				adl_ctxSleep(10);
				RECV_ENABLE(uart2PortHandler);
			}

			if(adl_eventWait(dataReadyEvent,RX_EVENT_WAIT_MASK,NULL,ADL_EVENT_WAIT_ALL,ADL_EVENT_NO_TIMEOUT) == OK){
				adl_eventClear (dataReadyEvent, RX_EVENT_WAIT_MASK, NULL);
				nb_read = serial2Interface.read( uart2PortHandler, chr, 1);
				while(nb_read > 0){
					if(chr[0] != '\r'){
						if(adl_semConsume(semaphoreRingBuf) == OK){
							RingBufWriteOne(&s2RingBufObject,chr[0]);
							adl_semProduce(semaphoreRingBuf);
						}
					}else{
						sampleLength = Serial2_CompareTestString();
					}
					nb_read = serial2Interface.read( uart2PortHandler, chr, 1);
				}
			}
		}else{
			SendString("RS485 Task Suspended\n\r");
			adl_ctxSuspend(rs485TaskID);
			SendString("RS485 Task Resumed\n\r");
		}
	}

	return;
}


s32 Serial2_OpenUartInterface(){
	s32 handle;

	sUartSettings_t Settings;
	psGItfCont_t    pinterface;
	sUartEvent_t    events;
	sUartLc_t       lc;
	sUartFlowCtrl_t Fc;

	/* Events */
	events.user_data 	= (void*)0;
	events.valid_cb 	= UART_CB_ON_RX_DATA_AVAILABLE | UART_CB_ON_TX_COMPLETE;// | UART_CB_ON_TX_EMPTY;
	memcpy((u8*)events.cb_list, (u8*)uartCbTab, 6*sizeof(sGCbDesc_t));

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

	/* Device */
	Settings.capabilities = NULL;
	Settings.identity = "UART2";
	Settings.role = UART_ROLE_NM;
	Settings.event_handlers = &events;
	Settings.interface = &pinterface;	/* To retrieve the UART SP Interface */
	Settings.line_coding = &lc;

	handle = adl_OpenDevice( DF_UART_CLID, &Settings );
	if( !handle ){
		adl_atSendResponse(ADL_AT_RSP, "\r\nError\r\n");
		// UART2 opening failed...
		return (s32)NULL;
	}

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

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

    if( serial2Interface.io_control( handle, IOC_UART_FC, (void*) &Fc) ){
		serial2Interface.close( handle );
		adl_atSendResponse(ADL_AT_RSP, (char*)"ERROR : IOCTL FC Set\n\r" );
		handle = 0;
		return (s32)NULL;
	}

    /* Initiate control variables */
	ioCtrlRecv.op = G_IOC_OP_SET;
	ioCtrlRecv.sig_id = UART_SIG_RTS;
	ioCtrlRecv.state = UART_SIG_RTS;

	ioCtrlSend.op = G_IOC_OP_SET;
	ioCtrlSend.sig_id = UART_SIG_RTS;
	ioCtrlSend.state = 0;

	//Set device ready for receiving data
    if(RECV_ENABLE(handle)){
    	serial2Interface.close( handle );
    	adl_atSendResponse(ADL_AT_RSP, (char*)"ERROR : IOCTL Set RTS\n\r" );
		handle = 0;
		return (s32)NULL;
    }

/*
    while(1){
//    	ioCtrlRecv.op = G_IOC_OP_SET;
//    	ioCtrlRecv.sig_id = UART_SIG_RTS;
//    	ioCtrlRecv.state = 0;
//		if( serial2Interface.io_control( handle, IOC_UART_SS, (void*) &ioCtrlRecv) ){
//			adl_atSendResponse(ADL_AT_RSP, (char*)"ERROR : IOCTL Set CTS\n\r" );
//			handle = 0;
//		}
		adl_ctxSleep(10);

    	SEND_ENABLE(handle);

		adl_ctxSleep(10);

//		ioCtrlSend.op = G_IOC_OP_SET;
//		ioCtrlSend.sig_id = UART_SIG_RTS;
//		ioCtrlSend.state = UART_SIG_RTS;
//		if( serial2Interface.io_control( handle, IOC_UART_SS, (void*) &ioCtrlSend) ){
//			adl_atSendResponse(ADL_AT_RSP, (char*)"ERROR : IOCTL Set RTS\n\r" );
//			handle = 0;
//		}

    	RECV_ENABLE(handle);

    }
*/
	return handle;
}

void SerialTask2(void){

	SendString("[Serial Task 2] Multitasking\n\r");

    rs485TermPin = myIODefs[RS485_TERM];

    //Activate RS485 Termination
    adl_ioWriteSingle(ioHandle,&rs485TermPin,TRUE);

	RingBufInit(&s2RingBufObject,serial2Buffer,SERIAL2_BUFFER_SIZE);
	dataReadyEvent = adl_eventCreate(INIT_TX_RX_MASK);
	//txDoneEvent = adl_eventCreate(0);

	uart2PortHandler = Serial2_OpenUartInterface();

	Serial2_PortHandlerStart();
}

I connect rs485 (ic max 3483) to uart2 and write driver with use uart acsess sample. but i found some problem

  1. data transfered dont correctly, last byte is truncated
    i control max 3483 with GPIO, with uart event UART_CB_ON_TX_COMPLETE

i dont no how to solve this problem, help me

Do you think that’s the correct event?

Have you checked what’s happening using an oscilloscope?

avaiable only

UART_CB_ON_TX_COMPLETE,
UART_CB_ON_RX_COMPLETE,
UART_CB_ON_RX_DATA_AVAILABLE
UART_CB_ON_SIG_STATE_CHANGE
UART_CB_ON_ERROR

events
I have not ocsiloscope

I send string " rs485 open" and see on terminal on computer only " rs485 ope" and 0xFE code on the end of string

Check again - you’ve missed one!

An oscilloscope is an essential tool for this kind of development; otherwise you are “blind” - as you cannot see what is actually happening!

Or, at least, a serial comms tester that allows you to view the signal states…

On TX Empty event use ?

Look at the descriptions of the two TX events - what do you think…?

I see the two TX events

4.1.4.6 The On TX Complete notification handler
This notification allows the application to be aware of the completion of the pending
asynchronous write operation. It occurs when the last byte, of the previously
submitted data block, is being transmitted by the UART service provider.
Before being notified the application shall open the UART service provider (must own
the UART SP interface as well as a valid UART SP handle) and configure the UART
service provider with its On TX Complete notification handler.
• Prototype
void on_txc (void* user_data, psGData_t evt_param);
• Parameters
user_data:
Generic 32 bits information the application previously provided during the
event handler configuration. The UART service provider is required to give
back this information to the application on every occurrence of the
transmission completion.
evt_param:
Address of a sGData_t structure allowing the application to provide the
UART service provider with address and size parameters of a new data
block to be transmitted. In case application does not have any more data
block to be transmitted it shall set the buf and len fields of the sGData_t
structure to a NULL value.
• Returned values
Not Applicable.

4.1.4.7 The On TX Empty notification handler
This notification allows the application to be aware of the completion of the pending
asynchronous write operation. It occurs when the last bit, of the previously submitted
data block, is being transmitted by the UART service provider.
Before being notified the application shall open the UART service provider (must own
the UART SP interface as well as a valid UART SP handle) and configure the UART
service provider with its On TX Empty notification handler.
• Prototype
void on_txe (void* user_data, psGData_t evt_param);
• Parameters
user_data:
Generic 32 bits information the application previously provided during the
event handler configuration. The UART service provider is required to give
back this information to the application on each transmitter empty
notification.
evt_param:
Address of a sGData_t structure allowing the application to provide the
UART service provider with address and size parameters of a new data
block to be transmitted. In case application does not have any more data
block to be transmitted it shall set the buf and len fields of the sGData_t
structure to a NULL value.
Returned values
Not Applicable.


the 2 event is identical, it is error ??

No, they aren’t; look again, carefully:

I am use event on tx complete and on tx empty but, end byte is 0xfe ((

Surely, you don’t want to use them both :question:

Choose either one or the other :exclamation: