Пример #1
0
/**
 * @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);
}
Пример #2
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
	
}
Пример #3
0
static void gpio_intr_reset(uint32 intr_num, uint8 reset)
{
    if (intr_num > 7) {
        return;
    }

    //bit PCNT_CNT_PAUSE_U0-7
    CLEAR_PERI_REG_MASK(PCNT_CTRL, BIT(intr_num * 2 + 1));

    //bit PCNT_PLUS_CNT_RST_U0-7
    if (reset) {
        SET_PERI_REG_MASK(PCNT_CTRL, BIT(intr_num * 2));
    } else {
        CLEAR_PERI_REG_MASK(PCNT_CTRL, BIT(intr_num * 2));
    }
}
Пример #4
0
/**
 * @brief Disable SPI interrupt source.
 *
 */
void ICACHE_FLASH_ATTR SPIIntDisable(SpiNum spiNum, SpiIntSrc intSrc)
{
    if (spiNum > SpiNum_HSPI) {
        return;
    }
    CLEAR_PERI_REG_MASK(SPI_SLAVE(spiNum), intSrc);
}
Пример #5
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
  }
}
Пример #6
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);
    }
}
Пример #7
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;
  }
}
Пример #8
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);
    }
}
Пример #9
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);
}
Пример #10
0
/**
 * @brief Clear all of SPI interrupt source.
 *
 */
void ICACHE_FLASH_ATTR SPIIntClear(SpiNum spiNum)
{
    if (spiNum > SpiNum_HSPI) {
        return;
    }
    CLEAR_PERI_REG_MASK(SPI_SLAVE(spiNum), SpiIntSrc_TransDone
                        | SpiIntSrc_WrStaDone
                        | SpiIntSrc_RdStaDone
                        | SpiIntSrc_WrBufDone
                        | SpiIntSrc_RdBufDone);
}
Пример #11
0
static void finishDma()
{
    //No need to finish if no DMA transfer going on
    if (!(READ_PERI_REG(I2S_FIFO_CONF_REG(0))&I2S_DSCR_EN)) {
        return;
    }

    //Wait till fifo done
    while (!(READ_PERI_REG(I2S_INT_RAW_REG(0))&I2S_TX_REMPTY_INT_RAW)) ;
    //Wait for last bytes to leave i2s xmit thing
    //ToDo: poll bit in next hw
//  for (i=0; i<(1<<8); i++);
    while (!(READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_IDLE));

    //Reset I2S for next transfer
    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
    CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START | I2S_INLINK_START);

    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);

