Other "small" bug in TWRK60 BSP ( MQX 3.7 )

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Other "small" bug in TWRK60 BSP ( MQX 3.7 )

920 Views
GottiLuca
Contributor IV

Recently i've tried to use a UART ( UART4 in the specific ) at a baud rate greater than 230400 ( llike 460800 or 921600 ) , and i see that i couldn't communicate with the host ( the GS1011M Wifi module in my specific case ) .

The reason is quite simple :  the function _kuart_polled_ioctl() in file mqx\source\io\serial\polled\serl_pol_kuart.c, modify only the baud rate registers ( BDH and BDL ) but at such high speed the error can be greater than 6 % !!

The solution is to set the BRFA ( Baud Rate Fine Adjust ) filed in register UART_C4 ; in this way i could get an error of  less 0.2 % and be able to tals correctly with my host .

For those interested to the code , this is the orignal "wrong" code (from line 345 ) :

 

     case IO_IOCTL_SERIAL_SET_BAUD:
         /* baud_divisor = clock_speed / baudrate + 0.5 */ 
         baud = (io_info_ptr->INIT.CLOCK_SPEED + (8 * (*param_ptr))) / (16 * (*param_ptr));
         if (baud > (UART_BDH_SBR_MASK << 8))
             return IO_ERROR_INVALID_IOCTL_CMD;
         io_info_ptr->INIT.BAUD_RATE = *param_ptr;   
         sci_ptr->BDH = (uchar)((baud >> 8) & UART_BDH_SBR_MASK);
         sci_ptr->BDL = (uchar)(baud & UART_BDL_SBR_MASK);     
         break;

I've modified in this way :

     case IO_IOCTL_SERIAL_SET_BAUD:
         /* baud_divisor = clock_speed / baudrate + 0.5 */ 
         baud = (io_info_ptr->INIT.CLOCK_SPEED + (8 * (*param_ptr))) / (16 * (*param_ptr));
         if (baud > (UART_BDH_SBR_MASK << 8))
             return IO_ERROR_INVALID_IOCTL_CMD;
         io_info_ptr->INIT.BAUD_RATE = *param_ptr;   

        /* Added this  code for high baud rates ... */
         switch ( *param_ptr ) {
            case 460800UL:
                baud = 6;       // Baud Rate = 48000000 / ( 16 * 7 ) = 428571 ( 7 % error )
                sci_ptr->C4 = 16;   // BRFA = BaudRate = 48000000 / ( 16 * 6.5 ) = 461538.4
                break;
            case 921600UL:
                baud = 3;
                sci_ptr->C4 = 8;   // BRFA= 8 (8/32 = 0.25) BaudRate = 48000000 / ( 16 * 3.25 ) = 923076.9
                break;
               
            default:
              sci_ptr->C4 = 0;   // BRFA =0
              break;
         }
        
         sci_ptr->BDH = (uchar)((baud >> 8) & UART_BDH_SBR_MASK);
         sci_ptr->BDL = (uchar)(baud & UART_BDL_SBR_MASK);     
         break;

 

( it's not an optimal solution since the settings are valid only for 48 MHz Module Clock rate but it is enought for the TWRK60 BSP..).

0 Kudos
1 Reply

287 Views
solen
Contributor II

I also ran into this problem, and I was surprised that the driver did not support the BRFA-register.

I modified the code as follows:

 

case IO_IOCTL_SERIAL_SET_BAUD:          /*  baud rate divisor (x) is calculated with the formula             16 * wished_for_baud_rate = clock_speed / x                    use 5 bit fix point arithmetics:          32*x = 32 * clock_speed / (16 * wished_for_baud_rate)          x_frac = x & 31;          x_int = x >> 5;                  */         baud = (io_info_ptr->INIT.CLOCK_SPEED * 2) / (*param_ptr);         if ((baud >> 5) > (UART_BDH_SBR_MASK << 8))             return IO_ERROR_INVALID_IOCTL_CMD;                           io_info_ptr->INIT.BAUD_RATE = *param_ptr;                sci_ptr->BDH = (uchar)((baud >> 13) & UART_BDH_SBR_MASK);         sci_ptr->BDL = (uchar)((baud >> 5) & UART_BDL_SBR_MASK);               sci_ptr->C4 = (uchar)UART_C4_BRFA(baud & 0x1f);         break;

 

This will hopefully in any given baudrate adjust to best possible baudrate match, regardless of uart clock used. 

 

 

0 Kudos