esp32-hal-uart.c 17.1 KB
Newer Older
M
me-no-dev 已提交
1
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
M
me-no-dev 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "esp32-hal-uart.h"
M
me-no-dev 已提交
16
#include "esp32-hal.h"
M
me-no-dev 已提交
17 18
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
M
me-no-dev 已提交
19
#include "freertos/queue.h"
M
me-no-dev 已提交
20 21 22 23 24 25
#include "freertos/semphr.h"
#include "rom/ets_sys.h"
#include "esp_attr.h"
#include "esp_intr.h"
#include "rom/uart.h"
#include "soc/uart_reg.h"
M
me-no-dev 已提交
26
#include "soc/uart_struct.h"
M
me-no-dev 已提交
27 28
#include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h"
M
me-no-dev 已提交
29
#include "soc/dport_reg.h"
M
Me No Dev 已提交
30
#include "soc/rtc.h"
M
me-no-dev 已提交
31
#include "esp_intr_alloc.h"
M
me-no-dev 已提交
32 33 34 35 36 37 38 39

#define UART_REG_BASE(u)    ((u==0)?DR_REG_UART_BASE:(      (u==1)?DR_REG_UART1_BASE:(    (u==2)?DR_REG_UART2_BASE:0)))
#define UART_RXD_IDX(u)     ((u==0)?U0RXD_IN_IDX:(          (u==1)?U1RXD_IN_IDX:(         (u==2)?U2RXD_IN_IDX:0)))
#define UART_TXD_IDX(u)     ((u==0)?U0TXD_OUT_IDX:(         (u==1)?U1TXD_OUT_IDX:(        (u==2)?U2TXD_OUT_IDX:0)))
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:((u==2)?ETS_UART2_INTR_SOURCE:0)))

static int s_uart_debug_nr = 0;

M
me-no-dev 已提交
40 41
struct uart_struct_t {
    uart_dev_t * dev;
42
#if !CONFIG_DISABLE_HAL_LOCKS
M
me-no-dev 已提交
43
    xSemaphoreHandle lock;
44
#endif
M
me-no-dev 已提交
45 46
    uint8_t num;
    xQueueHandle queue;
M
me-no-dev 已提交
47
    intr_handle_t intr_handle;
M
me-no-dev 已提交
48 49
};

50 51 52 53 54
#if CONFIG_DISABLE_HAL_LOCKS
#define UART_MUTEX_LOCK()
#define UART_MUTEX_UNLOCK()

static uart_t _uart_bus_array[3] = {
M
me-no-dev 已提交
55 56 57
    {(volatile uart_dev_t *)(DR_REG_UART_BASE), 0, NULL, NULL},
    {(volatile uart_dev_t *)(DR_REG_UART1_BASE), 1, NULL, NULL},
    {(volatile uart_dev_t *)(DR_REG_UART2_BASE), 2, NULL, NULL}
58 59
};
#else
M
me-no-dev 已提交
60 61
#define UART_MUTEX_LOCK()    do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS)
#define UART_MUTEX_UNLOCK()  xSemaphoreGive(uart->lock)
M
me-no-dev 已提交
62

M
me-no-dev 已提交
63
static uart_t _uart_bus_array[3] = {
M
me-no-dev 已提交
64 65 66
    {(volatile uart_dev_t *)(DR_REG_UART_BASE), NULL, 0, NULL, NULL},
    {(volatile uart_dev_t *)(DR_REG_UART1_BASE), NULL, 1, NULL, NULL},
    {(volatile uart_dev_t *)(DR_REG_UART2_BASE), NULL, 2, NULL, NULL}
M
me-no-dev 已提交
67
};
68
#endif
M
me-no-dev 已提交
69

M
Me No Dev 已提交
70 71
static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb);

