/**
 * @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);
}
Пример #3
0
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;
}
Пример #4
0
/**
 * @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);
}
Пример #5
0
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;
}
Пример #6
0
/******************************************************************************
 * 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);
}
Пример #7
0
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;
}
Пример #8
0
//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);
        }
Пример #9
0
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);
    }
}
Пример #10
0
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);
  }
}
Пример #11
0
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");
}
Пример #13
0
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;
}
Пример #14
0
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
  }
}
Пример #15
0
/**
 * @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));
}
Пример #16
0
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;
}
Пример #17
0
/******************************************************************************
 * 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
	
}
Пример #18
0
/******************************************************************************
 * 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);
  }
}
Пример #19
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!
Пример #20
0
//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));
}
Пример #21
0
//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);
    }
}
Пример #22
0
/**
 * @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);
}
Пример #23
0
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;
}
Пример #24
0
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);
}
Пример #25
0
/**
 * @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;
}
Пример #26
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);
}
Пример #27
0
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);
    }
}
Пример #28
0
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;
  }
}
Пример #29
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;
}
Пример #30
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);
}