• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Работа с uart в esp8266

pvvx

Активный участник сообщества
Подождите, подождите. А разве "свалка" от pvvx не избавлена от SDK Espressif в части работы с TCP стеком? А то я тут уже на этой свалке себе сервер пилить начал.
"Свалка" в части web не использует глючные функции espconn, а базируется на LwIP и при полном избавлении от SDK LwIP останется. Может версия его будет 1.4.1...
 

hd44780

New member
Снова привет :)
Кидаю в уарт с компа через FT232 97 байт (команда + аргументы). Но таск приёма не ловит ничего, такое ощущение, что модуль вообще впадает в ступор, потому что он и на другие команды перестаёт реагировать. Из ступора вывожу передёргиванием питания.
В таске приёма сделал эхо принимаемых байтов. От 97 байт эха вообще никакого.
Другие команды это - сброс, получение статуса, MAC/IP адресов. Все они однобайтные (только код команды).

Поэтому вопрос - какими порциями можно слать данные в уарт? И какого размера у него FIFO?
Для отправки данных использую Eltima Serial Port Monitor 5.0 (это монитор COM-порта) и FT232.

Ещё попробую отсылать не все 97 байт, а кусками.
 

pvvx

Активный участник сообщества
Поэтому вопрос - какими порциями можно слать данные в уарт? И какого размера у него FIFO?
fifo rx и tx по 128 байт.
Смотрите процедуру прерывания приема UART. У вас вроде была от AT, но там не очень всё хорошо.
Вариантов обработки приема с UART много - зависит от требуемых алгоритмов (что куда и когда) и указать что-то конкретное невозможно.
При нормальной скорости UART (от 115200) гарантии что "таск" успеет отработать до переполнения fifo в кодах AT нет и RTS там не задействован.
Ещё там куча проблем с включением/выключением прерываний от UART.
Чтение fifo rx в буфер:
Код:
   uint8 *ptr = &buf;
   int cnt = 0;
    while((sizebuf--) && (READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S))) {
        *ptr++ = READ_PERI_REG(UART_FIFO(UART0));
        cnt++;
    }
 
Последнее редактирование:

hd44780

New member
фу-ух ..
Вставил Ваш код в обработчик прерывания уарта, добавил туда эхо для контроля. Таски свои вырубил вообще.
Кидаю 10 байт и меньше - нормально всё, эхо проходит. 11 и больше - глухой висяк..
Даже вот такое:

Код:
    while ( READ_PERI_REG ( UART_STATUS ( UART0 ) ) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S) )
    {
        temp = READ_PERI_REG ( UART_FIFO ( UART0 ) );
        // Эхо
        uart0_sendByte ( temp );
/*
        // сохраняем байт в буфере
        cmdBuffer [ cmdBufferWriteIdx ++ ] = temp;

        // Закольцовываем
        if ( cmdBufferWriteIdx == CMD_BUFFER_SIZE )
            cmdBufferWriteIdx = 0;
*/
    } // while
глохнет.

Видимо придётся ещё какое-то подобие своего терминала писать ... Чтобы руками эти куски не клеить.
 
Последнее редактирование:

hd44780

New member
Да, сброс прерывания я прогавил, каюсь :) . Поправил.
Заметил в обработчике прерывания ветку:
if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST))
{
// os_printf("fifo full\r\n");
uart0_sendStr ( "FIFO full\r\n" );
ETS_UART_INTR_DISABLE();/////////
// system_os_post(taskReceivePrio, 0, 0);
} // if

Послал 16 байт, получил в ответ это сообщение :) . Т.е. входной буфер == 16 байт. Если, конечно, я это правильно понимаю.
 

pvvx

Активный участник сообщества
Послал 16 байт, получил в ответ это сообщение :) . Т.е. входной буфер == 16 байт. Если, конечно, я это правильно понимаю.
Нет. Fifo 128 байт, а у вас в конфигах UART назначено RXFIFO_FULL_INT по 16-ти байтам.
 

pvvx

