Esempio n. 1
0
void bootloader_reset(void)
{
#ifdef BOOTLOADER_BUILD
    uart_tx_flush(0);    /* Ensure any buffered log output is displayed */
    uart_tx_flush(1);
    ets_delay_us(1000); /* Allow last byte to leave FIFO */
    REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
    while (1) { }       /* This line will never be reached, used to keep gcc happy */
#else
    abort();            /* This function should really not be called from application code */
#endif
}
Esempio n. 2
0
void stat_help(void)
{
    uart_printf(
        "Stat command (s) output consists of heading line followed by %u channel stat lines"                   UART_EOL
        "Heading line: group current_timestamp"                                                                UART_EOL
        "  group                   - the number identifying radio frequency being used for communications:"    UART_EOL
        "                            0 - 24%02uMHz, 1 - 24%02uMHz"                                             UART_EOL
        "  current_timestamp       - the current receiver timestamp"                                           UART_EOL
                                                                                                               UART_EOL
        "Stat line: epoch rep_total rep_received first_ts last_ts sn ts bt_pressed pressed_ts released_ts vcc" UART_EOL
        "  epoch                   - the number incremented every time the transmitting module restart"        UART_EOL
        "                            is detected, zero epoch means the corresponding module was not ever run"  UART_EOL
        "  rep_total rep_received  - the number of report messages in current epoch"                           UART_EOL
        "  first_ts last_ts        - timestamps of first and last report received in current epoch"            UART_EOL
        "  sn                      - the last report sequence number"                                          UART_EOL
        "  ts                      - the last report timestamp as reported by sender"                          UART_EOL
        "  bt_pressed              - the button status: 0 - released, 1 - pressed"                             UART_EOL
        "  pressed_ts released_ts  - the timestamps of the button first press / last release"                  UART_EOL
        "  vcc                     - the transmitter power voltage measured in millivolts"                     UART_EOL
                                                                                                               UART_EOL
        "All timestamps are measured in 1/1024 sec units."                                                     UART_EOL
        "The ts, pressed_ts, released_ts are measured by the transmitter clock."                               UART_EOL,
        MAX_GR_ROLES, GR0_CH, GR1_CH
    );
    uart_tx_flush();
}
Esempio n. 3
0
// Print stat to UART
void stat_dump(void)
{
    unsigned i, ts = rtc_current();
    uart_printf("%u %u" UART_EOL, g_stat_group, ts);
    for (i = 0; i < MAX_GR_ROLES; ++i)
    {
        struct stat_buffer const* b = &g_stat_buff[i];
        struct stat_entry const* s = &b->e[b->ei];
        uart_printf("%u %u %u %u %u ", 
            s->epoch,
            s->reports_total,
            s->reports_received,
            s->first_report_ts,
            s->last_report_ts
        );
        struct report_packet const* r = &s->last_report;
        uart_printf("%u %u %u %u %u %u" UART_EOL, 
            r->sn,
            r->ts,
            r->bt_pressed,
            r->bt_pressed_ts,
            r->bt_released_ts,
            r->vcc_mv
        );
    }
    uart_tx_flush();
}
Esempio n. 4
0
void uart_rx_process(void)
{
    switch (g_uart_rx_buff[0]) {
    case 'r':
        get_stat();
        break;
    case 'u':
        get_transmitter_uptime();
        break;
    case 's':
        x_start();
        break;
    case 'q':
        if (g_uart_rx_buff[1] == 'd') {
            x_get_page();
        } else {
            x_get_status();
        }
        break;
    case '?':
        get_help();
        break;
    default:
        uart_printf("invalid command, send ? to get help" UART_EOL);
        uart_tx_flush();
    }
}
Esempio n. 5
0
static void x_start()
{
    x_upd_tout();
    x_set_status(x_starting);
    uart_printf(UART_EOL);
    uart_tx_flush();
}
Esempio n. 6
0
static void get_transmitter_uptime(void)
{
    if (!g_report_packets) {
        uart_printf(UART_EOL);
    } else {
        uart_printf("%u" UART_EOL, last_report_age() + g_last_report.sn * MEASURING_PERIOD);
    }
    uart_tx_flush();
}
Esempio n. 7
0
static inline void get_help(void)
{
    uart_printf(" r  - print last report and reception stat" UART_EOL);
    uart_printf(" u  - get transmitter uptime in seconds" UART_EOL);
    uart_printf(" s  - start data transfer" UART_EOL);
    uart_printf(" q  - query data transfer status" UART_EOL);
    uart_printf(" qd - query data transfer status and data page if available" UART_EOL);
    uart_printf(" ?  - this help" UART_EOL);
    uart_tx_flush();
}
Esempio n. 8
0
void panic_puts(const char *outstr)
{
	/* Flush the output buffer */
	uart_flush_output();

	/* Put all characters in the output buffer */
	while (*outstr)
		panic_txchar(NULL, *outstr++);

	/* Flush the transmit FIFO */
	uart_tx_flush();
}
Esempio n. 9
0
void uart_rx_process(void)
{
    switch (g_uart_rx_buff[0]) {
    case 's':
        g_stat_request = 1;
        break;
    case '?':
        stat_help();
        break;
    default:
        uart_printf("valid commands are: s, ?" UART_EOL);
        uart_tx_flush();
    }
}
Esempio n. 10
0
void panic_printf(const char *format, ...)
{
	va_list args;

	/* Flush the output buffer */
	uart_flush_output();

	va_start(args, format);
	vfnprintf(panic_txchar, NULL, format, args);
	va_end(args);

	/* Flush the transmit FIFO */
	uart_tx_flush();
}
Esempio n. 11
0
static void _console_tx_flush(void)
{
#if CONFIG_CONSOLE_SERIAL8250MEM
	uart8250_mem_tx_flush(CONFIG_OXFORD_OXPCIE_BASE_ADDRESS + 0x1000);
#endif
#if CONFIG_CONSOLE_SERIAL8250
	uart8250_tx_flush(CONFIG_TTYS0_BASE);
#endif
#if CONFIG_CONSOLE_SERIAL_UART
	uart_tx_flush();
#endif
#if CONFIG_USBDEBUG
	usbdebug_tx_flush(0);
#endif
}
Esempio n. 12
0
static void get_stat(void)
{
    if (!g_report_packets) {
        uart_printf("no valid reports received" UART_EOL);
    } else {
        int i, pg_cnt = 0;
        for (i = 0; i < DATA_PAGES; ++i) {
               if (bmap_get_bit(g_last_report.page_bitmap, i))
                   ++pg_cnt;
        }
        uart_printf("status = %#x"  UART_EOL, g_last_report.hdr.status);
        uart_printf("PW     = %.1f" UART_EOL, PW_SCALE * g_last_report.power);
        uart_printf("Vbatt  = %.4f" UART_EOL, VCC_SCALE * g_last_report.vbatt);
        uart_printf("SN     = %u"   UART_EOL, g_last_report.sn);
        uart_printf("%u pages used" UART_EOL, pg_cnt);
        uart_printf("%u report packets received" UART_EOL, g_report_packets);
        uart_printf("last packet was received %u sec ago" UART_EOL, last_report_age());        
    }
    if (g_total_packets) {
        uart_printf("total packets received: %u (%u%% good)" UART_EOL,
            g_total_packets, 100 * g_good_packets / g_total_packets);
    }
    uart_tx_flush();
}
Esempio n. 13
0
void cmd_loop() {
  while(1) {
    /* Wait for a command */
    while(ub.command == NULL) { }
    esp_command_req_t *command = ub.command;
    ub.command = NULL;
    /* provide easy access for 32-bit data words */
    uint32_t *data_words = (uint32_t *)command->data_buf;

    /* Send command response header */
    esp_command_response_t resp = {
      .resp = 1,
      .op_ret = command->op,
      .len_ret = 0, /* esptool.py ignores this value */
      .value = 0,
    };

    /* ESP_READ_REG is the only command that needs to write into the
       'resp' structure before we send it back. */
    if (command->op == ESP_READ_REG && command->data_len == 4) {
      resp.value = REG_READ(data_words[0]);
    }

    /* Send the command response. */
    SLIP_send_frame_delimiter();
    SLIP_send_frame_data_buf(&resp, sizeof(esp_command_response_t));

    if(command->data_len > MAX_WRITE_BLOCK+16) {
      SLIP_send_frame_data(ESP_BAD_DATA_LEN);
      SLIP_send_frame_data(0xEE);
      SLIP_send_frame_delimiter();
      continue;
    }

    /* ... some commands will insert in-frame response data
       between here and when we send the end of the frame */

    esp_command_error error = ESP_CMD_NOT_IMPLEMENTED;
    int status = 0;

    /* First stage of command processing - before sending error/status */
    switch (command->op) {
    case ESP_ERASE_FLASH:
      error = verify_data_len(command, 0) || SPIEraseChip();
      break;
    case ESP_ERASE_REGION:
      /* Params for ERASE_REGION are addr, len */
      error = verify_data_len(command, 8) || handle_flash_erase(data_words[0], data_words[1]);
      break;
    case ESP_SET_BAUD:
      /* ESP_SET_BAUD sends two args, we ignore the second one */
      error = verify_data_len(command, 8);
      /* actual baud setting happens after we send the reply */
      break;
    case ESP_READ_FLASH:
      error = verify_data_len(command, 16);
      /* actual data is sent after we send the reply */
      break;
    case ESP_FLASH_VERIFY_MD5:
      /* unsure why the MD5 command has 4 params but we only pass 2 of them,
         but this is in ESP32 ROM so we can't mess with it.
      */
      error = verify_data_len(command, 16) || handle_flash_get_md5sum(data_words[0], data_words[1]);
      break;
    case ESP_FLASH_BEGIN:
      /* parameters (interpreted differently to ROM flasher):
         0 - erase_size (used as total size to write)
         1 - num_blocks (ignored)
         2 - block_size (should be MAX_WRITE_BLOCK, relies on num_blocks * block_size >= erase_size)
         3 - offset (used as-is)
       */
        if (command->data_len == 16 && data_words[2] != MAX_WRITE_BLOCK) {
            error = ESP_BAD_BLOCKSIZE;
        } else {
            error = verify_data_len(command, 16) || handle_flash_begin(data_words[0], data_words[3]);
        }
      break;
    case ESP_FLASH_DEFLATED_BEGIN:
      /* parameters:
         0 - uncompressed size
         1 - num_blocks (based on compressed size)
         2 - block_size (should be MAX_WRITE_BLOCK, total bytes over serial = num_blocks * block_size)
         3 - offset (used as-is)
      */
        if (command->data_len == 16 && data_words[2] != MAX_WRITE_BLOCK) {
            error = ESP_BAD_BLOCKSIZE;
        } else {
            error = verify_data_len(command, 16) || handle_flash_deflated_begin(data_words[0], data_words[1] * data_words[2], data_words[3]);            }
        break;
    case ESP_FLASH_DATA:
    case ESP_FLASH_DEFLATED_DATA:
      /* ACK DATA commands immediately, then process them a few lines down,
         allowing next command to buffer */
      if(is_in_flash_mode()) {
        error = get_flash_error();
        int payload_len = command->data_len - 16;
        if (data_words[0] != payload_len) {
          /* First byte of data payload header is length (repeated) as a word */
          error = ESP_BAD_DATA_LEN;
        }
        uint8_t data_checksum = calculate_checksum(command->data_buf + 16, payload_len);
        if (data_checksum != command->checksum) {
          error = ESP_BAD_DATA_CHECKSUM;
        }
      }
      else {
        error = ESP_NOT_IN_FLASH_MODE;
      }
      break;
    case ESP_FLASH_END:
    case ESP_FLASH_DEFLATED_END:
      error = handle_flash_end();
      break;
    case ESP_SPI_SET_PARAMS:
      /* data params: fl_id, total_size, block_size, sector_Size, page_size, status_mask */
      error = verify_data_len(command, 24) || handle_spi_set_params(data_words, &status);
      break;
    case ESP_SPI_ATTACH:
      /* parameter is 'hspi mode' (0, 1 or a pin mask for ESP32. Ignored on ESP8266.) */
      error = verify_data_len(command, 4) || handle_spi_attach(data_words[0]);
      break;
    case ESP_WRITE_REG:
      /* params are addr, value, mask (ignored), delay_us (ignored) */
      error = verify_data_len(command, 16);
      if (error == ESP_OK) {
        REG_WRITE(data_words[0], data_words[1]);
      }
      break;
    case ESP_READ_REG:
      /* actual READ_REG operation happens higher up */
      error = verify_data_len(command, 4);
      break;
    case ESP_MEM_BEGIN:
        error = verify_data_len(command, 16) || handle_mem_begin(data_words[0], data_words[3]);
        break;
    case ESP_MEM_DATA:
        error = handle_mem_data(command->data_buf + 16, command->data_len - 16);
        break;
    case ESP_MEM_END:
        error = verify_data_len(command, 8) || handle_mem_finish();
        break;
    case ESP_RUN_USER_CODE:
        /* Returning from here will run user code, ie standard boot process

           This command does not send a response.
        */
        return;
    }

    SLIP_send_frame_data(error);
    SLIP_send_frame_data(status);
    SLIP_send_frame_delimiter();

    /* Some commands need to do things after after sending this response */
    if (error == ESP_OK) {
      switch(command->op) {
      case ESP_SET_BAUD:
        ets_delay_us(10000);
        uart_div_modify(0, baud_rate_to_divider(data_words[0]));
        ets_delay_us(1000);
        break;
      case ESP_READ_FLASH:
        /* args are: offset, length, block_size, max_in_flight */
        handle_flash_read(data_words[0], data_words[1], data_words[2],
                          data_words[3]);
        break;
      case ESP_FLASH_DATA:
        /* drop into flashing mode, discard 16 byte payload header */
        handle_flash_data(command->data_buf + 16, command->data_len - 16);
        break;
      case ESP_FLASH_DEFLATED_DATA:
        handle_flash_deflated_data(command->data_buf + 16, command->data_len - 16);
        break;
      case ESP_FLASH_DEFLATED_END:
      case ESP_FLASH_END:
        /* passing 0 as parameter for ESP_FLASH_END means reboot now */
        if (data_words[0] == 0) {
          /* Flush the FLASH_END response before rebooting */
#ifdef ESP32
          uart_tx_flush(0);
#endif
          ets_delay_us(10000);
          software_reset();
        }
        break;
      case ESP_MEM_END:
          if (data_words[1] != 0) {
              void (*entrypoint_fn)(void) = (void (*))data_words[1];
              /* this is a little different from the ROM loader,
                 which exits the loader routine and _then_ calls this
                 function. But for our purposes so far, having a bit of
                 extra stuff on the stack doesn't really matter.
              */
              entrypoint_fn();
          }
          break;
      }
    }
  }
}