M
me-no-dev 已提交
72 73
static void IRAM_ATTR _uart_isr(void *arg)
{
M
me-no-dev 已提交
74
    uint8_t i, c;
M
me-no-dev 已提交
75
    BaseType_t xHigherPriorityTaskWoken;
M
me-no-dev 已提交
76 77 78 79
    uart_t* uart;

    for(i=0;i<3;i++){
        uart = &_uart_bus_array[i];
M
me-no-dev 已提交
80 81 82
        if(uart->intr_handle == NULL){
            continue;
        }
M
me-no-dev 已提交
83 84 85
        uart->dev->int_clr.rxfifo_full = 1;
        uart->dev->int_clr.frm_err = 1;
        uart->dev->int_clr.rxfifo_tout = 1;
86
        while(uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
M
me-no-dev 已提交
87
            c = uart->dev->fifo.rw_byte;
88
            if(uart->queue != NULL)  {
M
me-no-dev 已提交
89 90
                xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken);
            }
M
me-no-dev 已提交
91 92 93 94 95 96 97 98
        }
    }

    if (xHigherPriorityTaskWoken) {
        portYIELD_FROM_ISR();
    }
}

M
me-no-dev 已提交
99 100
void uartEnableInterrupt(uart_t* uart)
{
M
me-no-dev 已提交
101
    UART_MUTEX_LOCK();
M
me-no-dev 已提交
102 103 104 105 106 107 108 109
    uart->dev->conf1.rxfifo_full_thrhd = 112;
    uart->dev->conf1.rx_tout_thrhd = 2;
    uart->dev->conf1.rx_tout_en = 1;
    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;

M
me-no-dev 已提交
110
    esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, _uart_isr, NULL, &uart->intr_handle);
M
me-no-dev 已提交
111
    UART_MUTEX_UNLOCK();
M
me-no-dev 已提交
112 113 114 115
}

void uartDisableInterrupt(uart_t* uart)
{
M
me-no-dev 已提交
116
    UART_MUTEX_LOCK();
M
me-no-dev 已提交
117 118 119
    uart->dev->conf1.val = 0;
    uart->dev->int_ena.val = 0;
    uart->dev->int_clr.val = 0xffffffff;
M
me-no-dev 已提交
120 121 122 123

    esp_intr_free(uart->intr_handle);
    uart->intr_handle = NULL;

M
me-no-dev 已提交
124
    UART_MUTEX_UNLOCK();
M
me-no-dev 已提交
125 126
}

127
void uartDetachRx(uart_t* uart, uint8_t rxPin)
M
me-no-dev 已提交
128 129 130
{
    if(uart == NULL) {
        return;
M
me-no-dev 已提交
131
    }
132
    pinMatrixInDetach(rxPin, false, false);
M
me-no-dev 已提交
133 134
    uartDisableInterrupt(uart);
}
M
me-no-dev 已提交
135

136
void uartDetachTx(uart_t* uart, uint8_t txPin)
M
me-no-dev 已提交
137 138 139
{
    if(uart == NULL) {
        return;
M
me-no-dev 已提交
140
    }
141
    pinMatrixOutDetach(txPin, false, false);
M
me-no-dev 已提交
142
}
M
me-no-dev 已提交
143

M
me-no-dev 已提交
144 145 146 147
void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted)
{
    if(uart == NULL || rxPin > 39) {
        return;
M
me-no-dev 已提交
148
    }
M
me-no-dev 已提交
149 150 151 152
    pinMode(rxPin, INPUT);
    pinMatrixInAttach(rxPin, UART_RXD_IDX(uart->num), inverted);
    uartEnableInterrupt(uart);
}
M
me-no-dev 已提交
153

M
me-no-dev 已提交
154 155 156 157 158 159 160 161
void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
{
    if(uart == NULL || txPin > 39) {
        return;
    }
    pinMode(txPin, OUTPUT);
    pinMatrixOutAttach(txPin, UART_TXD_IDX(uart->num), inverted, false);
}
M
me-no-dev 已提交
162

M
me-no-dev 已提交
163 164 165 166 167
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted)
{
    if(uart_nr > 2) {
        return NULL;
    }
M
me-no-dev 已提交
168

M
me-no-dev 已提交
169 170 171
    if(rxPin == -1 && txPin == -1) {
        return NULL;
    }
M
me-no-dev 已提交
172

M
me-no-dev 已提交
173
    uart_t* uart = &_uart_bus_array[uart_nr];
M
me-no-dev 已提交
174

175
#if !CONFIG_DISABLE_HAL_LOCKS
M
me-no-dev 已提交
176 177 178 179 180 181
    if(uart->lock == NULL) {
        uart->lock = xSemaphoreCreateMutex();
        if(uart->lock == NULL) {
            return NULL;
        }
    }
182
#endif
M
me-no-dev 已提交
183

M
me-no-dev 已提交
184
    if(queueLen && uart->queue == NULL) {
M
me-no-dev 已提交
185 186 187 188 189
        uart->queue = xQueueCreate(queueLen, sizeof(uint8_t)); //initialize the queue
        if(uart->queue == NULL) {
            return NULL;
        }
    }
M
me-no-dev 已提交
190 191 192 193 194 195
    if(uart_nr == 1){
        DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN);
        DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST);
    } else if(uart_nr == 2){
        DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN);
        DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST);
