/** * @brief Send data to slave(ESP8266 register of RD_STATUS or WR_STATUS). * */ void ICACHE_FLASH_ATTR SPIMasterSendStatus (SpiNum spiNum, uint8_t data) { if (spiNum > SpiNum_HSPI) { return; } while (READ_PERI_REG(SPI_CMD(spiNum)) & SPI_USR) ; // Enable MOSI SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI); CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR); // 8bits cmd, 0x04 is eps8266 slave write cmd value WRITE_PERI_REG(SPI_USER2(spiNum), ((7 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | MASTER_WRITE_STATUS_TO_SLAVE_CMD); // Set data send buffer length. SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MOSI_BITLEN, ( (sizeof (data) << 3) - 1), SPI_USR_MOSI_BITLEN_S); WRITE_PERI_REG(SPI_W0(spiNum), (uint32 ) (data)); // Start SPI SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR); }
/** * @brief Receive status register from slave(ESP8266). * */ int ICACHE_FLASH_ATTR SPIMasterRecvStatus (SpiNum spiNum) { if (spiNum > SpiNum_HSPI) { return -1; } while (READ_PERI_REG(SPI_CMD(spiNum)) & SPI_USR) ; // Enable MISO SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO); CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI | SPI_USR_DUMMY | SPI_USR_ADDR); // 8bits cmd, 0x06 is eps8266 slave read status cmd value WRITE_PERI_REG(SPI_USER2(spiNum), ((7 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | MASTER_READ_STATUS_FROM_SLAVE_CMD); // Set revcive buffer length. SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MISO_BITLEN, 7, SPI_USR_MISO_BITLEN_S); // start spi module. SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR); while (READ_PERI_REG(SPI_CMD(spiNum)) & SPI_USR) ; uint8_t data = (uint8) (READ_PERI_REG(SPI_W0(spiNum)) & 0xff); return (uint8) (READ_PERI_REG(SPI_W0(spiNum)) & 0xff); }
bool miot_uart_dev_init(struct miot_uart_state *us) { struct miot_uart_config *cfg = us->cfg; if (!esp_uart_validate_config(cfg)) return false; ETS_INTR_DISABLE(ETS_UART_INUM); uart_div_modify(us->uart_no, UART_CLK_FREQ / cfg->baud_rate); if (us->uart_no == 0) { PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); if (cfg->swap_rxcts_txrts) { 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_rxcts_txrts) { 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(us->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(us->uart_no), conf1); s_us[us->uart_no] = us; /* Start with TX and RX ints disabled. */ WRITE_PERI_REG(UART_INT_ENA(us->uart_no), UART_INFO_INTS); ETS_UART_INTR_ATTACH(esp_uart_isr, NULL); ETS_INTR_ENABLE(ETS_UART_INUM); return true; }
/** * @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio * @param cal_clk which clock to calibrate * @param slowclk_cycles number of slow clock cycles to count * @return number of XTAL clock cycles within the given number of slow clock cycles */ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) { /* Enable requested clock (150k clock is always on) */ int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); } if (cal_clk == RTC_CAL_8MD256) { SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); } /* Prepare calibration */ REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk); CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING); REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles); /* Figure out how long to wait for calibration to finish */ uint32_t expected_freq; rtc_slow_freq_t slow_freq = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); if (cal_clk == RTC_CAL_32K_XTAL || (cal_clk == RTC_CAL_RTC_MUX && slow_freq == RTC_SLOW_FREQ_32K_XTAL)) { expected_freq = 32768; /* standard 32k XTAL */ } else if (cal_clk == RTC_CAL_8MD256 || (cal_clk == RTC_CAL_RTC_MUX && slow_freq == RTC_SLOW_FREQ_8MD256)) { expected_freq = RTC_FAST_CLK_FREQ_APPROX / 256; } else { expected_freq = 150000; /* 150k internal oscillator */ } uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq); /* Start calibration */ CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); /* Wait the expected time calibration should take. * TODO: if running under RTOS, and us_time_estimate > RTOS tick, use the * RTOS delay function. */ ets_delay_us(us_time_estimate); /* Wait for calibration to finish up to another us_time_estimate */ int timeout_us = us_time_estimate; while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY) && timeout_us > 0) { timeout_us--; ets_delay_us(1); } REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state); if (cal_clk == RTC_CAL_8MD256) { CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); } if (timeout_us == 0) { /* timed out waiting for calibration */ return 0; } return REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE); }
esp_err_t spi_set_clk_div(spi_host_t host, spi_clk_div_t *clk_div) { SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); SPI_CHECK(clk_div, "parameter pointer is empty", ESP_ERR_INVALID_ARG); ENTER_CRITICAL(); if (SPI_MASTER_MODE == spi_object[host]->mode) { if (SPI_80MHz_DIV == *clk_div) { switch (host) { case CSPI_HOST: { SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYS_CLK); } break; case HSPI_HOST: { SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK); } break; } SPI[host]->clock.clk_equ_sysclk = true; } else { // Configure the IO_MUX clock (required, otherwise the clock output will be confusing) switch (host) { case CSPI_HOST: { CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYS_CLK); } break; case HSPI_HOST: { CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK); } break; } // FRE(SCLK) = clk_equ_sysclk ? 80MHz : APB_CLK(80MHz) / clkdiv_pre / clkcnt SPI[host]->clock.clk_equ_sysclk = false; SPI[host]->clock.clkdiv_pre = 0; SPI[host]->clock.clkcnt_n = *clk_div - 1; // In the master mode clkcnt_h = floor((clkcnt_n+1)/2-1). In the slave mode it must be 0 SPI[host]->clock.clkcnt_h = *clk_div / 2 - 1; // In the master mode clkcnt_l = clkcnt_n. In the slave mode it must be 0 SPI[host]->clock.clkcnt_l = *clk_div - 1; } } else { // Slave mode must be set to 0 SPI[host]->clock.val = 0; } EXIT_CRITICAL(); return ESP_OK; }
/****************************************************************************** * 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_PULLDWN_DIS(PERIPHS_IO_MUX_GPIO2_U); 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_PULLUP_DIS (PERIPHS_IO_MUX_U0TXD_U); //PIN_PULLDWN_DIS(PERIPHS_IO_MUX_U0TXD_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); PIN_PULLUP_DIS (PERIPHS_IO_MUX_U0RXD_U); //PIN_PULLDWN_DIS(PERIPHS_IO_MUX_U0RXD_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, 0); // FUNC_U0RXD==0 } 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 80 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), ((80 & 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); }
uint64_t rtc_time_get(void) { SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE); while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) { ets_delay_us(1); // might take 1 RTC slowclk period, don't flood RTC bus } SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_TIME_VALID_INT_CLR); uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG); t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32; return t; }
//esp8266 slave isr handle funtion,tiggered when any transmission is finished. //the function is registered in spi_slave_init. static void ICACHE_FLASH_ATTR spi_slave_isr_handler(void *para) { uint32 regvalue; if(READ_PERI_REG(0x3ff00020)&BIT4) { //following 3 lines is to clear isr signal CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI), 0x3ff); } else if(READ_PERI_REG(0x3ff00020)&BIT7) //bit7 is for hspi isr, { regvalue=READ_PERI_REG(SPI_SLAVE(HSPI)); CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_TRANS_DONE_EN| SPI_SLV_WR_STA_DONE_EN| SPI_SLV_RD_STA_DONE_EN| SPI_SLV_WR_BUF_DONE_EN| SPI_SLV_RD_BUF_DONE_EN); SET_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_SYNC_RESET); CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_TRANS_DONE| SPI_SLV_WR_STA_DONE| SPI_SLV_RD_STA_DONE| SPI_SLV_WR_BUF_DONE| SPI_SLV_RD_BUF_DONE); SET_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_TRANS_DONE_EN| SPI_SLV_WR_STA_DONE_EN| SPI_SLV_RD_STA_DONE_EN| SPI_SLV_WR_BUF_DONE_EN| SPI_SLV_RD_BUF_DONE_EN); if(regvalue&SPI_SLV_WR_BUF_DONE) { uint32_t i, reg, recv_data; GPIO_OUTPUT_SET(0, 0); for(reg = SPI_W0(HSPI); reg < SPI_W8(HSPI); reg += 4) { recv_data = READ_PERI_REG(reg); for(i = 0; i < 4; ++i, ++idx, recv_data >>= 8) spi_data[idx] = recv_data & 0xff; } /* TODO: post task event ... * * system_os_post(USER_TASK_PRIO_1, ut_sig_mosi, (ETSParam)spi_data); * */ GPIO_OUTPUT_SET(0, 1); }
void IRAM_ATTR esp_cpu_stall(int cpu_id) { if (cpu_id == 1) { CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M); SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_APPCPU_C1_S); CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M); SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_APPCPU_C0_S); } else { CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M); SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_PROCPU_C1_S); CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M); SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_PROCPU_C0_S); } }
void miot_uart_dev_set_rx_enabled(struct miot_uart_state *us, bool enabled) { int uart_no = us->uart_no; if (enabled) { if (us->cfg->rx_fc_ena) { SET_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); } SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RX_INTS); } else { if (us->cfg->rx_fc_ena) { /* With UART_SW_RTS = 0 in CONF0 this throttles RX (sets RTS = 1). */ CLEAR_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); } CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RX_INTS); } }
void mgos_uart_hal_set_rx_enabled(struct mgos_uart_state *us, bool enabled) { int uart_no = us->uart_no; if (enabled) { if (us->cfg.rx_fc_type == MGOS_UART_FC_HW) { SET_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); } SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RX_INTS); } else { if (us->cfg.rx_fc_type == MGOS_UART_FC_HW) { /* With UART_SW_RTS = 0 in CONF0 this throttles RX (sets RTS = 1). */ CLEAR_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); } CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RX_INTS); } }
void some_timer_func(void *arg) // in Arduino this is loop the main loop { PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_U0CTS);//CONFIG MTCK PIN FUNC TO U0CTS PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);//CONFIG MTDO PIN FUNC TO U0RTS SET_PERI_REG_MASK(0x3ff00028 , BIT2);//SWAP PIN : U0TXD<==>U0RTS(MTDO) , U0RXD<==>U0CTS(MTCK) os_printf("pins activated"); }
void ws2812_init(int gpioNum) { SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_RMT_CLK_EN); CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_RMT_RST); PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpioNum], 2); gpio_matrix_out(gpioNum, RMT_SIG_OUT0_IDX + RMTCHANNEL, 0, 0); gpio_set_direction(gpioNum, GPIO_MODE_OUTPUT); ws2812_initRMTChannel(RMTCHANNEL); RMT.tx_lim_ch[RMTCHANNEL].limit = MAX_PULSES; RMT.int_ena.ch0_tx_thr_event = 1; RMT.int_ena.ch0_tx_end = 1; ws2812_bits[0].level0 = 1; ws2812_bits[0].level1 = 0; ws2812_bits[0].duration0 = PULSE_T0H; ws2812_bits[0].duration1 = PULSE_T0L; ws2812_bits[1].level0 = 1; ws2812_bits[1].level1 = 0; ws2812_bits[1].duration0 = PULSE_T1H; ws2812_bits[1].duration1 = PULSE_T1L; esp_intr_alloc(ETS_RMT_INTR_SOURCE, 0, ws2812_handleInterrupt, NULL, &rmt_intr_handle); return; }
FAST static void rx_isr(void *param) { /* TODO(alashkin): add errors checking */ unsigned int peri_reg = READ_PERI_REG(UART_INTR_STATUS(UART_MAIN)); static volatile int tail = 0; if ((peri_reg & UART_RXBUF_FULL) != 0 || (peri_reg & UART_RX_NEW) != 0) { int char_count, i; CLEAR_PERI_REG_MASK(UART_CTRL_INTR(UART_MAIN), UART_RXBUF_FULL | UART_RX_NEW); WRITE_PERI_REG(UART_CLEAR_INTR(UART_MAIN), UART_RXBUF_FULL | UART_RX_NEW); char_count = READ_PERI_REG(UART_DATA_STATUS(UART_MAIN)) & 0x000000FF; /* TODO(mkm): handle overrun */ for (i = 0; i < char_count; i++, tail = (tail + 1) % RX_BUFFER_SIZE) { rx_buf[tail] = READ_PERI_REG(UART_BUF(UART_MAIN)) & 0xFF; if (rx_buf[tail] == UART_SIGINT_CHAR && uart_interrupt_cb) { /* swallow the intr byte */ tail = (tail - 1) % RX_BUFFER_SIZE; uart_interrupt_cb(UART_SIGINT_CHAR); } } WRITE_PERI_REG(UART_CLEAR_INTR(UART_MAIN), UART_RXBUF_FULL | UART_RX_NEW); SET_PERI_REG_MASK(UART_CTRL_INTR(UART_MAIN), UART_RXBUF_FULL | UART_RX_NEW); #ifndef RTOS_SDK system_os_post(TASK_PRIORITY, 0, tail); #else rtos_dispatch_char_handler(tail); #endif } }
/** * @brief Enable SPI interrupt source. * */ void ICACHE_FLASH_ATTR SPIIntEnable(SpiNum spiNum, SpiIntSrc intSrc) { if (spiNum > SpiNum_HSPI) { return; } SET_PERI_REG_MASK(SPI_SLAVE(spiNum), (intSrc << 5)); }
static int32 rx_buff_load_done(uint16 rx_len) { union sdio_slave_status sdio_sta; if(rx_len == 0) { return 0; } if(rx_len > rx_que.blocksize) { rx_len = rx_que.blocksize; } //os_memcpy(rx_que.buf_ptr,data,rx_len); /////config rx queue information rx_que.blocksize=RX_BUFFER_SIZE; rx_que.datalen=rx_len + SDIO_TOKEN_SIZE; rx_que.eof=1; rx_que.owner=1; #ifdef SDIO_DEBUG sum_len += rx_que.datalen; #endif //ETS_SDIO_INTR_DISABLE(); //available_buffer_amount--; /////modify sdio status reg sdio_sta.word_value=READ_PERI_REG(SLC_HOST_CONF_W2); sdio_sta.elm_value.rd_empty=0; sdio_sta.elm_value.intr_no |= RX_AVAILIBLE; sdio_sta.elm_value.rx_length=rx_len; SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START); //rx buffer is ready for being read WRITE_PERI_REG(SLC_HOST_CONF_W2, sdio_sta.word_value); //update sdio status register //ETS_SDIO_INTR_ENABLE(); return rx_len; }
/****************************************************************************** * FunctionName : spi_lcd_mode_init * Description : SPI master initial function for driving LCD TM035PDZV36 * Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid *******************************************************************************/ void spi_lcd_mode_init(uint8 spi_no) { uint32 regvalue; if(spi_no>1) return; //handle invalid input number //bit9 of PERIPHS_IO_MUX should be cleared when HSPI clock doesn't equal CPU clock //bit8 of PERIPHS_IO_MUX should be cleared when SPI clock doesn't equal CPU clock if(spi_no==SPI){ WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005); //clear bit9,and bit8 PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode }else if(spi_no==HSPI){ WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9 PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode } SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND); CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE); // SPI clock=CPU clock/8 WRITE_PERI_REG(SPI_CLOCK(spi_no), ((1&SPI_CLKDIV_PRE)<<SPI_CLKDIV_PRE_S)| ((3&SPI_CLKCNT_N)<<SPI_CLKCNT_N_S)| ((1&SPI_CLKCNT_H)<<SPI_CLKCNT_H_S)| ((3&SPI_CLKCNT_L)<<SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div }
/****************************************************************************** * 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) { os_printf("UART framing error (bad baud rate?)\n"); 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)) { //DBG_UART("stat:%02X",*(uint8 *)UART_INT_ENA(uart_no)); ETS_UART_INTR_DISABLE(); post_usr_task(uart_recvTaskNum, 0); } }
/* @defgroup SPI hardware implementation * @brief transfer32() * * private method used by transfer(byte) and transfer16(sort) * to send/recv one uint32_t * * SPI transfer is based on a simultaneous send and receive: * the received data is returned in receivedVal (or receivedVal16). * * receivedVal = SPI.transfer(val) : single byte * receivedVal16 = SPI.transfer16(val16) : single short */ uint32 SPIClass::transfer32(uint32 data, uint8 bits) { uint32_t regvalue = READ_PERI_REG(SPI_USER(SPI_NO)) & (SPI_WR_BYTE_ORDER | SPI_RD_BYTE_ORDER | SPI_CK_OUT_EDGE); while(READ_PERI_REG(SPI_CMD(SPI_NO))&SPI_USR); regvalue |= SPI_USR_MOSI | SPI_DOUTDIN | SPI_CK_I_EDGE; WRITE_PERI_REG(SPI_USER(SPI_NO), regvalue); WRITE_PERI_REG(SPI_USER1(SPI_NO), ( (bits-1 & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S ) | ( (bits-1 & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S ) ); // copy data to W0 if(READ_PERI_REG(SPI_USER(SPI_NO))&SPI_WR_BYTE_ORDER) { WRITE_PERI_REG(SPI_W0(SPI_NO), data<<(32-bits)); } else { WRITE_PERI_REG(SPI_W0(SPI_NO), data); } SET_PERI_REG_MASK(SPI_CMD(SPI_NO), SPI_USR); // send while (READ_PERI_REG(SPI_CMD(SPI_NO)) & SPI_USR); // wait a while before reading the register into the buffer // delayMicroseconds(2); if(READ_PERI_REG(SPI_USER(SPI_NO))&SPI_RD_BYTE_ORDER) { return READ_PERI_REG(SPI_W0(SPI_NO)) >> (32-bits); //Assuming data in is written to MSB. TBC } else { return READ_PERI_REG(SPI_W0(SPI_NO)); //Read in the same way as DOUT is sent. Note existing contents of SPI_W0 remain unless overwritten!
//Set the I2S sample rate, in HZ void i2sSetRate(int rate) { //Find closest divider int bestbck=0, bestfreq=0; int tstfreq; int i; //Calculate the base divider for 16 bits of data int div=(BASEFREQ/(rate*32)); //The base divider can be off by as much as <1 Compensate by trying to make the amount of bytes in the //i2s cycle more than 16. Do this by trying the amounts from 16 to 32 and keeping the one that fits best. for (i=16; i<32; i++) { tstfreq=BASEFREQ/(div*i*2); // printf("Best (%d,%d) cur (%d,%d) div %d\n", bestbck, bestfreq, i, tstfreq, ABS(rate-tstfreq)); if (ABS(rate-tstfreq)<ABS(rate-bestfreq)) { bestbck=i; bestfreq=tstfreq; } } // printf("ReqRate %d Div %d Bck %d Frq %d\n", rate, div, bestbck, BASEFREQ/(div*bestbck*2)); CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD| (I2S_BITS_MOD<<I2S_BITS_MOD_S)| (I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)| (I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S)); SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD| I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT| (((bestbck-1)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)| (((div-1)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)); }
//only when USART_HardwareFlowControl_RTS is set , will the rx_thresh value be set. void UART_SetFlowCtrl(UART_Port uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh) { if (flow_ctrl & USART_HardwareFlowControl_RTS) { PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); SET_PERI_REG_BITS(UART_CONF1(uart_no), UART_RX_FLOW_THRHD, rx_thresh, UART_RX_FLOW_THRHD_S); SET_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); } else { CLEAR_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); } if (flow_ctrl & USART_HardwareFlowControl_CTS) { PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN); } else { CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN); } }
/** * @brief Select SPI CS pin. * */ void ICACHE_FLASH_ATTR SPICsPinSelect(SpiNum spiNum, SpiPinCS pinCs) { if (spiNum > SpiNum_HSPI) { return; } // clear select SET_PERI_REG_BITS(SPI_PIN(spiNum), 3, 0, 0); SET_PERI_REG_MASK(SPI_PIN(spiNum), pinCs); }
uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt) { REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt); WRITE_PERI_REG(RTC_CNTL_SLP_REJECT_CONF_REG, reject_opt); /* Start entry into sleep mode */ SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN); while (GET_PERI_REG_MASK(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) == 0) { ; } /* In deep sleep mode, we never get here */ uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW); SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR); return reject; }
void gpio_config(GPIO_ConfigTypeDef *pGPIOConfig) { uint32 gpio_pin_mask = pGPIOConfig->GPIO_Pin; uint32 gpio_pin_mask_high = pGPIOConfig->GPIO_Pin_high; uint32 io_reg; uint8 io_num = 0; uint32 pin_reg; uint32 bit_valid; if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Input) { GPIO_AS_INPUT(gpio_pin_mask); GPIO_AS_INPUT_HIGH(gpio_pin_mask_high); } else if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Output) { GPIO_AS_OUTPUT(gpio_pin_mask); GPIO_AS_OUTPUT_HIGH(gpio_pin_mask_high); } do { bit_valid = (io_num >= 32 ? (gpio_pin_mask_high & (0x1 << (io_num - 32))) : (gpio_pin_mask & (0x1 << io_num))); if (bit_valid && (io_reg = GPIO_PIN_REG[io_num])) { if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Input) { SET_PERI_REG_MASK(io_reg, FUN_IE); } //for ESP32 function 2 of every pad is allways GPIO func PIN_FUNC_SELECT(io_reg, 2); if (pGPIOConfig->GPIO_Pullup) { PIN_PULLUP_EN(io_reg); } else { PIN_PULLUP_DIS(io_reg); } if (pGPIOConfig->GPIO_Pulldown) { PIN_PULLDWN_EN(io_reg); } else { PIN_PULLDWN_DIS(io_reg); } if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Out_OD) { portENTER_CRITICAL(); pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(io_num)); //pin_reg &= (~GPIO_GPIO_PIN0_PAD_DRIVER); pin_reg |= GPIO_GPIO_PIN0_PAD_DRIVER; GPIO_REG_WRITE(GPIO_PIN_ADDR(io_num), pin_reg); portEXIT_CRITICAL(); } gpio_pin_intr_state_set(io_num, pGPIOConfig->GPIO_IntrType); } io_num++; } while (io_num < GPIO_PIN_COUNT); }
/** * @brief Configurate slave prepare for receive data. * */ int ICACHE_FLASH_ATTR SPISlaveRecvData(SpiNum spiNum) { if ((spiNum > SpiNum_HSPI)) { return -1; } // Enable slave transmission liston SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR); return 0; }
/****************************************************************************** * FunctionName : cache_flush * Description : clear all the cpu cache data for stability test. *******************************************************************************/ void cache_flush(void) { while(READ_PERI_REG(CACHE_FLASH_CTRL_REG)&CACHE_EMPTY_FLAG_BIT) { CLEAR_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT); SET_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT); } while(!(READ_PERI_REG(CACHE_FLASH_CTRL_REG)&CACHE_EMPTY_FLAG_BIT)); CLEAR_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT); }
void UART_SetParity(UART_Port uart_no, UART_ParityMode Parity_mode) { CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY | UART_PARITY_EN); if (Parity_mode == USART_Parity_None) { } else { SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode | UART_PARITY_EN); } }
void esp_uart_set_rx_enabled(int uart_no, int enabled) { struct esp_uart_state *us = s_us[uart_no]; if (us == NULL) return; struct esp_uart_config *cfg = us->cfg; if (enabled) { if (cfg->rx_fc_ena) { SET_PERI_REG_MASK(UART_CONF1(cfg->uart_no), UART_RX_FLOW_EN); } SET_PERI_REG_MASK(UART_INT_ENA(cfg->uart_no), UART_RX_INTS); us->rx_enabled = 1; } else { if (cfg->rx_fc_ena) { /* With UART_SW_RTS = 0 in CONF0 this throttles RX (sets RTS = 1). */ CLEAR_PERI_REG_MASK(UART_CONF1(cfg->uart_no), UART_RX_FLOW_EN); } CLEAR_PERI_REG_MASK(UART_INT_ENA(cfg->uart_no), UART_RX_INTS); us->rx_enabled = 0; } }
int do_flash_write(uint32_t addr, uint32_t len, uint32_t erase) { struct uart_buf ub; uint8_t digest[16]; uint32_t num_written = 0, num_erased = 0; struct MD5Context ctx; MD5Init(&ctx); if (addr % FLASH_SECTOR_SIZE != 0) return 0x32; if (len % FLASH_SECTOR_SIZE != 0) return 0x33; if (SPIUnlock() != 0) return 0x34; ub.nr = 0; ub.pr = ub.pw = ub.data; ets_isr_attach(ETS_UART_INUM, uart_isr, &ub); SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RX_INTS); ets_isr_unmask(1 << ETS_UART_INUM); SLIP_send(&num_written, 4); while (num_written < len) { volatile uint32_t *nr = &ub.nr; /* Prepare the space ahead. */ while (erase && num_erased < num_written + SPI_WRITE_SIZE) { const uint32_t num_left = (len - num_erased); if (num_left > FLASH_BLOCK_SIZE && addr % FLASH_BLOCK_SIZE == 0) { if (SPIEraseBlock(addr / FLASH_BLOCK_SIZE) != 0) return 0x35; num_erased += FLASH_BLOCK_SIZE; } else { /* len % FLASH_SECTOR_SIZE == 0 is enforced, no further checks needed */ if (SPIEraseSector(addr / FLASH_SECTOR_SIZE) != 0) return 0x36; num_erased += FLASH_SECTOR_SIZE; } } /* Wait for data to arrive. */ while (*nr < SPI_WRITE_SIZE) { } MD5Update(&ctx, ub.pr, SPI_WRITE_SIZE); if (SPIWrite(addr, ub.pr, SPI_WRITE_SIZE) != 0) return 0x37; ets_intr_lock(); *nr -= SPI_WRITE_SIZE; ets_intr_unlock(); num_written += SPI_WRITE_SIZE; addr += SPI_WRITE_SIZE; ub.pr += SPI_WRITE_SIZE; if (ub.pr >= ub.data + UART_BUF_SIZE) ub.pr = ub.data; SLIP_send(&num_written, 4); } ets_isr_mask(1 << ETS_UART_INUM); MD5Final(digest, &ctx); SLIP_send(digest, 16); return 0; }
/* This is a very, very, very hacked up LCD routine which ends up basically doing a memcpy from sbuf to rbuf. */ static void sendRecvBufDma(uint16_t *sbuf, uint16_t *rbuf, int len) { //Fill DMA descriptor dmaDesc[0].length = len * 2; dmaDesc[0].size = len * 2; dmaDesc[0].owner = 1; dmaDesc[0].sosf = 0; dmaDesc[0].buf = (uint8_t *)sbuf; dmaDesc[0].offset = 0; //unused in hw dmaDesc[0].empty = 0; dmaDesc[0].eof = 1; dmaDesc[1].length = len * 2; dmaDesc[1].size = len * 2; dmaDesc[1].owner = 1; dmaDesc[1].sosf = 0; dmaDesc[1].buf = (uint8_t *)rbuf; dmaDesc[1].offset = 0; //unused in hw dmaDesc[1].empty = 0; dmaDesc[1].eof = 1; //Reset DMA SET_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST); CLEAR_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST); //Reset I2S FIFO SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET); CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET); //Set desc addr CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_ADDR); SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), ((uint32_t)(&dmaDesc[0]))&I2S_OUTLINK_ADDR); CLEAR_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_ADDR); SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), ((uint32_t)(&dmaDesc[1]))&I2S_INLINK_ADDR); SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(0), I2S_DSCR_EN); //Enable DMA mode WRITE_PERI_REG(I2S_RXEOF_NUM_REG(0), len); //Enable and configure DMA WRITE_PERI_REG(I2S_LC_CONF_REG(0), I2S_OUT_DATA_BURST_EN | I2S_OUT_EOF_MODE | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN | I2S_INDSCR_BURST_EN | I2S_MEM_TRANS_EN); //Start transmission SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START); SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_START); SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START); //Clear int flags WRITE_PERI_REG(I2S_INT_CLR_REG(0), 0xFFFFFFFF); }