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.

controlSUITE driver lib bug

Other Parts Discussed in Thread: CONTROLSUITE

I discovered a nasty bug in the driver lib, in uart.c.  Specifically, the following code from the UARTCharPut() function is wrong:

//
// Wait until space is available.
//
while(!(HWREGB(ulBase + UART_O_CTL2) & UART_CTL2_TXRDY))
{
}

The code works fine until compiler optimizations are turned on, at which point erroneous code is produced.  Here is the generated assembly code with optimizations turned off, which is fine:

.dwpsn file "../uart.c",line 728,column 5,is_stmt
;----------------------------------------------------------------------
; 728 | while(!(HWREGB(ulBase + UART_O_CTL2) & UART_CTL2_TXRDY))
;----------------------------------------------------------------------
$C$L14:
.dwpsn file "../uart.c",line 728,column 11,is_stmt
;----------------------------------------------------------------------
; 732 | //
; 733 | // Send the char.
; 734 | //
;----------------------------------------------------------------------
MOVB ACC,#4 ; [CPU_] |728|
ADDL ACC,*-SP[2] ; [CPU_] |728|
MOVL XAR4,ACC ; [CPU_] |728|
MOVB AL.LSB,*+XAR4[0] ; [CPU_] |728|
TBIT AL,#7 ; [CPU_] |728|
BF $C$L14,NTC ; [CPU_] |728|
; branchcc occurs ; [] |728|

Here is the assembly code produced with optimization turned on (level 3), which is wrong:

MOVL XAR6,ACC ; [CPU_] |719|
ADDB ACC,#4 ; [CPU_]
MOVL XAR5,ACC ; [CPU_]
MOVB AL.LSB,*+XAR5[0] ; [CPU_]
$C$L31:
.dwpsn file "../uart.c",line 728,column 11,is_stmt
;----------------------------------------------------------------------
; 728 | while(!(HWREGB(ulBase + UART_O_CTL2) & UART_CTL2_TXRDY))
; 732 | //
; 733 | // Send the char.
; 734 | //
;----------------------------------------------------------------------
TBIT AL,#7 ; [CPU_] |728|
BF $C$L31,NTC ; [CPU_] |728|
; branchcc occurs ; [] |728|

The code simply tests a bit in a processor register in a tight loop, without ever reloading the register from the UART peripheral register.  So, this ends up looping forever.  The bug appears to be in the HWREGB macro, which makes use of the __byte() intrinsic.  The __byte() intrinsic DOES NOT include the volatile keyword in its signature, so produces undesired logic when optimizations are turned on.  I did not do an exhaustive search of the driver lib (or USB lib) code to find out where else this bug occurs, but it is likely in more place than one.

My solutions was to replace the use of the HWREGB macro with the following implementation, which works for me:

while (!(*((volatile unsigned char *)(ulBase + UART_O_CTL2)) & UART_CTL2_TXRDY))
{
}