add more annotation to explain how to choose different uart output mode.
A simple DMA to output data to uart0
Move output data in interrupt handler instead of in system task.
============================================================
150413 update:
fix some errors in parity setting in uart_config()
add definitions in uart_register.h
150410 update:
add a demo with uart data buffer and task
send data via uart fifo empty interrupt
recv data via uart fifo full and timeout interrupt
==========================================
150112 update:
1. ADD SOME APIs FOR CFG
2.FIX SOME ERROR OF DEFINITION IN UART.H
THIS IS FOR NONE_OS VERSION.
I RECOMMEND THE RTOS VERSION DRIVER , MORE FRIENDLY.
YOU CAN GET FROM
https://github.com/espressif/esp_iot_rtos_sdk
===========================================================
141123 update: GENERATE A TX BREAK SIGNAL!
In order to issue a tx break signal , you should do like this :
1. set UART_TXFIFO_RST,
2. set UART_TXD_BRK
3. set a timer to RESET UART_TXD_BRK
3. reset UART_TXD_BRK in timer(or other event)
Code: Select all
// 1. set UART_TXFIFO_RST,
SET_PERI_REG_MASK(UART_CONF0(UART0), UART_RXFIFO_RST | UART_TXFIFO_RST);
CLEAR_PERI_REG_MASK(UART_CONF0(UART0), UART_RXFIFO_RST | UART_TXFIFO_RST);
// 2. set UART_TXD_BRK
SET_PERI_REG_MASK(UART_CONF0(UART0), UART_TXD_BRK);
// 3. set a timer to RESET UART_TXD_BRK
os_timer_arm(&brk_timer,1,0);
Code: Select all
//timer
os_timer_t brk_timer;
void ICACHE_FLASH_ATTR clr_brk_bit()
{
CLEAR_PERI_REG_MASK(UART_CONF0(UART0), UART_TXD_BRK);
}
LOCAL void ICACHE_FLASH_ATTR
uart_config(uint8 uart_no)
{
......
os_timer_setfn(&brk_timer, (os_timer_func_t *)clr_brk_bit, NULL);
}
Also you can set up a loop back test for this :
1.enable UART_BRK_DET interrupt in uart initial func
Code: Select all
//1.enable UART_BRK_DET interrupt in uart initial func
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_BRK_DET_INT_ENA);
2.process UART_BRK_DET_INT in uart interrupt handler
Code: Select all
//2.process UART_BRK_DET_INT in uart interrupt handler
......
else if(UART_BRK_DET_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_BRK_DET_INT_ST)) {
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_BRK_DET_INT_CLR);//clear interrupt
CLEAR_PERI_REG_MASK(UART_CONF0(UART0), UART_LOOPBACK);//disable uart loopback
CLEAR_PERI_REG_MASK(UART_CONF0(UART0), UART_TXD_BRK);//CLEAR BRK BIT
os_printf("BRK INTR\n\r");
}
......
3.IN TESTCASE :START A LOOPBACK TX BRK SIGNAL AND TRIGGER THE INTERRUPT
Code: Select all
//enable uart loopback
SET_PERI_REG_MASK(UART_CONF0(UART0), UART_LOOPBACK);
//reset fifo
SET_PERI_REG_MASK(UART_CONF0(UART0), UART_RXFIFO_RST | UART_TXFIFO_RST);
CLEAR_PERI_REG_MASK(UART_CONF0(UART0), UART_RXFIFO_RST | UART_TXFIFO_RST);
//set UART_TXD_BRK bit
SET_PERI_REG_MASK(UART_CONF0(UART0), UART_TXD_BRK);
==========================================================================
[ATTENTION PLEASE]:
In the rx tout and rx fifo full interrupt handler, make sure to read the whole fifo data out ,then set the interrupt clear bit.
This is a UART register description.
The two uart modules have their own independent register address and hw fifo.
We can distinguish them with the macros UART0 and UART1.
To config a register, you can do like this:
Code: Select all
/*
*e.g.
*#define TEST_REG_ADDR 0x60000000
*#define TEST_REG_FUNC 0x0000007F
*#define TEST_REG_FUNC_S 8
*BASE ADDR:0x60000000
*TEST_REG_FUNC MASK FOR THE CONFIG ITEM(0x7F means it takes 7 bit)
*TEST_REG_FUNC_S is the bit offset from the lsb
*eg.in order to set 0x55:
*((0x55 & TEST_REG_FUNC)<<TEST_REG_FUNC_S)
*you can use it along with the macros below
*GET_PERI_REG_BITS(reg, hipos,lowpos)
*GET_PERI_REG_BITS(TEST_REG_ADDR,TEST_REG_FUNC_S+7,TEST_REG_FUNC_S)
*SET_PERI_REG_BITS(reg,bit_map,value,shift)
*SET_PERI_REG_BITS(TEST_REG_ADDR,TEST_REG_FUNC,0x55,TEST_REG_FUNC_S)
*/
Do compare the difference of the macros, WRITE_PERI_REG,SET_PERI_REG_BITS,SET_PERI_REG_MASK
Here are some reference codes:
1.uart1 pin mux select:
Code: Select all
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); //CONFIG GPIO2 TO UART1 TXD
2.config uart speed
Code: Select all
uart_div_modify(uart_no, UART_CLK_FREQ / (115200)); //CONFIG UART baudrate to 115200
3.config UART0 data format
Code: Select all
WRITE_PERI_REG(UART_CONF0(UART0),
(BIT(1)) //ENABLE PARITY CHECK
|(BIT(0)) //SET ODD CHECK
| (0x1 << UART_STOP_BIT_NUM_S) //STOP BIT SET
| (0x3 << UART_BIT_NUM_S) //DATA BIT SET
4. Reset tx/rx fifo
Code: Select all
//clear rx and tx fifo
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
5.interrupt config
Code: Select all
//set rx INTRRUPT PARAM
WRITE_PERI_REG(UART_CONF1(uart_no),
((60 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | //UART RX FULL THRESHOLD
((100 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) | //UART RX FLOW CONTROL THRESHOLD
UART_RX_FLOW_EN | //ENABLE RX FLOW CONTROL
(0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S | //UART RX TIMEOUT THRESHOLD
UART_RX_TOUT_EN); //UART RX TIMEOUT INTERRUPT ENABLE
6.enable interrupt
Code: Select all
//clear all interrupt
WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff);
//enable rx_interrupt
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no),0x1ff);
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | //ENABLE RX FIFO FULL INTERRUPT
UART_RXFIFO_TOUT_INT_ENA | //ENABLE RX TIMEOUT INTERRUPT
UART_FRM_ERR_INT_ENA | //ENABLE RX FRAME ERROR INTERRUPT
UART_PARITY_ERR_INT_ENA| //ENABLE PARITY CHECK ERROR INTERRUPT
UART_BRK_DET_INT_ENA| //ENABLE BYTE START ERROR INTERRUPT
);
7.register uart interrupt handler
Code: Select all
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); //REGISTER UART INTR HANDLER ,WITH PARAM BUFFER ADDR
8.handler ,do as less job as possible in interrupt handler, or post a signal to the task.
[code]if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)){ //DECIDE THE INTERRUPT SOURCE
while ( (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT){ //PROCESS ALL DATAS IN RX FIFO UNTIL IT IS EMPTY
RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF;
}
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); //AT LAST CLEAR INTERRUPT STATUS
}