Активный участник сообщества
WRITE_PERI_REG(UART_CONF1(UART0),
((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) // для срабатывания int_fifo_full при приеме одного символа и заряжающий таймер на набор fifo перед передачей.
| ((0x10 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S) // для срабатывания сигнала int, когда в передающем fifo (tx) остается ещё 16 символов и успела отработать процедура int до новой догрузки fifo, чтобы дырок в передаче не было.
| ((0x70 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) // для срабатывания сигнала RTS, когда в fifo останется ещё место для 16 символов и передающий успел сообразить, что забил буфер.
| ((0x01 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S) //
);
+ ещё много других установок в регистрах Uart и разных процедур обработки...
А вы пока не выбрали даже метод работы - по прерываниям или путем опроса, с таймерами или без и т.д...
(пример из моей свалки TCP2UART Web_base\app\web\uart.c и tcp_terminal.c)
Описание регистров UART, Таймера, SPI, I/O портов
 
Последнее редактирование:

hd44780

New member
Вроде разобрался, заработало. RTS я убрал, не использую его. Даже не знаю на какой он ноге у меня :( . Модуль - ESP-03.
pvvx, спасибо Вам огромное.
 

diygoodies

New member
Добрый день. Тоже мучаюсь с настройкой УАРТ и прерываниями. У меня приходят пакеты по 20 байт, выходит что получает 3 пакета и зависает и уходит в перезагрузку.
Код:
//Stupid bit of code that does the bare minimum to make os_printf work.

/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/

#include <esp8266.h>
#include <uart_hw.h>
#include "serial_transfer.h"



typedef struct {
    uint32     RcvBuffSize;
    uint8     *pRcvMsgBuff;
    uint8     *pWritePos;
    uint8     *pReadPos;
    uint8      TrigLvl; //JLU: may need to pad
    RcvMsgBuffState  BuffState;
} RcvMsgBuff;

static RcvMsgBuff rcv_buff;


LOCAL void
uart0_rx_intr_handler(void *para)
{
  uint8 RcvChar;
  uint8 uart_no = UART0;//UartDev.buff_uart_no;

  if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST))
  {
    os_printf("FRM_ERR\r\n");
    WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
  }

  if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST))
  {
    os_printf("fifo full\r\n");
    ETS_UART_INTR_DISABLE();
    WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
    while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S))
    {
     RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF;
     //os_printf("%02X", RcvChar);
     get_package_char(RcvChar);
    }
  }

  else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST))
  {
    ETS_UART_INTR_DISABLE();
    WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_TOUT_INT_CLR);
    while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S))
    {
     RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF;
     //os_printf("%02X", RcvChar);
     get_package_char(RcvChar);
    }
  }
  else if(UART_RXFIFO_TOUT_INT_ST != 0)
  {
    ETS_UART_INTR_DISABLE();
    os_printf("stat:%02X",*(uint8 *)UART_INT_ENA(uart_no));
    WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xFFFF);
  }
  //ETS_UART_INTR_ENABLE();
}

