mac 674 error with espconn_send and interrupts

Caesium
Posts: 2
Joined: Mon Dec 14, 2015 12:06 am

mac 674 error with espconn_send and interrupts

Postby Caesium » Mon Dec 14, 2015 12:40 am

Hello,

I've been running into an odd issue that I wonder if is a bug with the SDK, I can't see where I'm going wrong.

See attached code. It is also at https://gist.github.com/celsworth/4ea8a790df66683496a5 if you prefer.

Code: Select all

#include "esp8266.h"

#include "espconn.h"
#include "gpio.h"
#include "driver/uart.h"

#define WIFI_SSID "xx"
#define WIFI_PASS "xx"

LOCAL const int uart_rx = 14; /* GPIO pin for software serial RX decoding */
LOCAL const int uart_tx = 12; /* GPIO pin for software serial TX (not yet implemented) */
LOCAL const int uart_baud = 9600;

LOCAL uint16_t ts_read_timeout = 7200;
LOCAL struct espconn ts_server;

LOCAL struct espconn *ts_client;

// two buffers, one we're writing into for tx, one is being sent
LOCAL char ts_buf1[256], ts_buf2[256];

// which buffer we're pointing at for writing into
LOCAL char *tx_buffer;
LOCAL int ts_buf_len;

LOCAL bool ts_sending;

void ICACHE_FLASH_ATTR ts_send_buf(void)
{
   int r, t_len;
   char *t;

   // only attempt a send if we're not waiting for a previous espconn_send()
   // to return, and we actually have some data to send.
   if (ts_client && !ts_sending && ts_buf_len > 0)
   {
      // swap the buffers with interrupts turned off, so
      // ts_append_output() cannot be called while we're in the middle of it
      uint32_t savedPS = xt_rsil(15);
      t_len = ts_buf_len;
      t = tx_buffer;
      tx_buffer = (tx_buffer == ts_buf1) ? ts_buf2 : ts_buf1;
      ts_buf_len = 0;
      xt_wsr_ps(savedPS);

      ts_sending = true;
      r = espconn_send(ts_client, t, t_len);

      if (r != 0)
         os_printf("ts_send_buf: len = %d, r = %d\n", t_len, r);
   }
}

// queue some output onto our txbuffer
// this is called from interrupt, don't put in flash
void ts_append_output(char c)
{
   if (!ts_client) return;

   if (ts_buf_len < 256)
   {
      tx_buffer[ts_buf_len++] = c;
   }
   else
   {
      //os_printf("BUFFER FULL, LOSING SERIAL RX DATA!\n");
   }
}

LOCAL void ICACHE_FLASH_ATTR ts_disconcb(void *arg)
{
   struct espconn *c = (struct espconn *)arg;

   ts_client = NULL;

   os_printf("tcp connection disconnected\n");
}

LOCAL void ICACHE_FLASH_ATTR ts_recvcb(void *arg, char *pusrdata, unsigned short length)
{
   struct espconn *c = (struct espconn *)arg;

   // TODO: send pusrdata to the uart
}

LOCAL void ICACHE_FLASH_ATTR ts_sentcb(void *arg)
{
   struct espconn *c = (struct espconn *)arg;
   int r;

   ts_sending = false;

   // check if there's any more buffered data to send
   ts_send_buf();
}

LOCAL void ICACHE_FLASH_ATTR ts_connectcb(void *arg)
{
   struct espconn *c = (struct espconn *)arg;

   ts_client = c;
   ts_buf_len = 0;
   tx_buffer = ts_buf1;
   ts_sending = false;

   os_printf("tcp connection established\n");

   espconn_regist_recvcb(c, ts_recvcb);
   // espconn_regist_reconcb(c, ts_recon_cb);
   espconn_regist_disconcb(c, ts_disconcb);
   espconn_regist_sentcb(c, ts_sentcb);
}

void ICACHE_FLASH_ATTR ts_init(void)
{
   ts_server.type = ESPCONN_TCP;
   ts_server.state = ESPCONN_NONE;
   ts_server.proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
   ts_server.proto.tcp->local_port = 2001;
   espconn_regist_connectcb(&ts_server, ts_connectcb);
   espconn_accept(&ts_server);
   espconn_regist_time(&ts_server, ts_read_timeout, 0);

   // only accept one connection at a time (they get exclusive access to serial console)
   espconn_tcp_set_max_con_allow(&ts_server, 1);

   os_printf("[%s] ts initialised\n", __func__);
}

LOCAL volatile os_timer_t loop_timer;

LOCAL void ICACHE_FLASH_ATTR loop(os_event_t *events)
{
   ts_send_buf();

   //os_timer_disarm(&loop_timer); // not sure if needed, sdk doc says yes, doc example says no?
   os_timer_arm(&loop_timer, 10, 0);
}