M
me-no-dev 已提交
196 197 198
    } else {
        DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN);
        DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST);
M
me-no-dev 已提交
199
    }
M
me-no-dev 已提交
200
    uartFlush(uart);
M
me-no-dev 已提交
201
    uartSetBaudRate(uart, baudrate);
M
me-no-dev 已提交
202
    UART_MUTEX_LOCK();
M
me-no-dev 已提交
203
    uart->dev->conf0.val = config;
C
Claude Heintz 已提交
204 205
    #define TWO_STOP_BITS_CONF 0x3
    #define ONE_STOP_BITS_CONF 0x1
206

C
Claude Heintz 已提交
207 208 209 210
    if ( uart->dev->conf0.stop_bit_num == TWO_STOP_BITS_CONF) {
        uart->dev->conf0.stop_bit_num = ONE_STOP_BITS_CONF;
        uart->dev->rs485_conf.dl1_en = 1;
    }
211 212 213 214 215

    // tx_idle_num : idle interval after tx FIFO is empty(unit: the time it takes to send one bit under current baudrate)
    // Setting it to 0 prevents line idle time/delays when sending messages with small intervals
    uart->dev->idle_conf.tx_idle_num = 0;  //

M
me-no-dev 已提交
216
    UART_MUTEX_UNLOCK();
M
me-no-dev 已提交
217 218 219 220 221 222 223 224

    if(rxPin != -1) {
        uartAttachRx(uart, rxPin, inverted);
    }

    if(txPin != -1) {
        uartAttachTx(uart, txPin, inverted);
    }
M
Me No Dev 已提交
225
    addApbChangeCallback(uart, uart_on_apb_change);
M
me-no-dev 已提交
226 227 228
    return uart;
}

229
void uartEnd(uart_t* uart, uint8_t txPin, uint8_t rxPin)
M
me-no-dev 已提交
230
{
M
me-no-dev 已提交
231
    if(uart == NULL) {
M
me-no-dev 已提交
232 233
        return;
    }
M
Me No Dev 已提交
234
    removeApbChangeCallback(uart, uart_on_apb_change);
M
me-no-dev 已提交
235

M
me-no-dev 已提交
236
    UART_MUTEX_LOCK();
M
me-no-dev 已提交
237
    if(uart->queue != NULL) {
M
me-no-dev 已提交
238
        vQueueDelete(uart->queue);
M
me-no-dev 已提交
239
        uart->queue = NULL;
M
me-no-dev 已提交
240 241
    }

M
me-no-dev 已提交
242
    uart->dev->conf0.val = 0;
243

M
me-no-dev 已提交
244
    UART_MUTEX_UNLOCK();
245

246 247
    uartDetachRx(uart, rxPin);
    uartDetachTx(uart, txPin);
M
me-no-dev 已提交
248 249
}

250 251
size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
    if(uart == NULL) {
252
        return 0;
253 254 255 256 257 258 259
    }

    UART_MUTEX_LOCK();
    if(uart->queue != NULL) {
        vQueueDelete(uart->queue);
        uart->queue = xQueueCreate(new_size, sizeof(uint8_t));
        if(uart->queue == NULL) {
260
            UART_MUTEX_UNLOCK();
261 262 263 264 265 266 267 268
            return NULL;
        }
    }
    UART_MUTEX_UNLOCK();

    return new_size;
}

269 270 271 272 273 274 275 276 277 278 279
void uartSetRxInvert(uart_t* uart, bool invert)
{
    if (uart == NULL)
        return;
    
    if (invert)
        uart->dev->conf0.rxd_inv = 1;
    else
        uart->dev->conf0.rxd_inv = 0;
}