//  for (i=0; i<(1<<8); i++);
    while ((READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_FIFO_RESET_BACK));
}
Пример #12
0
/******************************************************************************
 * FunctionName : spi_master_init
 * Description  : SPI master initial function for common byte units transmission
 * Parameters   : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
*******************************************************************************/
void ICACHE_FLASH_ATTR
    spi_master_init(uint8 spi_no)
{
	uint32 regvalue; 

	if(spi_no>1) 		return; //handle invalid input number
	
	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);

	WRITE_PERI_REG(SPI_CLOCK(spi_no), 
					((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
}
Пример #13
0
void SPIIntCfg(SpiNum spiNum, SpiIntInfo *pIntInfo)
{
    if ((spiNum > SpiNum_HSPI)
        || (NULL == pIntInfo)) {
        return;
    }
    // Clear the interrupt source and disable all of the interrupt.
    CLEAR_PERI_REG_MASK(SPI_SLAVE(spiNum), 0x3FF);
    SPIIntEnable(spiNum, pIntInfo->src);
    os_printf("src=%x\r\n,isrFunc=%x", (pIntInfo->src << 5), pIntInfo->isrFunc);
    //
    ETS_SPI_INTR_ATTACH(pIntInfo->isrFunc, NULL);
    // Enable isr
    ETS_SPI_INTR_ENABLE();    
}
Пример #14
0
void C3WireOutput::output(const uint8_t *pData) {
	// Stop DMA
	// Reset descriptor address
	SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_STOP);
	// TODO: Ideally this should be moved closer to the rest of the register access
	// But that will sometimes fail.
	// I suspect we have to wait for the SLC to actually be stopped before messing with the registers
	m_pEncoder->encode(pData, m_nLength, m_pBuffer);
	// Ideally I'd like to adjust the buffer length,
	// but that will creep out the SLC when it's not properly stopped.
	// So assume that the rest of the buffer is 0 anyway.
	// m_qBuffer.datalen = m_qBuffer.blocksize = nOutputLength * 4;

	// Adjust SLC (DMA) to point to just encoded buffer
	CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK);
	SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&m_qBuffer) & SLC_RXLINK_DESCADDR_MASK);

	// Reset FIFO, toggle pin, don't leave high
	SET_PERI_REG_MASK(I2SCONF, I2S_I2S_TX_FIFO_RESET);
	CLEAR_PERI_REG_MASK(I2SCONF, I2S_I2S_TX_FIFO_RESET);

	// Start DMA
	SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START);
}
Пример #15
0
void pwm_tim1_intr_handler()
{
	CLEAR_PERI_REG_MASK(FRC1_INT_ADDRESS, FRC1_INT_CLR_MASK);

	if (_pwm_enable)
	{
		GPIO_OUTPUT_SET(_gpio_pin_num, _pwm_lvl);
		_pwm_lvl ^= 1;
	}
	else if (_pwm_lvl == _logic_high)
	{
		_pwm_lvl = _logic_low;
		GPIO_OUTPUT_SET(_gpio_pin_num, _pwm_lvl);
	}

	WRITE_PERI_REG(FRC1_LOAD_ADDRESS, _frc1_ticks);
}
Пример #16
0
//Set the I2S sample rate, in HZ
void ICACHE_FLASH_ATTR i2sSetRate(int rate, int lockBitcount) {
	//Find closest divider 
	int bestclkmdiv, bestbckdiv, bestbits, bestfreq=0;
	int tstfreq;
	int bckdiv, clkmdiv, bits;
	/*
		CLK_I2S = 160MHz / I2S_CLKM_DIV_NUM
		BCLK = CLK_I2S / I2S_BCK_DIV_NUM
		WS = BCLK/ 2 / (16 + I2S_BITS_MOD)
		Note that I2S_CLKM_DIV_NUM must be >5 for I2S data
		I2S_CLKM_DIV_NUM - 5-127
		I2S_BCK_DIV_NUM - 2-127
		
		We also have the option to send out more than 2x16 bit per sample. Most I2S codecs will
		ignore the extra bits and in the case of the 'fake' PWM/delta-sigma outputs, they will just lower the output
		voltage a bit, so we add them when it makes sense. Some of them, however, won't accept it, that's
		why we have the option not to do this.
	*/
	for (bckdiv=2; bckdiv<128; bckdiv++) {
		for (clkmdiv=5; clkmdiv<128; clkmdiv++) {
			for (bits=16; bits<(lockBitcount?17:20); bits++) {
				tstfreq=BASEFREQ/(bckdiv*clkmdiv*bits*2);
				if (ABS(rate-tstfreq)<ABS(rate-bestfreq)) {
					bestfreq=tstfreq;
					bestclkmdiv=clkmdiv;
					bestbckdiv=bckdiv;
					bestbits=bits;
				}
			}
		}
	}

	printf("ReqRate %d MDiv %d BckDiv %d Bits %d  Frq %d\n", 
		rate, bestclkmdiv, bestbckdiv, bestbits, (int)(BASEFREQ/(bckdiv*clkmdiv*bits*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|
						((bestbits-16)<<I2S_BITS_MOD_S)|
						(((bestbckdiv)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
						(((bestclkmdiv)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S));
}
Пример #17
0
IRAM int esp_uart_dispatch_rx_top(int uart_no) {
  struct esp_uart_state *us = s_us[uart_no];
  if (us == NULL || !us->rx_enabled) return 1;
  uint32_t rxn = 0;
  cs_rbuf_t *rxb = &us->rx_buf;
  /* RX */
  if (rxb->avail > 0 && rx_fifo_len(uart_no) > 0) {
    int linger_counter = 0;
    /* 32 here is a constant measured (using system_get_time) to provide
     * linger time of rx_linger_micros. It basically means that one iteration
     * of the loop takes 3.2 us.
     *
     * Note: lingering may starve TX FIFO if the flow is bidirectional.
     * TODO(rojer): keep transmitting from tx_buf while lingering.
     */
    int max_linger = us->cfg->rx_linger_micros / 10 * 32;
#ifdef MEASURE_LINGER_TIME
    uint32_t st = system_get_time();
#endif
    while (rxb->avail > 0 && linger_counter <= max_linger) {
      int rx_len = rx_fifo_len(uart_no);
      if (rx_len > 0) {
        while (rx_len-- > 0 && rxb->avail > 0) {
          cs_rbuf_append_one(rxb, rx_byte(uart_no));
          rxn++;
        }
        if (linger_counter > 0) {
          us->stats.rx_linger_conts++;
          linger_counter = 0;
        }
      } else {
        linger_counter++;
      }
    }
#ifdef MEASURE_LINGER_TIME
    fprintf(stderr, "Time spent reading: %u us\n", system_get_time() - st);
#endif
    us->stats.rx_bytes += rxn;
  }
  int rfl = rx_fifo_len(uart_no);
  if (rfl < us->cfg->rx_fifo_full_thresh) {
    CLEAR_PERI_REG_MASK(UART_INT_CLR(uart_no), UART_RX_INTS);
  }
  return rfl == 0;
}
Пример #18
0
void mgos_uart_hal_dispatch_rx_top(struct mgos_uart_state *us) {
  int uart_no = us->uart_no;
  struct mbuf *rxb = &us->rx_buf;
  uint32_t rxn = 0;
  /* RX */
  if (mgos_uart_rxb_free(us) > 0 && esp_uart_rx_fifo_len(uart_no) > 0) {
    int linger_counter = 0;
    /* 32 here is a constant measured (using system_get_time) to provide
     * linger time of rx_linger_micros. It basically means that one iteration
     * of the loop takes 3.2 us.
     *
     * Note: lingering may starve TX FIFO if the flow is bidirectional.
     * TODO(rojer): keep transmitting from tx_buf while lingering.
     */
    int max_linger = us->cfg.rx_linger_micros / 10 * 32;
#ifdef MEASURE_LINGER_TIME
    uint32_t st = system_get_time();
#endif
    while (mgos_uart_rxb_free(us) > 0 && linger_counter <= max_linger) {
      size_t rx_len = esp_uart_rx_fifo_len(uart_no);
      if (rx_len > 0) {
        rx_len = MIN(rx_len, mgos_uart_rxb_free(us));
        if (rxb->size < rxb->len + rx_len) mbuf_resize(rxb, rxb->len + rx_len);
        while (rx_len > 0) {
          uint8_t b = rx_byte(uart_no);
          mbuf_append(rxb, &b, 1);
          rx_len--;
          rxn++;
        }
        if (linger_counter > 0) {
          us->stats.rx_linger_conts++;
          linger_counter = 0;
        }
      } else {
        linger_counter++;
      }
    }
#ifdef MEASURE_LINGER_TIME
    fprintf(stderr, "Time spent reading: %u us\n", system_get_time() - st);
#endif
    us->stats.rx_bytes += rxn;
  }
  CLEAR_PERI_REG_MASK(UART_INT_CLR(uart_no), UART_RX_INTS);
}
Пример #19
0
void UARTInit() {
	//Enable TxD pin
	PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
	
	//Set baud rate and other serial parameters to 115200,n,8,1
	uart_div_modify(0, UART_CLK_FREQ/BIT_RATE_115200);
	WRITE_PERI_REG(UART_CONF0(0), (STICK_PARITY_DIS)|(ONE_STOP_BIT << UART_STOP_BIT_NUM_S)| \
				(EIGHT_BITS << UART_BIT_NUM_S));

	//Reset tx & rx fifo
	SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
	CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
	//Clear pending interrupts
	WRITE_PERI_REG(UART_INT_CLR(0), 0xffff);

	//Install our own putchar handler
	os_install_putc1((void *)UARTPutChar);
}
Пример #20
0
static void uartRxInit()
{
    uint32_t reg_val;
    PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);

//  reg_val = READ_PERI_REG(UART_CONF1(0));
    reg_val = (1 << UART_RXFIFO_FULL_THRHD_S);
    WRITE_PERI_REG(UART_CONF1_REG(0), reg_val);
    CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_TXFIFO_EMPTY_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
    SET_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_RXFIFO_FULL_INT_ENA);

    printf("Enabling int %d\n", ETS_UART0_INUM);
    DPORT_REG_SET_FIELD(DPORT_PRO_UART_INTR_MAP_REG, DPORT_PRO_UART_INTR_MAP, ETS_UART0_INUM);
    DPORT_REG_SET_FIELD(DPORT_PRO_UART1_INTR_MAP_REG, DPORT_PRO_UART1_INTR_MAP, ETS_UART0_INUM);

    xt_set_interrupt_handler(ETS_UART0_INUM, uartIsrHdl, NULL);
    xt_ints_on(1 << ETS_UART0_INUM);

}
Пример #21
0
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);
}
Пример #22
0
int gdb_read_uart_buf(char *buf) {
  unsigned int peri_reg = READ_PERI_REG(UART_INTR_STATUS(UART_MAIN));

  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;

    for (i = 0; i < char_count; i++) {
      buf[i] = READ_PERI_REG(UART_BUF(UART_MAIN)) & 0xFF;
    }

    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);
    return char_count;
  }
  return 0;
}
Пример #23
0
void W25QXX_Write_Page(uint8 data,uint32 WriteAddr,uint16 NumByteToWrite)
{
	u16 i=0;  
	spi_mast_byte_write(SPI,0x06);
	SET_PERI_REG_MASK(SPI_PIN(SPI), SPI_CS_DIS);
	spi_mast_byte_write(SPI,0x02);
	spi_mast_byte_write(SPI,(u8)((WriteAddr)>>16));
	spi_mast_byte_write(SPI,(u8)((WriteAddr)>>8));
	spi_mast_byte_write(SPI,(u8)WriteAddr);

	while(i<NumByteToWrite)
	{
		spi_mast_byte_write(HSPI,data);
		i++;
	} 
	
	CLEAR_PERI_REG_MASK(SPI_PIN(SPI), SPI_CS_DIS);
	 
	if (i==NumByteToWrite){
		spi_mast_byte_write(HSPI,data);
	}
} 
Пример #24
0
/**
 * @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);

}
Пример #25
0
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 :)
}
Пример #26
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) {
#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);
  }
}
Пример #27
0
static void gpio_intr_init(uint32 intr_num, GPIO_INT_TYPE intr_type)
{
    uint32 cfg0_addr = PCNT_U0_CONF0 + (intr_num * 12);
    uint32 cfg1_addr = PCNT_U0_CONF1 + (intr_num * 12);
    uint32 cfg2_addr = PCNT_U0_CONF2 + (intr_num * 12);

    SET_PERI_REG_BITS(cfg0_addr, PCNT_CH1_LCTRL_MODE_U0, 0, PCNT_CH1_LCTRL_MODE_U0_S);
    SET_PERI_REG_BITS(cfg0_addr, PCNT_CH1_HCTRL_MODE_U0, 0, PCNT_CH1_HCTRL_MODE_U0_S);
    SET_PERI_REG_BITS(cfg0_addr, PCNT_CH1_POS_MODE_U0, 0, PCNT_CH1_POS_MODE_U0_S);
    SET_PERI_REG_BITS(cfg0_addr, PCNT_CH1_NEG_MODE_U0, 0, PCNT_CH1_NEG_MODE_U0_S);
    SET_PERI_REG_BITS(cfg0_addr, PCNT_CH0_LCTRL_MODE_U0, 0, PCNT_CH0_LCTRL_MODE_U0_S);
    SET_PERI_REG_BITS(cfg0_addr, PCNT_CH0_HCTRL_MODE_U0, 0, PCNT_CH0_HCTRL_MODE_U0_S);

    if (intr_type == GPIO_PIN_INTR_NEGEDGE) {
        SET_PERI_REG_BITS(cfg0_addr, PCNT_CH0_POS_MODE_U0, 0, PCNT_CH0_POS_MODE_U0_S);
        SET_PERI_REG_BITS(cfg0_addr, PCNT_CH0_NEG_MODE_U0, 1, PCNT_CH0_NEG_MODE_U0_S);
    } else if (intr_type == GPIO_PIN_INTR_POSEDGE) {
        SET_PERI_REG_BITS(cfg0_addr, PCNT_CH0_POS_MODE_U0, 1, PCNT_CH0_POS_MODE_U0_S);
        SET_PERI_REG_BITS(cfg0_addr, PCNT_CH0_NEG_MODE_U0, 0, PCNT_CH0_NEG_MODE_U0_S);
    } else if (intr_type == GPIO_PIN_INTR_ANYEDGE) {
        SET_PERI_REG_BITS(cfg0_addr, PCNT_CH0_POS_MODE_U0, 1, PCNT_CH0_POS_MODE_U0_S);
        SET_PERI_REG_BITS(cfg0_addr, PCNT_CH0_NEG_MODE_U0, 1, PCNT_CH0_NEG_MODE_U0_S);
    } else {
        SET_PERI_REG_BITS(cfg0_addr, PCNT_CH0_POS_MODE_U0, 0, PCNT_CH0_POS_MODE_U0_S);
        SET_PERI_REG_BITS(cfg0_addr, PCNT_CH0_NEG_MODE_U0, 0, PCNT_CH0_NEG_MODE_U0_S);
    }

    SET_PERI_REG_BITS(cfg1_addr, PCNT_CNT_THRES0_U0, 1, PCNT_CNT_THRES0_U0_S);
    SET_PERI_REG_BITS(cfg2_addr, PCNT_CNT_L_LIM_U0, 10, PCNT_CNT_L_LIM_U0_S);
    SET_PERI_REG_BITS(cfg2_addr, PCNT_CNT_H_LIM_U0, 10, PCNT_CNT_H_LIM_U0_S);
    CLEAR_PERI_REG_MASK(cfg0_addr, (PCNT_THR_THRES1_EN_U0 | PCNT_THR_L_LIM_EN_U0
                                    | PCNT_THR_H_LIM_EN_U0 | PCNT_THR_ZERO_EN_U0 | PCNT_FILTER_EN_U0));

    SET_PERI_REG_MASK(cfg0_addr, PCNT_THR_THRES0_EN_U0);
    SET_PERI_REG_MASK(PCNT_INT_ENA, BIT(intr_num));
}
Пример #28
0
static void lcdIfaceInit()
{
    SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
    CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);

    //Init pins to i2s functions
    SET_PERI_REG_MASK(GPIO_ENABLE_W1TS_REG, (1 << 11) | (1 << 3) | (1 << 0) | (1 << 2) | (1 << 5) | (1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 20)); //ENABLE GPIO oe_enable

    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, 0);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, 0);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, 0);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, 0);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, 0);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO18_U, 0);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, 0);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO20_U, 0);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 2); //11
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO26_U, 0); //RS

    WRITE_PERI_REG(GPIO_FUNC0_OUT_SEL_CFG_REG, (148 << GPIO_FUNC0_OUT_SEL_S));
    WRITE_PERI_REG(GPIO_FUNC2_OUT_SEL_CFG_REG, (149 << GPIO_FUNC0_OUT_SEL_S));
    WRITE_PERI_REG(GPIO_FUNC5_OUT_SEL_CFG_REG, (150 << GPIO_FUNC0_OUT_SEL_S));
    WRITE_PERI_REG(GPIO_FUNC16_OUT_SEL_CFG_REG, (151 << GPIO_FUNC0_OUT_SEL_S));
    WRITE_PERI_REG(GPIO_FUNC17_OUT_SEL_CFG_REG, (152 << GPIO_FUNC0_OUT_SEL_S));
    WRITE_PERI_REG(GPIO_FUNC18_OUT_SEL_CFG_REG, (153 << GPIO_FUNC0_OUT_SEL_S));
    WRITE_PERI_REG(GPIO_FUNC19_OUT_SEL_CFG_REG, (154 << GPIO_FUNC0_OUT_SEL_S));
    WRITE_PERI_REG(GPIO_FUNC20_OUT_SEL_CFG_REG, (155 << GPIO_FUNC0_OUT_SEL_S));
    WRITE_PERI_REG(GPIO_FUNC26_OUT_SEL_CFG_REG, (156 << GPIO_FUNC0_OUT_SEL_S)); //RS
    WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, (I2S0O_WS_OUT_IDX << GPIO_FUNC0_OUT_SEL_S));
//  WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG, (I2S0O_BCK_OUT_IDX<<GPIO_GPIO_FUNC0_OUT_SEL_S));

    //GPIO_SET_GPIO_FUNC11_OUT_INV_SEL(1); //old
    WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, READ_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG) | GPIO_FUNC11_OUT_INV_SEL);

    //Reset I2S subsystem
    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
    CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);

    WRITE_PERI_REG(I2S_CONF_REG(0), 0);//I2S_SIG_LOOPBACK);
    WRITE_PERI_REG(I2S_CONF2_REG(0), 0);

    WRITE_PERI_REG(I2S_SAMPLE_RATE_CONF_REG(0),
                   (16 << I2S_RX_BITS_MOD_S) |
                   (16 << I2S_TX_BITS_MOD_S) |
                   (1 << I2S_RX_BCK_DIV_NUM_S) |
                   (1 << I2S_TX_BCK_DIV_NUM_S));
    WRITE_PERI_REG(I2S_CLKM_CONF_REG(0),
                   I2S_CLKA_ENA | I2S_CLK_EN |
                   (1 << I2S_CLKM_DIV_A_S) |
                   (1 << I2S_CLKM_DIV_B_S) |
                   (1 << I2S_CLKM_DIV_NUM_S));
    WRITE_PERI_REG(I2S_FIFO_CONF_REG(0),
                   (32 << I2S_TX_DATA_NUM_S) |     //Low watermark for IRQ
                   (32 << I2S_RX_DATA_NUM_S));

    WRITE_PERI_REG(I2S_CONF1_REG(0), I2S_RX_PCM_BYPASS | I2S_TX_PCM_BYPASS);

    WRITE_PERI_REG(I2S_CONF_CHAN_REG(0), (2 << I2S_TX_CHAN_MOD_S) | (2 << I2S_RX_CHAN_MOD_S));

    //Invert WS to active-low
    SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RIGHT_FIRST | I2S_RX_RIGHT_FIRST);
    WRITE_PERI_REG(I2S_TIMING_REG(0), 0);
}
Пример #29
0
//Initialize I2S subsystem for DMA circular buffer use
void ICACHE_FLASH_ATTR i2sInit() {
	int x, y;
	
	underrunCnt=0;
	
	//First, take care of the DMA buffers.
	for (y=0; y<I2SDMABUFCNT; y++) {
		//Allocate memory for this DMA sample buffer.
		i2sBuf[y]=malloc(I2SDMABUFLEN*4);
		//Clear sample buffer. We don't want noise.
		for (x=0; x<I2SDMABUFLEN; x++) {
			i2sBuf[y][x]=0;
		}
	}

	//Reset DMA
	SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST|SLC_TXLINK_RST);
	CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST|SLC_TXLINK_RST);

	//Clear DMA int flags
	SET_PERI_REG_MASK(SLC_INT_CLR,  0xffffffff);
	CLEAR_PERI_REG_MASK(SLC_INT_CLR,  0xffffffff);

	//Enable and configure DMA
	CLEAR_PERI_REG_MASK(SLC_CONF0, (SLC_MODE<<SLC_MODE_S));
	SET_PERI_REG_MASK(SLC_CONF0,(1<<SLC_MODE_S));
	SET_PERI_REG_MASK(SLC_RX_DSCR_CONF,SLC_INFOR_NO_REPLACE|SLC_TOKEN_NO_REPLACE);
	CLEAR_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_RX_FILL_EN|SLC_RX_EOF_MODE | SLC_RX_FILL_MODE);


	//Initialize DMA buffer descriptors in such a way that they will form a circular
	//buffer.
	for (x=0; x<I2SDMABUFCNT; x++) {
		i2sBufDesc[x].owner=1;
		i2sBufDesc[x].eof=1;
		i2sBufDesc[x].sub_sof=0;
		i2sBufDesc[x].datalen=I2SDMABUFLEN*4;
		i2sBufDesc[x].blocksize=I2SDMABUFLEN*4;
		i2sBufDesc[x].buf_ptr=(uint32_t)&i2sBuf[x][0];
		i2sBufDesc[x].unused=0;
		i2sBufDesc[x].next_link_ptr=(int)((x<(I2SDMABUFCNT-1))?(&i2sBufDesc[x+1]):(&i2sBufDesc[0]));
	}
	
	//Feed dma the 1st buffer desc addr
	//To send data to the I2S subsystem, counter-intuitively we use the RXLINK part, not the TXLINK as you might
	//expect. The TXLINK part still needs a valid DMA descriptor, even if it's unused: the DMA engine will throw
	//an error at us otherwise. Just feed it any random descriptor.
	CLEAR_PERI_REG_MASK(SLC_TX_LINK,SLC_TXLINK_DESCADDR_MASK);
	SET_PERI_REG_MASK(SLC_TX_LINK, ((uint32)&i2sBufDesc[1]) & SLC_TXLINK_DESCADDR_MASK); //any random desc is OK, we don't use TX but it needs something valid
	CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK);
	SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDesc[0]) & SLC_RXLINK_DESCADDR_MASK);

	//Attach the DMA interrupt
	_xt_isr_attach(ETS_SLC_INUM, (_xt_isr)slc_isr, NULL);
	//Enable DMA operation intr
	WRITE_PERI_REG(SLC_INT_ENA,  SLC_RX_EOF_INT_ENA);
	//clear any interrupt flags that are set
	WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);
	///enable DMA intr in cpu
	_xt_isr_unmask(1<<ETS_SLC_INUM);

	//We use a queue to keep track of the DMA buffers that are empty. The ISR will push buffers to the back of the queue,
	//the mp3 decode will pull them from the front and fill them. For ease, the queue will contain *pointers* to the DMA
	//buffers, not the data itself. The queue depth is one smaller than the amount of buffers we have, because there's
	//always a buffer that is being used by the DMA subsystem *right now* and we don't want to be able to write to that
	//simultaneously.
	dmaQueue=xQueueCreate(I2SDMABUFCNT-1, sizeof(int*));

	//Start transmission
	SET_PERI_REG_MASK(SLC_TX_LINK, SLC_TXLINK_START);
	SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START);

//----

	//Init pins to i2s functions
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_I2SO_DATA);
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_I2SO_WS);
#ifndef USE_ESP01_MODULE
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_I2SO_BCK);
#else
	GPIO_AS_INPUT(1<<15);
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15);
#endif
	//Enable clock to i2s subsystem
	i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1);

	//Reset I2S subsystem
	CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
	SET_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
	CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);

	//Select 16bits per channel (FIFO_MOD=0), no DMA access (FIFO only)
	CLEAR_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN|(I2S_I2S_RX_FIFO_MOD<<I2S_I2S_RX_FIFO_MOD_S)|(I2S_I2S_TX_FIFO_MOD<<I2S_I2S_TX_FIFO_MOD_S));
	//Enable DMA in i2s subsystem
	SET_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN);

	//tx/rx binaureal
	CLEAR_PERI_REG_MASK(I2SCONF_CHAN, (I2S_TX_CHAN_MOD<<I2S_TX_CHAN_MOD_S)|(I2S_RX_CHAN_MOD<<I2S_RX_CHAN_MOD_S));

	//Clear int
	SET_PERI_REG_MASK(I2SINT_CLR,   I2S_I2S_TX_REMPTY_INT_CLR|I2S_I2S_TX_WFULL_INT_CLR|
			I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
	CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_TX_REMPTY_INT_CLR|I2S_I2S_TX_WFULL_INT_CLR|
			I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);

	//trans master&rece slave,MSB shift,right_first,msb right
	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|
						((16&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
						((7&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S));


	//No idea if ints are needed...
	//clear int
	SET_PERI_REG_MASK(I2SINT_CLR,   I2S_I2S_TX_REMPTY_INT_CLR|I2S_I2S_TX_WFULL_INT_CLR|
			I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
	CLEAR_PERI_REG_MASK(I2SINT_CLR,   I2S_I2S_TX_REMPTY_INT_CLR|I2S_I2S_TX_WFULL_INT_CLR|
			I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
	//enable int
	SET_PERI_REG_MASK(I2SINT_ENA,   I2S_I2S_TX_REMPTY_INT_ENA|I2S_I2S_TX_WFULL_INT_ENA|
	I2S_I2S_RX_REMPTY_INT_ENA|I2S_I2S_TX_PUT_DATA_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA);

	//Start transmission
	SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START);
}
/**
 * @brief Based on pAttr initialize SPI module.
 *
 */
