/** * @brief Compute UxBRG and set BRGH if needed. * * @param[in] uart_num * @param[in] baudrate * @return -1 if the baudrate error is greater than 3%, 0 otherwise */ static int compute_divisor(unsigned int uart_num, uint32_t baudrate) { uint32_t divisor0, divisor1; uint32_t baudrate0, baudrate1; uint32_t error0, error1; int use_brgh = 0; const uint32_t pclk = mcu_get_system_clock() >> 1; /* Compute divisor with BRGH=0 */ divisor0 = (pclk / (16 * baudrate)) - 1; if (divisor0 > UINT16_MAX) divisor0 = UINT16_MAX; /* Compute divisor with BRGH=1 */ divisor1 = (pclk / (4 * baudrate)) - 1; if (divisor1 > UINT16_MAX) divisor1 = UINT16_MAX; /* Compute error */ baudrate0 = pclk / (16 * (divisor0 + 1)); baudrate1 = pclk / (4 * (divisor1 + 1)); if (baudrate > baudrate0) error0 = baudrate - baudrate0; else error0 = baudrate0 - baudrate; if (baudrate > baudrate1) error1 = baudrate - baudrate1; else error1 = baudrate1 - baudrate; use_brgh = error1 < error0; /* Check if error is less than 3%. This uses the fact that 1/32 ~ 3% */ if (use_brgh) { if ((error1 << 5) >= baudrate) return -1; } else if ((error0 << 5) >= baudrate) { return -1; } /* Configure UART module */ if (use_brgh) { UxMODE(uart_num) |= _U1MODE_BRGH_MASK; UxBRG(uart_num) = divisor1; } else { UxBRG(uart_num) = divisor0; } return 0; }
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { assert(uart <= UART_NUMOF && uart != 0); /*No uart 0 on pic32*/ /* Pin Mux should be setup in board file */ pic_uart[uart].regs = (volatile uint32_t *)(_UART1_BASE_ADDRESS + (uart - 1) * REGS_SPACING); pic_uart[uart].clock = PERIPHERAL_CLOCK; UxBRG(pic_uart[uart])= (pic_uart[uart].clock / (16 * baudrate)) - 1; UxSTA(pic_uart[uart])= 0; UxMODE(pic_uart[uart])= _U1MODE_ON_MASK; UxSTASET(pic_uart[uart])= _U1STA_URXEN_MASK; UxSTASET(pic_uart[uart])= _U1STA_UTXEN_MASK; return 0; }