M
me-no-dev 已提交
280 281
uint32_t uartAvailable(uart_t* uart)
{
M
me-no-dev 已提交
282 283 284
    if(uart == NULL || uart->queue == NULL) {
        return 0;
    }
285
    return (uxQueueMessagesWaiting(uart->queue) + uart->dev->status.rxfifo_cnt) ;
M
me-no-dev 已提交
286 287
}

288 289 290 291 292 293 294 295
uint32_t uartAvailableForWrite(uart_t* uart)
{
    if(uart == NULL) {
        return 0;
    }
    return 0x7f - uart->dev->status.txfifo_cnt;
}

296 297 298 299
void uartRxFifoToQueue(uart_t* uart)
{
	uint8_t c;
    UART_MUTEX_LOCK();
300 301 302 303 304 305 306 307 308 309 310 311
	//disable interrupts
	uart->dev->int_ena.val = 0;
	uart->dev->int_clr.val = 0xffffffff;
	while (uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
		c = uart->dev->fifo.rw_byte;
		xQueueSend(uart->queue, &c, 0);
	}
	//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;
312 313 314
    UART_MUTEX_UNLOCK();
}

M
me-no-dev 已提交
315 316
uint8_t uartRead(uart_t* uart)
{
M
me-no-dev 已提交
317 318 319
    if(uart == NULL || uart->queue == NULL) {
        return 0;
    }
M
me-no-dev 已提交
320
    uint8_t c;
321 322 323 324
    if ((uxQueueMessagesWaiting(uart->queue) == 0) && (uart->dev->status.rxfifo_cnt > 0))
    {
    	uartRxFifoToQueue(uart);
    }
M
me-no-dev 已提交
325 326 327 328 329 330 331 332
    if(xQueueReceive(uart->queue, &c, 0)) {
        return c;
    }
    return 0;
}

uint8_t uartPeek(uart_t* uart)
{
M
me-no-dev 已提交
333 334 335
    if(uart == NULL || uart->queue == NULL) {
        return 0;
    }
M
me-no-dev 已提交
336
    uint8_t c;
337 338 339 340
    if ((uxQueueMessagesWaiting(uart->queue) == 0) && (uart->dev->status.rxfifo_cnt > 0))
    {
    	uartRxFifoToQueue(uart);
    }
M
me-no-dev 已提交
341 342 343 344 345 346 347 348
    if(xQueuePeek(uart->queue, &c, 0)) {
        return c;
    }
    return 0;
}

void uartWrite(uart_t* uart, uint8_t c)
{
M
me-no-dev 已提交
349 350 351
    if(uart == NULL) {
        return;
    }
M
me-no-dev 已提交
352
    UART_MUTEX_LOCK();
M
me-no-dev 已提交
353
    while(uart->dev->status.txfifo_cnt == 0x7F);
M
me-no-dev 已提交
354
    uart->dev->fifo.rw_byte = c;
M
me-no-dev 已提交
355
    UART_MUTEX_UNLOCK();
M
me-no-dev 已提交
356 357 358 359
}

void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len)
{
M
me-no-dev 已提交
360 361 362
    if(uart == NULL) {
        return;
    }
M
me-no-dev 已提交
363
    UART_MUTEX_LOCK();
M
me-no-dev 已提交
364
    while(len) {
M
Me No Dev 已提交
365 366 367
        while(uart->dev->status.txfifo_cnt == 0x7F);
        uart->dev->fifo.rw_byte = *data++;
        len--;
M
me-no-dev 已提交
368
    }
M
me-no-dev 已提交
369
    UART_MUTEX_UNLOCK();
M
me-no-dev 已提交
370 371 372
}

void uartFlush(uart_t* uart)
C
chuck todd 已提交
373
{
B
Bert Melis 已提交
374
    uartFlushTxOnly(uart,true);
C
chuck todd 已提交
375 376 377
}

void uartFlushTxOnly(uart_t* uart, bool txOnly)
M
me-no-dev 已提交
378
{
M
me-no-dev 已提交
379
    if(uart == NULL) {
M
me-no-dev 已提交
380 381 382
        return;
    }

M
me-no-dev 已提交
383
    UART_MUTEX_LOCK();
B
Bert Melis 已提交
384
    while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
C
chuck todd 已提交
385 386 387 388 389 390 391 392 393
    
    if( !txOnly ){
        //Due to hardware issue, we can not use fifo_rst to reset uart fifo.
        //See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <<esp32_technical_reference_manual>> v2.6 or later.

        // we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`.
        while(uart->dev->status.rxfifo_cnt != 0 || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
            READ_PERI_REG(UART_FIFO_REG(uart->num));
        }
M
me-no-dev 已提交
394

C
chuck todd 已提交
395
        xQueueReset(uart->queue);
396
    }
C
chuck todd 已提交
397
    
M
me-no-dev 已提交
398
    UART_MUTEX_UNLOCK();
M
me-no-dev 已提交
399 400 401 402
}

