This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: hal_diag serial driver: using XON/XOFF flow control?


I now believe the simple answer to my question is: "Implement the XON/XOFF flow control inside the HAL driver."

Because some people were asking, I'm posting my implementation.



// Theory of XON/XOFF support in the HAL diag driver // Even if the HAL driver has interrupts enabled, they're only for CTRLC character reception. // They can not be used to buffer incoming text characters, because /dev/haldiag isn't made // to do that. // So if you activate interrupts for the hal diag driver, it means that you will lose incoming // text characters. If you do want them, don't activate interrupts, but poll instead. (maybe // a CTRLC check is needed in the polling routine? Didn't check that.) // This also means that we can receive XON/XOFF characters here and let the HAL driver itself do // flow control for transferred data (instead of inside the serial device driver).

#define HAL_IO_SERIAL_FLOW_CONTROL_XON_CHAR 17
#define HAL_IO_SERIAL_FLOW_CONTROL_XOFF_CHAR 19

typedef struct {
   cyg_int32 msec_timeout;
   int isr_vector_rx;
   volatile bool throttle_tx;
} channel_data_t;

static int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...);
static cyg_bool cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch);

void
cyg_hal_plf_serial_putc(void *__ch_data, char c)
{
   channel_data_t* chan = (channel_data_t*)__ch_data;
   CYGARC_HAL_SAVE_GP();

	if(chan->throttle_tx==true)
	{
		// Wait for XON. To be safe against race conditions, turn off interrupts
		// and poll RX from here.
		char chdum;
		cyg_hal_plf_serial_control(__ch_data, __COMMCTL_IRQ_DISABLE);
		while(chan->throttle_tx==true)
			cyg_hal_plf_serial_getc_nonblock(__ch_data, &chdum);
		cyg_hal_plf_serial_control(__ch_data, __COMMCTL_IRQ_ENABLE);
	};

	// Write to UART
	while(!(uartRegisterRead(LSR)&LSRTHR));
	uartRegisterWrite(THR, (cyg_uint32)c);
	CYGARC_HAL_RESTORE_GP();
}

static cyg_bool
cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
{
channel_data_t* chan = (channel_data_t*)__ch_data;
bool success=false;

if(uartRegisterRead(LSR)&LSRDR)
{
*ch=((unsigned char)uartRegisterRead(RBR)&0xff);
if (*ch==HAL_IO_SERIAL_FLOW_CONTROL_XON_CHAR) chan->throttle_tx=false;
else if (*ch==HAL_IO_SERIAL_FLOW_CONTROL_XOFF_CHAR) chan->throttle_tx=true;
success=true;
};

return success;
}


--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]