forked from espressif/arduino-esp32
Handle APB frequency change (#2250)
* Add APB change callbacks and move cpu code to own file * Properly set esp_timer and FreeRTOS tick dividers * Improve updated devisors * No need to update REF_TICK yet * Add initial handling for UART baud change * fix uartWriteBuf and uartDetectBaudrate * trigger callbacks even when APB did not change * toggle UART ISR on CPU change * add XTAL freq getter and add cpu freq validation * Support CPU frequency changes in I2C (#2287) **esp32-hal-i2c.c** * add callback for cpu frequency changes * adjust fifo thresholds based on cpu frequency and i2c bus frequency * reduce i2c bus frequency if differential is too small **Wire.h** * version to 1.1.0 * Implement clock change for the other peripherals * remove bad CPU clock values from the menu * Add note to CPU freqs that support WiFi and BT
This commit is contained in:
@ -67,6 +67,8 @@ static uart_t _uart_bus_array[3] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb);
|
||||
|
||||
static void IRAM_ATTR _uart_isr(void *arg)
|
||||
{
|
||||
uint8_t i, c;
|
||||
@ -216,6 +218,7 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
|
||||
uartAttachTx(uart, txPin, inverted);
|
||||
}
|
||||
|
||||
addApbChangeCallback(uart, uart_on_apb_change);
|
||||
return uart;
|
||||
}
|
||||
|
||||
@ -224,11 +227,10 @@ void uartEnd(uart_t* uart)
|
||||
if(uart == NULL) {
|
||||
return;
|
||||
}
|
||||
removeApbChangeCallback(uart, uart_on_apb_change);
|
||||
|
||||
UART_MUTEX_LOCK();
|
||||
if(uart->queue != NULL) {
|
||||
uint8_t c;
|
||||
while(xQueueReceive(uart->queue, &c, 0));
|
||||
vQueueDelete(uart->queue);
|
||||
uart->queue = NULL;
|
||||
}
|
||||
@ -248,8 +250,6 @@ size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
|
||||
|
||||
UART_MUTEX_LOCK();
|
||||
if(uart->queue != NULL) {
|
||||
uint8_t c;
|
||||
while(xQueueReceive(uart->queue, &c, 0));
|
||||
vQueueDelete(uart->queue);
|
||||
uart->queue = xQueueCreate(new_size, sizeof(uint8_t));
|
||||
if(uart->queue == NULL) {
|
||||
@ -319,10 +319,9 @@ void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len)
|
||||
}
|
||||
UART_MUTEX_LOCK();
|
||||
while(len) {
|
||||
while(len && uart->dev->status.txfifo_cnt < 0x7F) {
|
||||
uart->dev->fifo.rw_byte = *data++;
|
||||
len--;
|
||||
}
|
||||
while(uart->dev->status.txfifo_cnt == 0x7F);
|
||||
uart->dev->fifo.rw_byte = *data++;
|
||||
len--;
|
||||
}
|
||||
UART_MUTEX_UNLOCK();
|
||||
}
|
||||
@ -359,13 +358,49 @@ void uartSetBaudRate(uart_t* uart, uint32_t baud_rate)
|
||||
UART_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb)
|
||||
{
|
||||
uart_t* uart = (uart_t*)arg;
|
||||
if(ev_type == APB_BEFORE_CHANGE){
|
||||
UART_MUTEX_LOCK();
|
||||
//disabple interrupt
|
||||
uart->dev->int_ena.val = 0;
|
||||
uart->dev->int_clr.val = 0xffffffff;
|
||||
// read RX fifo
|
||||
uint8_t c;
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
while(uart->dev->status.rxfifo_cnt != 0 || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
|
||||
c = uart->dev->fifo.rw_byte;
|
||||
if(uart->queue != NULL && !xQueueIsQueueFullFromISR(uart->queue)) {
|
||||
xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
// wait TX empty
|
||||
while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
|
||||
} else {
|
||||
//todo:
|
||||
// set baudrate
|
||||
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
|
||||
uint32_t baud_rate = ((old_apb<<4)/clk_div);
|
||||
clk_div = ((new_apb<<4)/baud_rate);
|
||||
uart->dev->clk_div.div_int = clk_div>>4 ;
|
||||
uart->dev->clk_div.div_frag = clk_div & 0xf;
|
||||
//enable interrupts
|
||||
uart->dev->int_ena.rxfifo_full = 1;
|
||||
uart->dev->int_ena.frm_err = 1;
|
||||
uart->dev->int_ena.rxfifo_tout = 1;
|
||||
uart->dev->int_clr.val = 0xffffffff;
|
||||
UART_MUTEX_UNLOCK();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t uartGetBaudRate(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
|
||||
return ((UART_CLK_FREQ<<4)/clk_div);
|
||||
return ((getApbFrequency()<<4)/clk_div);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR uart0_write_char(char c)
|
||||
@ -505,7 +540,7 @@ uartDetectBaudrate(uart_t *uart)
|
||||
uart->dev->auto_baud.en = 0;
|
||||
uartStateDetectingBaudrate = false; // Initialize for the next round
|
||||
|
||||
unsigned long baudrate = UART_CLK_FREQ / divisor;
|
||||
unsigned long baudrate = getApbFrequency() / divisor;
|
||||
|
||||
static const unsigned long default_rates[] = {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 256000, 460800, 921600, 1843200, 3686400};
|
||||
|
||||
|
Reference in New Issue
Block a user