void uartSetBaudRate(uart_t* uart, uint32_t baud_rate)
{
M
me-no-dev 已提交
403
    if(uart == NULL) {
M
me-no-dev 已提交
404 405
        return;
    }
M
me-no-dev 已提交
406
    UART_MUTEX_LOCK();
M
Me No Dev 已提交
407
    uint32_t clk_div = ((getApbFrequency()<<4)/baud_rate);
M
me-no-dev 已提交
408 409
    uart->dev->clk_div.div_int = clk_div>>4 ;
    uart->dev->clk_div.div_frag = clk_div & 0xf;
M
me-no-dev 已提交
410
    UART_MUTEX_UNLOCK();
M
me-no-dev 已提交
411 412
}

M
Me No Dev 已提交
413 414 415 416 417 418 419 420 421 422
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;
423
   //     BaseType_t xHigherPriorityTaskWoken;
M
Me No Dev 已提交
424 425
        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;
426 427
            if(uart->queue != NULL ) {
                xQueueSend(uart->queue, &c, 1); //&xHigherPriorityTaskWoken);
M
Me No Dev 已提交
428 429
            }
        }
430 431
        UART_MUTEX_UNLOCK();
 
M
Me No Dev 已提交
432 433 434 435 436
        // wait TX empty
        while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
    } else {
        //todo:
        // set baudrate
437
        UART_MUTEX_LOCK();
M
Me No Dev 已提交
438 439 440 441 442 443 444 445 446 447 448 449 450 451
        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();
    }
}

M
me-no-dev 已提交
452 453
uint32_t uartGetBaudRate(uart_t* uart)
{
M
me-no-dev 已提交
454
    if(uart == NULL) {
M
me-no-dev 已提交
455 456
        return 0;
    }
J
Jeroen88 已提交
457

M
me-no-dev 已提交
458
    uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
J
Jeroen88 已提交
459 460 461 462
    if(!clk_div) {
        return 0;
    }

M
Me No Dev 已提交
463
    return ((getApbFrequency()<<4)/clk_div);
M
me-no-dev 已提交
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
}