void uart_intr(void *arg)
{
   int *gpio_num = arg;
   uint8_t i, d = 0, gpio_pin = GPIO_ID_PIN((*gpio_num));
   uint32_t start_time, bit_time = (1000000 / uart_baud);

   if (! GPIO_INPUT_GET(gpio_pin))
   {
      // pin is low; we have a start bit. pause for half the expected duration so we can
      // sample the next bit right in the middle.
      os_delay_us(bit_time / 2);

      start_time = 0x7FFFFFFF & system_get_time();

      for (i = 0 ; i < 8 ; i++)
      {
         while ((0x7FFFFFFF & system_get_time()) < (start_time + (bit_time*(i+1))))
         {
            // abort if timer overflows
            if ((0x7FFFFFFF & system_get_time()) < start_time)
               break;
         }

         //shift d to the right
         d >>= 1;

         // read the bit
         if (GPIO_INPUT_GET(gpio_pin))
         {
            // record the presence of the high bit
            d |= 0x80;
         }
      }

      // wait for stop bit
      os_delay_us(bit_time);

      ts_append_output(d);
   }
}

void user_init(void)
{
   struct station_config sc;

   uart_init(9600, 9600);

   // easyintr initialisation
   ei_init();

   strcpy((char *)&sc.ssid, WIFI_SSID);
   strcpy((char *)&sc.password, WIFI_PASS);

   wifi_set_opmode_current(STATION_MODE);
   wifi_station_set_config_current(&sc);

   /* initialise software uart (connected to another serial port) with easyintr */
   ei_attach(uart_rx, PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14, uart_intr, &uart_rx);
   GPIO_DIS_OUTPUT(GPIO_ID_PIN(uart_rx));
   PIN_PULLUP_EN(PERIPHS_IO_MUX_MTMS_U);

   os_timer_disarm(&loop_timer);
   os_timer_setfn(&loop_timer, loop, NULL);
   os_timer_arm(&loop_timer, 1, 0);

   ts_init();

   os_printf("SDK version:%s\n", system_get_sdk_version());
}

void user_rf_pre_init(void)
{
}



This is basically a serial-to-wifi bridge (only receiving from the serial and sending over tcp works for now).

When running this with some serial data coming into GPIO14, and a client connected which is receiving it, I get "mac 674" after some amount of time - it can vary from seconds to half an hour or more before it triggers.

It happens with SDK 1.3.0, 1.4.0 and 1.5.0.

Code: Select all

scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 2
cnt

connected with AirPort, channel 1
dhcp client start...
ip:192.168.0.212,mask:255.255.255.0,gw:192.168.0.1
tcp connection established
pm open,type:2 0
mac 674


Does my code look ok? I have put the full zipfile (its an esp-open-sdk project) here: http://kojan.cae.me.uk/espconn_send_hang.tar.gz

If there is no client connected (so espconn_send does not get called) it runs for hours just fine. No crash.

Would really appreciate any ideas. Thanks!

ESP_Faye
Posts: 1646
Joined: Mon Oct 27, 2014 11:08 am

Re: mac 674 error with espconn_send and interrupts

Postby ESP_Faye » Mon Dec 14, 2015 1:39 pm

Hi,

Sorry that I can not compile your codes, could your provide the whole project ?

Caesium
Posts: 2
Joined: Mon Dec 14, 2015 12:06 am

Re: mac 674 error with espconn_send and interrupts

Postby Caesium » Mon Dec 14, 2015 5:30 pm

Hi,

Thanks for taking a look at this. Are you able to compile the project at http://kojan.cae.me.uk/espconn_send_hang.tar.gz using esp-open-sdk?

ESP_Faye
Posts: 1646
Joined: Mon Oct 27, 2014 11:08 am

Re: mac 674 error with espconn_send and interrupts

Postby ESP_Faye » Fri Dec 18, 2015 6:39 pm

Hi,

I tested your project, but sorry that I did not duplicate your problem.

How did you send data through GPIO14 ? How many bytes per time, in what time interval ?

mdelfede
Posts: 2
Joined: Thu Sep 24, 2015 12:11 am

Re: mac 674 error with espconn_send and interrupts

Postby mdelfede » Wed Jan 13, 2016 3:04 am

same error here.

Slave SPI with ISR routine, and soon or later the "mac 674" error happens.

Is there a solution ?

ESP_Faye
Posts: 1646
Joined: Mon Oct 27, 2014 11:08 am

Re: mac 674 error with espconn_send and interrupts

Postby ESP_Faye » Mon Jan 18, 2016 3:02 pm

Hi,

Sorry that we can not duplicate this problem.

Could you have a try with the latest ESP8266_NONOS_SDK_V1.5.1 ?

If your problem is still unsolved, please provide your test code, we will help debug it.

Who is online

Users browsing this forum: No registered users and 18 guests