[En-Nut-Discussion] RE: UART_SETCLOCKMODE - UART_NSYNCSLAVE - found a bug in NutOs

Dave Smart Dave at Smart-Family.net
Sun Sep 17 05:03:12 CEST 2006


I found a bug in the AVR usart driver.
I have a follow on issue with _ioctl(...) not behaving as I expected

======================= BUG Report =============================
In NutOs 4.0.3.2 of nut\arch\avr\dev\usartavr.c, line 1046, 
and in the CVS tip [shown below] it is line 1050.

UCSRnA should be UCSRnC - which is the register where UMSEL appears.

	 1024 static int AvrUsartSetClockMode(u_char mode)
	 1025 {
	 1026 #ifdef __AVR_ENHANCED__
	...
	 1047         /* Disable high speed. */
	 1048         cbi(UCSRnA, U2X);
	 1049         /* Enable synchronous mode. */
	 1050         sbi(UCSRnA, UMSEL);
	...
	 1064         /* Disable negated clock. */
	 1065         cbi(UCSRnC, UCPOL);
	 1066         /* Disable synchronous mode. */
	 1067         cbi(UCSRnC, UMSEL);
	

I fixed this line, then used the configuration to rebuild, forced a build of
my code, and yet it didn't actually fix my problem, so there is something
I'm yet missing. 


======================= Follow On Issue with _ioctl(...)
==========================

I tried some brute-force tests, but unexpectedly received error return
values as you see here. This sequence - 

	rlen = NutRegisterDevice(&devUart1, 0, 0);	// open the UART as
a stream
	uartkybd = fopen("uart1", "r+b");
	_ioctlParam = 2;	// 2 = even parity
	rlen = _ioctl(_fileno(uartkybd), UART_SETPARITY, &_ioctlParam);
	if (rlen)
		puts_P(PSTR("***** error in SetParity()\n"));
	_ioctlParam = 1;
	rlen = _ioctl(_fileno(uartkybd), UART_SETSTOPBITS, &_ioctlParam);
	if (rlen)
		puts_P(PSTR("***** error in SetStop()\n"));
	_ioctlParam = 8;
	rlen = _ioctl(_fileno(uartkybd), UART_SETDATABITS, &_ioctlParam);
	if (rlen)
		puts_P(PSTR("***** error in SetData()\n"));
	
	
	_ioctlParam = UART_SYNCSLAVE;	// tx on rising edge, rx on falling
edge
	rlen = _ioctl(_fileno(uartkybd), UART_SETCLOCKMODE, &_ioctlParam);
	if (rlen)
		puts_P(PSTR("***** error in
SetClockMode(UART_SYNCSLAVE)\n"));
	
	_ioctlParam = UART_NSYNCSLAVE;	// tx on rising edge, rx on falling
edge
	rlen = _ioctl(_fileno(uartkybd), UART_SETCLOCKMODE, &_ioctlParam);
	if (rlen)
		puts_P(PSTR("***** error in
SetClockMode(UART_NSYNCSLAVE)\n"));

Printed - 
	***** error in SetParity()
	***** error in SetClockMode(UART_SYNCSLAVE)
	***** error in SetClockMode(UART_NSYNCSLAVE)  


Just after these lines of code I put this into play.

	UCSR1C |= 0x40;	// Skip the driver and force Sync Mode

And did get sync mode to work as I wanted.

Regards,
Dave Smart 




More information about the En-Nut-Discussion mailing list