static void IRAM_ATTR uart0_write_char(char c)
{
    while(((ESP_REG(0x01C+DR_REG_UART_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
    ESP_REG(DR_REG_UART_BASE) = c;
}

static void IRAM_ATTR uart1_write_char(char c)
{
    while(((ESP_REG(0x01C+DR_REG_UART1_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
    ESP_REG(DR_REG_UART1_BASE) = c;
}

static void IRAM_ATTR uart2_write_char(char c)
{
    while(((ESP_REG(0x01C+DR_REG_UART2_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
    ESP_REG(DR_REG_UART2_BASE) = c;
}

M
Me No Dev 已提交
484
void uart_install_putc()
M
me-no-dev 已提交
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
{
    switch(s_uart_debug_nr) {
    case 0:
        ets_install_putc1((void (*)(char)) &uart0_write_char);
        break;
    case 1:
        ets_install_putc1((void (*)(char)) &uart1_write_char);
        break;
    case 2:
        ets_install_putc1((void (*)(char)) &uart2_write_char);
        break;
    default:
        ets_install_putc1(NULL);
        break;
    }
}

M
Me No Dev 已提交
502 503 504 505 506 507 508 509 510 511 512 513 514 515
void uartSetDebug(uart_t* uart)
{
    if(uart == NULL || uart->num > 2) {
        s_uart_debug_nr = -1;
        //ets_install_putc1(NULL);
        //return;
    } else
    if(s_uart_debug_nr == uart->num) {
        return;
    } else
    s_uart_debug_nr = uart->num;
    uart_install_putc();
}

M
me-no-dev 已提交
516 517 518 519 520
int uartGetDebug()
{
    return s_uart_debug_nr;
}

521 522 523 524 525
int log_printf(const char *format, ...)
{
    if(s_uart_debug_nr < 0){
        return 0;
    }
M
me-no-dev 已提交
526
    static char loc_buf[64];
527
    char * temp = loc_buf;
M
me-no-dev 已提交
528
    int len;
529 530 531 532 533 534 535 536 537 538 539 540 541
    va_list arg;
    va_list copy;
    va_start(arg, format);
    va_copy(copy, arg);
    len = vsnprintf(NULL, 0, format, arg);
    va_end(copy);
    if(len >= sizeof(loc_buf)){
        temp = (char*)malloc(len+1);
        if(temp == NULL) {
            return 0;
        }
    }
    vsnprintf(temp, len+1, format, arg);
542
#if !CONFIG_DISABLE_HAL_LOCKS
543
    if(_uart_bus_array[s_uart_debug_nr].lock){
M
me-no-dev 已提交
544
        xSemaphoreTake(_uart_bus_array[s_uart_debug_nr].lock, portMAX_DELAY);
M
me-no-dev 已提交
545 546
        ets_printf("%s", temp);
        xSemaphoreGive(_uart_bus_array[s_uart_debug_nr].lock);
547
    } else {
M
me-no-dev 已提交
548
        ets_printf("%s", temp);
549
    }
550
#else
M
me-no-dev 已提交
551
    ets_printf("%s", temp);
552
#endif
553
    va_end(arg);
M
me-no-dev 已提交
554
    if(len >= sizeof(loc_buf)){
555 556 557 558
        free(temp);
    }
    return len;
}
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582

/*
 * if enough pulses are detected return the minimum high pulse duration + minimum low pulse duration divided by two. 
 * This equals one bit period. If flag is true the function return inmediately, otherwise it waits for enough pulses.
 */
unsigned long uartBaudrateDetect(uart_t *uart, bool flg)
{
    while(uart->dev->rxd_cnt.edge_cnt < 30) { // UART_PULSE_NUM(uart_num)
        if(flg) return 0;
        ets_delay_us(1000);
    }

    UART_MUTEX_LOCK();
    unsigned long ret = ((uart->dev->lowpulse.min_cnt + uart->dev->highpulse.min_cnt) >> 1) + 12;
    UART_MUTEX_UNLOCK();

    return ret;
}

/*
 * To start detection of baud rate with the uart the auto_baud.en bit needs to be cleared and set. The bit period is 
 * detected calling uartBadrateDetect(). The raw baudrate is computed using the UART_CLK_FREQ. The raw baudrate is 
 * rounded to the closed real baudrate.
*/
J
Jeroen88 已提交
583 584 585 586 587 588 589 590
void uartStartDetectBaudrate(uart_t *uart) {
  if(!uart) return;

  uart->dev->auto_baud.glitch_filt = 0x08;
  uart->dev->auto_baud.en = 0;
  uart->dev->auto_baud.en = 1;
}

591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
unsigned long
uartDetectBaudrate(uart_t *uart)
{
    static bool uartStateDetectingBaudrate = false;

    if(!uartStateDetectingBaudrate) {
        uart->dev->auto_baud.glitch_filt = 0x08;
        uart->dev->auto_baud.en = 0;
        uart->dev->auto_baud.en = 1;
        uartStateDetectingBaudrate = true;
    }

    unsigned long divisor = uartBaudrateDetect(uart, true);
    if (!divisor) {
        return 0;
    }

    uart->dev->auto_baud.en = 0;
    uartStateDetectingBaudrate = false; // Initialize for the next round

M
Me No Dev 已提交
611
    unsigned long baudrate = getApbFrequency() / divisor;
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628

    static const unsigned long default_rates[] = {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 256000, 460800, 921600, 1843200, 3686400};

    size_t i;
    for (i = 1; i < sizeof(default_rates) / sizeof(default_rates[0]) - 1; i++)	// find the nearest real baudrate
    {
        if (baudrate <= default_rates[i])
        {
            if (baudrate - default_rates[i - 1] < default_rates[i] - baudrate) {
                i--;
            }
            break;
        }
    }

    return default_rates[i];
}
629 630 631 632 633 634 635

/*
 * Returns the status of the RX state machine, if the value is non-zero the state machine is active.
 */
bool uartRxActive(uart_t* uart) {
    return uart->dev->status.st_urx_out != 0;
}