void ICACHE_FLASH_ATTR SPIInit (SpiNum spiNum, SpiAttr* pAttr)
{
	if ((spiNum > SpiNum_HSPI) || (NULL == pAttr))
	{
		return;
	}
	// SPI_CPOL & SPI_CPHA
	switch (pAttr->subMode)
	{
	case SpiSubMode_1:
		CLEAR_PERI_REG_MASK(SPI_PIN(spiNum), SPI_IDLE_EDGE);
		SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_CK_OUT_EDGE); // CHPA_FALLING_EDGE_SAMPLE
		break;
	case SpiSubMode_2:
		SET_PERI_REG_MASK(SPI_PIN(spiNum), SPI_IDLE_EDGE);
		SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_CK_OUT_EDGE); // CHPA_FALLING_EDGE_SAMPLE
		break;
	case SpiSubMode_3:
		SET_PERI_REG_MASK(SPI_PIN(spiNum), SPI_IDLE_EDGE);
		CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_CK_OUT_EDGE);
		break;
	case SpiSubMode_0:
		default:
		CLEAR_PERI_REG_MASK(SPI_PIN(spiNum), SPI_IDLE_EDGE);
		CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_CK_OUT_EDGE);
		// To do nothing
		break;
	}

	// SPI bit order
	if (SpiBitOrder_MSBFirst == pAttr->bitOrder)
	{
		CLEAR_PERI_REG_MASK(SPI_CTRL(spiNum), SPI_WR_BIT_ORDER);
		CLEAR_PERI_REG_MASK(SPI_CTRL(spiNum), SPI_RD_BIT_ORDER);
	}
	else if (SpiBitOrder_LSBFirst == pAttr->bitOrder)
	{
		SET_PERI_REG_MASK(SPI_CTRL(spiNum), SPI_WR_BIT_ORDER);
		SET_PERI_REG_MASK(SPI_CTRL(spiNum), SPI_RD_BIT_ORDER);
	}
	else
	{
		// To do nothing
	}

	// Disable flash operation mode
	// As earlier as better, if not SPI_CTRL2 can not to be set delay cycles.
	CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_FLASH_MODE);

	// SPI mode type
	if (SpiMode_Master == pAttr->mode)
	{
		// SPI mode type
		CLEAR_PERI_REG_MASK(SPI_SLAVE(spiNum), SPI_SLAVE_MODE);
		// SPI Send buffer
		CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO_HIGHPART);// By default slave send buffer C0-C7
		// SPI Speed
		if (1 < (pAttr->speed))
		{
			uint8 i, k;
			i = (pAttr->speed / 40) ? (pAttr->speed / 40) : 1;
			k = pAttr->speed / i;
			CLEAR_PERI_REG_MASK(SPI_CLOCK(spiNum), SPI_CLK_EQU_SYSCLK);
			WRITE_PERI_REG(SPI_CLOCK(spiNum),
			        (((i - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
			        (((k - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
			        ((((k + 1) / 2 - 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
			        (((k - 1) & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
		}
		else
		{
			WRITE_PERI_REG(SPI_CLOCK(spiNum), SPI_CLK_EQU_SYSCLK); // 80Mhz speed
		}
		// By default format:CMD+ADDR+DATA
		SET_PERI_REG_MASK(SPI_USER(spiNum),
		        SPI_CS_SETUP | SPI_CS_HOLD | SPI_USR_MOSI);

		//delay num
		SET_PERI_REG_MASK(SPI_CTRL2(spiNum),
		        ((0x1 & SPI_MISO_DELAY_NUM) << SPI_MISO_DELAY_NUM_S));
	}
	else if (SpiMode_Slave == pAttr->mode)
	{
		// BIT19 must do
		SET_PERI_REG_MASK(SPI_PIN(spiNum), BIT19);

		// SPI mode type
		SET_PERI_REG_MASK(SPI_SLAVE(spiNum), SPI_SLAVE_MODE);
		// SPI Send buffer
		SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO_HIGHPART);// By default slave send buffer C8-C15

		SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI);

		// If do not set delay cycles, slave not working,master cann't get the data.
		SET_PERI_REG_MASK(SPI_CTRL2(spiNum),
		        ((0x1 & SPI_MOSI_DELAY_NUM) << SPI_MOSI_DELAY_NUM_S)); //delay num
		// SPI Speed
		WRITE_PERI_REG(SPI_CLOCK(spiNum), 0);

		// By default format::CMD(8bits)+ADDR(8bits)+DATA(32bytes).
		SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_BITLEN,
		        7, SPI_USR_COMMAND_BITLEN_S);
		SET_PERI_REG_BITS(SPI_SLAVE1(spiNum), SPI_SLV_WR_ADDR_BITLEN,
		        7, SPI_SLV_WR_ADDR_BITLEN_S);
		SET_PERI_REG_BITS(SPI_SLAVE1(spiNum), SPI_SLV_RD_ADDR_BITLEN,
		        7, SPI_SLV_RD_ADDR_BITLEN_S);
		SET_PERI_REG_BITS(SPI_SLAVE1(spiNum), SPI_SLV_BUF_BITLEN,
		        (32 * 8 - 1), SPI_SLV_BUF_BITLEN_S);
		// For 8266 work on slave mode.
		SET_PERI_REG_BITS(SPI_SLAVE1(spiNum), SPI_SLV_STATUS_BITLEN,
		        7, SPI_SLV_STATUS_BITLEN_S);
	}
	else
	{
		// To do nothing
	}

	//clear Daul or Quad lines transmission mode
	CLEAR_PERI_REG_MASK(SPI_CTRL(spiNum),
	        SPI_QIO_MODE | SPI_DIO_MODE | SPI_DOUT_MODE | SPI_QOUT_MODE);
	// Clear the data buffer.
	uint8 i;
	uint32 regAddr = REG_SPI_BASE(spiNum) + 0x40;
	for (i = 0; i < 16; ++i)
	{
		WRITE_PERI_REG(regAddr, 0);
		regAddr += 4;
	}

}