static void ICACHE_FLASH_ATTR stdoutUartTxd(char c) {
    //Wait until there is room in the FIFO
    while (((READ_PERI_REG(UART_STATUS(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ;
    //Send the character
    WRITE_PERI_REG(UART_FIFO(0), c);
}

static void ICACHE_FLASH_ATTR stdoutPutchar(char c) {
    //convert \n -> \r\n
    if (c=='\n') stdoutUartTxd('\r');
    stdoutUartTxd(c);
}


void ICACHE_FLASH_ATTR stdoutInit() {


    ETS_UART_INTR_ATTACH(uart0_rx_intr_handler,  &(rcv_buff));
    //Enable TxD pin
    PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
  
    //Set baud rate and other serial parameters to 115200,n,8,1
    uart_div_modify(0, UART_CLK_FREQ/BIT_RATE_115200);
    WRITE_PERI_REG(UART_CONF0(0), (STICK_PARITY_DIS)|(ONE_STOP_BIT << UART_STOP_BIT_NUM_S)| \
                (EIGHT_BITS << UART_BIT_NUM_S));

    //Reset tx & rx fifo
    SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
    CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
    //Clear pending interrupts


    //set rx fifo trigger
    WRITE_PERI_REG(UART_CONF1(0),
                   ((0x10 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
                   ((0x10 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) |UART_RX_FLOW_EN |
                   (0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S |  UART_RX_TOUT_EN);
    SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA);


    WRITE_PERI_REG(UART_INT_CLR(0), 0xffff);

    SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA);

    //Install our own putchar handler
    os_install_putc1((void *)stdoutPutchar);
    ETS_UART_INTR_ENABLE();
}
И функция разбора пакета

Код:
void ICACHE_FLASH_ATTR get_package_char(char DataUART)
{        
  
    //Some packet function

    WRITE_PERI_REG(0X60000914, 0x73);
    if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_FULL_INT_ST))
    {
    WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
    }
    else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_TOUT_INT_ST))
    {
    WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
    }
    ETS_UART_INTR_ENABLE();
}
Скорее всего переполняется буфер хотелось бы знать как правильно его очистить
 
Чёт не понял что значит SDK? С ним я смогу переписать прошивку самого SIM900??? Я просто по этой ссылке не вижу никаких сдк,, пдфок много, еще какой-то сервер, поммогите пожалуйста понять как загрузить это сдк, и перепрошивать
SIM900, извините что не в тему пишу.
 

diygoodies

New member
Короче такой обработчик рабочий
Код:
static void ICACHE_FLASH_ATTR recvTask(os_event_t *events)
{
    uint8_t i;    
    while (READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S))
    {
        WRITE_PERI_REG(0X60000914, 0x73); //WTD
        uint16 length = 0;
        while ((READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) && (length<MAX_UARTBUFFER))
            uartbuffer[length++] = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
        for (i = 0; i < MAX_CONN; ++i)
            if (connData[i].conn)
                espbuffsent(&connData[i], uartbuffer, length);       
    }

    if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_FULL_INT_ST))
    {
        WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
    }
    else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_TOUT_INT_ST))
    {
        WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
    }
    ETS_UART_INTR_ENABLE();
}
взял здесь https://github.com/beckdac/ESP8266-transparent-bridge/blob/master/user/user_main.c
 

Tomahawk

New member
Во многих проектах их авторы используют в тексте os_printf для вывода отладочной информации, но на деле через uart в terminal 1.9 ничего не выводится. Судя по описанию, достаточно подключить osapi.h, но нет... В чём секрет? Единственный рабочий способ, который я знаю, находился в UDK (функция console_print).
 

pvvx

Активный участник сообщества
Во многих проектах их авторы используют в тексте os_printf для вывода отладочной информации, но на деле через uart в terminal 1.9 ничего не выводится. Судя по описанию, достаточно подключить osapi.h, но нет... В чём секрет? Единственный рабочий способ, который я знаю, находился в UDK (функция console_print).
os_printf() - это в SDK os_printf_plus():
Имеет отключение вывода с помощью system_set_os_print(flag), flag = 0 отключает вывод.
Так-же os_printf() может выводить строки из области flash и IRAM.
Для вывода она использует назначенную функцию по os_install_putc1(func), назначенная func может быть любой. Т.е. может выводить побайтно хоть в память, а не в UART0 или UART1. По умолчанию в SDK назначена функция вывода в UART0 с иcпользованием FIFO (fifo у uart 128 байт, если сообщение лезет в него, то ожидания не происходит и оно аппаратно выводится и после выполнения os_printf() не тормозя основную программу).
Выход TX UART0 может быть переключен на другой вывод чипа ESP8266, а так-же полностью отключен.
В UDK console_print - это переназначенная ets_uart_printf(), которая находится в ROM-BIOS и имеет ошибки (к примеру с "%p:"), да работает с функцией _putc1() по адресу ROM:40001DCC которая использует номер UART из структуры UartDev.buff_uart_no и не использует FIFO. Т.е. при выводе через неё ожидается вывод каждого символа.
 

Tomahawk

New member
Использую ESP-01, хочу вывести через os_print на RxD и TxD (console_print на них же работает, а os_print нет). Ставить system_set_os_print(1); пробовал, но не помогло. Получается выводить возможно только на GPIO2? Зачем такие сложности, интересно...)
 
Сверху Снизу