extern uint32_t _bss_start;
extern uint32_t _bss_end;

void __attribute__((used)) stub_main();


#ifdef ESP8266
__asm__ (
  ".global stub_main_8266\n"
  ".literal_position\n"
  ".align 4\n"
  "stub_main_8266:\n"
/* ESP8266 wrapper for "stub_main()" manipulates the return address in
 * a0, so 'return' from here runs user code.
 *
 * After setting a0, we jump directly to stub_main_inner() which is a
 * normal C function
 *
 * Adapted from similar approach used by Cesanta Software for ESP8266
 * flasher stub.
 *
 */
  "movi a0, 0x400010a8;"
  "j stub_main;");
#endif

/* This function is called from stub_main, with return address
   reset to point to user code. */
void stub_main()
{
  const uint32_t greeting = 0x4941484f; /* OHAI */

  /* this points to stub_main now, clear for next boot */
  ets_set_user_start(0);

  /* zero bss */
  for(uint32_t *p = &_bss_start; p < &_bss_end; p++) {
    *p = 0;
  }

  SLIP_send(&greeting, 4);

  /* All UART reads come via uart_isr */
  ub.reading_buf = ub.buf_a;
  ets_isr_attach(ETS_UART0_INUM, uart_isr, NULL);
  SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RX_INTS);
  ets_isr_unmask(1 << ETS_UART0_INUM);

  /* Configure default SPI flash functionality.
     Can be overriden later by esptool.py. */
#ifdef ESP8266
        SelectSpiFunction();
#else
        uint32_t spiconfig = ets_efuse_get_spiconfig();
        uint32_t strapping = REG_READ(GPIO_STRAP_REG);
        /* If GPIO1 (U0TXD) is pulled low and no other boot mode is
           set in efuse, assume HSPI flash mode (same as normal boot)
        */
        if (spiconfig == 0 && (strapping & 0x1c) == 0x08) {
            spiconfig = 1; /* HSPI flash mode */
        }
        spi_flash_attach(spiconfig, 0);
#endif
        SPIParamCfg(0, 16*1024*1024, FLASH_BLOCK_SIZE, FLASH_SECTOR_SIZE,
                    FLASH_PAGE_SIZE, FLASH_STATUS_MASK);

  cmd_loop();

  /* if cmd_loop returns, it's due to ESP_RUN_USER_CODE command. */

  return;
}