IRAM void esp_uart_dispatch_bottom(int uart_no) { struct esp_uart_state *us = s_us[uart_no]; if (us == NULL) return; cs_rbuf_t *rxb = &us->rx_buf; cs_rbuf_t *txb = &us->tx_buf; uint32_t int_ena = UART_INFO_INTS; /* Determine which interrupts we want. */ if (us->rx_enabled && rxb->avail > 0) int_ena |= UART_RX_INTS; if (txb->used > 0) int_ena |= UART_TX_INTS; WRITE_PERI_REG(UART_INT_ENA(uart_no), int_ena); }
IRAM NOINSTR static void esp_handle_uart_int(struct esp_uart_state *us) { const int uart_no = us->cfg->uart_no; /* Since both UARTs use the same int, we need to apply the mask manually. */ const unsigned int int_st = READ_PERI_REG(UART_INT_ST(uart_no)) & READ_PERI_REG(UART_INT_ENA(uart_no)); if (int_st == 0) return; us->stats.ints++; if (int_st & UART_RXFIFO_OVF_INT_ST) us->stats.rx_overflows++; if (int_st & UART_CTS_CHG_INT_ST) { if (cts(uart_no) != 0 && tx_fifo_len(uart_no) > 0) us->stats.tx_throttles++; } if (int_st & (UART_RX_INTS | UART_TX_INTS)) { if (int_st & UART_RX_INTS) us->stats.rx_ints++; if (int_st & UART_TX_INTS) us->stats.tx_ints++; /* Wake up the processor and disable TX and RX ints until it runs. */ WRITE_PERI_REG(UART_INT_ENA(uart_no), UART_INFO_INTS); us->cfg->dispatch_cb(uart_no); } WRITE_PERI_REG(UART_INT_CLR(uart_no), int_st); }
void UART_IntrConfig(UART_Port uart_no, UART_IntrConfTypeDef *pUARTIntrConf) { uint32 reg_val = 0; UART_ClearIntrStatus(uart_no, UART_INTR_MASK); reg_val = READ_PERI_REG(UART_CONF1(uart_no)) & ~((UART_RX_FLOW_THRHD << UART_RX_FLOW_THRHD_S) | UART_RX_FLOW_EN) ; reg_val |= ((pUARTIntrConf->UART_IntrEnMask & UART_RXFIFO_TOUT_INT_ENA) ? ((((pUARTIntrConf->UART_RX_TimeOutIntrThresh)&UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S) | UART_RX_TOUT_EN) : 0); reg_val |= ((pUARTIntrConf->UART_IntrEnMask & UART_RXFIFO_FULL_INT_ENA) ? (((pUARTIntrConf->UART_RX_FifoFullIntrThresh)&UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) : 0); reg_val |= ((pUARTIntrConf->UART_IntrEnMask & UART_TXFIFO_EMPTY_INT_ENA) ? (((pUARTIntrConf->UART_TX_FifoEmptyIntrThresh)&UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S) : 0); WRITE_PERI_REG(UART_CONF1(uart_no), reg_val); CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_INTR_MASK); SET_PERI_REG_MASK(UART_INT_ENA(uart_no), pUARTIntrConf->UART_IntrEnMask); }
bool mgos_uart_hal_init(struct mgos_uart_state *us) { /* Start with ints disabled. */ WRITE_PERI_REG(UART_INT_ENA(us->uart_no), 0); #ifdef RTOS_SDK _xt_isr_mask(1 << ETS_UART_INUM); _xt_isr_attach(ETS_UART_INUM, (void *) esp_uart_isr, NULL); #else ETS_INTR_DISABLE(ETS_UART_INUM); ETS_UART_INTR_ATTACH(esp_uart_isr, NULL); #endif return true; }
/****************************************************************************** * FunctionName : uart_config * Description : Internal used function * UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled * UART1 just used for debug output * Parameters : uart_no, use UART0 or UART1 defined ahead * Returns : NONE *******************************************************************************/ static void ICACHE_FLASH_ATTR uart_config(uint8 uart_no) { if (uart_no == UART1) { PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO2_U); } else { /* rcv_buff size is 0x100 */ ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, 0); // FUNC_U0RXD==0 PIN_PULLUP_DIS (PERIPHS_IO_MUX_U0TXD_U); //now done in serbridgeInitPins PIN_PULLUP_DIS (PERIPHS_IO_MUX_U0RXD_U); } uart_div_modify(uart_no, UART_CLK_FREQ / UartDev.baut_rate); if (uart_no == UART1) //UART 1 always 8 N 1 WRITE_PERI_REG(UART_CONF0(uart_no), CALC_UARTMODE(EIGHT_BITS, NONE_BITS, ONE_STOP_BIT)); else WRITE_PERI_REG(UART_CONF0(uart_no), CALC_UARTMODE(UartDev.data_bits, UartDev.parity, UartDev.stop_bits)); //clear rx and tx fifo,not ready 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); if (uart_no == UART0) { // Configure RX interrupt conditions as follows: trigger rx-full when there are 127 characters // in the buffer, trigger rx-timeout when the fifo is non-empty and nothing further has been // received for 4 character periods. // Set the hardware flow-control to trigger when the FIFO holds 100 characters, although // we don't really expect the signals to actually be wired up to anything. It doesn't hurt // to set the threshold here... // We do not enable framing error interrupts 'cause they tend to cause an interrupt avalanche // and instead just poll for them when we get a std RX interrupt. WRITE_PERI_REG(UART_CONF1(uart_no), ((127 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | ((100 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) | UART_RX_FLOW_EN | (4 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S | UART_RX_TOUT_EN); SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA); } else { WRITE_PERI_REG(UART_CONF1(uart_no), ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S)); } //clear all interrupt WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff); }
void mgos_uart_hal_dispatch_bottom(struct mgos_uart_state *us) { uint32_t int_ena = UART_INFO_INTS; /* Determine which interrupts we want. */ if (us->rx_enabled) { if (mgos_uart_rxb_free(us) > 0) { int_ena |= UART_RX_INTS; } if (adj_rx_fifo_full_thresh(us)) { int_ena |= UART_RXFIFO_FULL_INT_ENA; } } if (us->tx_buf.len > 0) int_ena |= UART_TX_INTS; WRITE_PERI_REG(UART_INT_ENA(us->uart_no), int_ena); }
void esp_uart_print_status(void *arg) { struct esp_uart_state *us = (struct esp_uart_state *) arg; struct esp_uart_stats *s = &us->stats; struct esp_uart_stats *ps = &us->prev_stats; int uart_no = us->cfg->uart_no; fprintf( stderr, "UART%d ints %u/%u/%u; rx en %d bytes %u buf %u fifo %u, ovf %u, lcs %u; " "tx %u %u %u, thr %u; hf %u i 0x%03x ie 0x%03x cts %d\n", uart_no, s->ints - ps->ints, s->rx_ints - ps->rx_ints, s->tx_ints - ps->tx_ints, us->rx_enabled, s->rx_bytes - ps->rx_bytes, us->rx_buf.used, rx_fifo_len(us->cfg->uart_no), s->rx_overflows - ps->rx_overflows, s->rx_linger_conts - ps->rx_linger_conts, s->tx_bytes - ps->tx_bytes, us->tx_buf.used, tx_fifo_len(us->cfg->uart_no), s->tx_throttles - ps->tx_throttles, system_get_free_heap_size(), READ_PERI_REG(UART_INT_RAW(uart_no)), READ_PERI_REG(UART_INT_ENA(uart_no)), cts(uart_no)); memcpy(ps, s, sizeof(*s)); }
void HardwareSerial::begin(const uint32_t baud/* = 9600*/) { //TODO: Move to params! UartDev.baut_rate = (UartBautRate)baud; UartDev.parity = NONE_BITS; UartDev.exist_parity = STICK_PARITY_DIS; UartDev.stop_bits = ONE_STOP_BIT; UartDev.data_bits = EIGHT_BITS; ETS_UART_INTR_ATTACH((void*)uart0_rx_intr_handler, &(UartDev.rcv_buff)); PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); uart_div_modify(uart, UART_CLK_FREQ / (UartDev.baut_rate)); WRITE_PERI_REG(UART_CONF0(uart), UartDev.exist_parity | UartDev.parity | (UartDev.stop_bits << UART_STOP_BIT_NUM_S) | (UartDev.data_bits << UART_BIT_NUM_S)); //clear rx and tx fifo,not ready SET_PERI_REG_MASK(UART_CONF0(uart), UART_RXFIFO_RST | UART_TXFIFO_RST); CLEAR_PERI_REG_MASK(UART_CONF0(uart), UART_RXFIFO_RST | UART_TXFIFO_RST); //set rx fifo trigger WRITE_PERI_REG(UART_CONF1(uart), (UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S); //clear all interrupt WRITE_PERI_REG(UART_INT_CLR(uart), 0xffff); //enable rx_interrupt SET_PERI_REG_MASK(UART_INT_ENA(uart), UART_RXFIFO_FULL_INT_ENA); ETS_UART_INTR_ENABLE(); delay(10); Serial.println("\r\n"); // after SPAM :) }
/****************************************************************************** * FunctionName : uart0_rx_intr_handler * Description : Internal used function * UART0 interrupt handler, add self handle code inside * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg * Returns : NONE *******************************************************************************/ static void // must not use ICACHE_FLASH_ATTR ! uart0_rx_intr_handler(void *para) { // we assume that uart1 has interrupts disabled (it uses the same interrupt vector) uint8 uart_no = UART0; const uint32 one_sec = 1000000; // one second in usecs // we end up largely ignoring framing errors and we just print a warning every second max if (READ_PERI_REG(UART_INT_RAW(uart_no)) & UART_FRM_ERR_INT_RAW) { uint32 now = system_get_time(); if (last_frm_err == 0 || (now - last_frm_err) > one_sec) { #ifdef UART_DBG os_printf("UART framing error (bad baud rate?)\n"); #endif last_frm_err = now; } // clear rx fifo (apparently this is not optional at this point) SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST); CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST); // reset framing error WRITE_PERI_REG(UART_INT_CLR(UART0), UART_FRM_ERR_INT_CLR); // once framing errors are gone for 10 secs we forget about having seen them } else if (last_frm_err != 0 && (system_get_time() - last_frm_err) > 10*one_sec) { last_frm_err = 0; } if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST) || UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) { #ifdef UART_DBG os_printf("stat:%02X",*(uint8 *)UART_INT_ENA(uart_no)); #endif ETS_UART_INTR_DISABLE(); system_os_post(recvTaskPrio, 0, 0); } }
uint32_t esp_uart_int_mask(int uart_no) { return READ_PERI_REG(UART_INT_ENA(uart_no)); }
void miot_uart_dev_deinit(struct miot_uart_state *us) { WRITE_PERI_REG(UART_INT_ENA(us->uart_no), 0); s_us[us->uart_no] = NULL; }
int esp_uart_init(struct esp_uart_config *cfg) { if (cfg == NULL || !esp_uart_validate_config(cfg)) return 0; struct esp_uart_state *us = s_us[cfg->uart_no]; if (us != NULL) { s_us[cfg->uart_no] = NULL; esp_uart_deinit(us); } us = calloc(1, sizeof(*us)); us->cfg = cfg; cs_rbuf_init(&us->rx_buf, cfg->rx_buf_size); cs_rbuf_init(&us->tx_buf, cfg->tx_buf_size); ETS_INTR_DISABLE(ETS_UART_INUM); uart_div_modify(cfg->uart_no, UART_CLK_FREQ / cfg->baud_rate); if (cfg->uart_no == 0) { PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); if (cfg->swap_rxtx_ctsrts) { SET_PERI_REG_MASK(PERIPHS_DPORT_BASEADDR + HOST_INF_SEL, PERI_IO_UART0_PIN_SWAP); } else { CLEAR_PERI_REG_MASK(PERIPHS_DPORT_BASEADDR + HOST_INF_SEL, PERI_IO_UART0_PIN_SWAP); } } else { PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO2_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); if (cfg->swap_rxtx_ctsrts) { SET_PERI_REG_MASK(PERIPHS_DPORT_BASEADDR + HOST_INF_SEL, PERI_IO_UART1_PIN_SWAP); } else { CLEAR_PERI_REG_MASK(PERIPHS_DPORT_BASEADDR + HOST_INF_SEL, PERI_IO_UART1_PIN_SWAP); } } unsigned int conf0 = 0b011100; /* 8-N-1 */ if (cfg->tx_fc_ena) { conf0 |= UART_TX_FLOW_EN; PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_U0CTS); } WRITE_PERI_REG(UART_CONF0(cfg->uart_no), conf0); unsigned int conf1 = cfg->rx_fifo_full_thresh; conf1 |= (cfg->tx_fifo_empty_thresh << 8); if (cfg->rx_fifo_alarm >= 0) { conf1 |= UART_RX_TOUT_EN | ((cfg->rx_fifo_alarm & 0x7f) << 24); } if (cfg->rx_fc_ena && cfg->rx_fifo_fc_thresh > 0) { /* UART_RX_FLOW_EN will be set in uart_start. */ conf1 |= ((cfg->rx_fifo_fc_thresh & 0x7f) << 16); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); } WRITE_PERI_REG(UART_CONF1(cfg->uart_no), conf1); if (cfg->status_interval_ms > 0) { os_timer_disarm(&us->status_timer); os_timer_setfn(&us->status_timer, esp_uart_print_status, us); os_timer_arm(&us->status_timer, cfg->status_interval_ms, 1 /* repeat */); } s_us[cfg->uart_no] = us; /* Start with TX and RX ints disabled. */ WRITE_PERI_REG(UART_INT_ENA(cfg->uart_no), UART_INFO_INTS); ETS_UART_INTR_ATTACH(esp_uart_isr, NULL); ETS_INTR_ENABLE(ETS_UART_INUM); return 1; }
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; }
void UART_SetIntrEna(UART_Port uart_no, uint32 ena_mask) { SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask); }