/** * @brief System main loop called by the ETS * * This function is called by ETS after all initializations has been * finished to start periodic processing of defined ETS tasks. We * overwrite this ETS function to take over the control and to start RIOT. */ void ets_run(void) { #if ENABLE_DEBUG register uint32_t *sp __asm__ ("a1"); ets_uart_printf("_stack %p\n", sp); ets_uart_printf("_bss_start %p\n", &_bss_start); ets_uart_printf("_bss_end %p\n", &_bss_end); ets_uart_printf("_heap_start %p\n", &_sheap); ets_uart_printf("_heap_end %p\n", &_eheap); ets_uart_printf("_heap_free %lu\n", get_free_heap_size()); #endif /* init min task priority */ ets_task_min_prio = 0; #ifdef MODULE_NEWLIB_SYSCALLS_DEFAULT _init(); #endif ets_tasks_init(); /* enable interrupts used by ETS/SDK */ #ifndef MODULE_ESP_SDK_INT_HANDLING ets_isr_unmask(BIT(ETS_FRC2_INUM)); ets_isr_unmask(BIT(ETS_WDEV_INUM)); ets_isr_unmask(BIT(ETS_WDT_INUM)); #endif #ifdef MODULE_ESP_GDBSTUB gdbstub_init(); #endif #if ENABLE_DEBUG==0 /* disable SDK messages */ system_set_os_print(0); #endif #ifdef CONTEXT_SWITCH_BY_INT extern void IRAM thread_yield_isr(void* arg); ets_isr_attach(ETS_SOFT_INUM, thread_yield_isr, NULL); ets_isr_unmask(BIT(ETS_SOFT_INUM)); #endif /* initialize dummy lwIP library to link it even if esp_wifi is not used */ extern void esp_lwip_init(void); esp_lwip_init(); thread_create(ets_task_stack, sizeof(ets_task_stack), ETS_TASK_PRIORITY, THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST, ets_task_func, NULL, "ets"); /* does not return */ kernel_init(); }
void ICACHE_FLASH_ATTR init_GPIOs_intr(void) { if(GPIO_TEST1 == GPIO_TEST2 || GPIO_TEST1 > 15 || GPIO_TEST1 > 15) { GPIO_TEST1 = 4; GPIO_TEST2 = 5; } // ets_isr_mask(1 << ETS_GPIO_INUM); // запрет прерываний GPIOs // чтение пользовательских констант (0 < idx < 4) из записей в Flash GPIO_INT_Counter1 = read_user_const(1); GPIO_INT_Counter2 = read_user_const(2); system_os_task(task_GPIOs_intr, GPIOs_intr_TASK_PRIO, GPIOs_intr_taskQueue, GPIOs_intr_TASK_QUEUE_LEN); uint32 pins_mask = (1<<GPIO_TEST1) | (1<<GPIO_TEST2); gpio_output_set(0,0,0, pins_mask); // настроить GPIOx на ввод set_gpiox_mux_func_ioport(GPIO_TEST1); // установить функцию GPIOx в режим порта i/o set_gpiox_mux_func_ioport(GPIO_TEST2); // установить функцию GPIOx в режим порта i/o // GPIO_ENABLE_W1TC = pins_mask; // GPIO OUTPUT DISABLE отключить вывод в портах ets_isr_attach(ETS_GPIO_INUM, GPIOs_intr_handler, NULL); gpio_pin_intr_state_set(GPIO_TEST1, GPIO_PIN_INTR_ANYEDGE); // GPIO_PIN_INTR_POSEDGE | GPIO_PIN_INTR_NEGEDGE ? gpio_pin_intr_state_set(GPIO_TEST2, GPIO_PIN_INTR_ANYEDGE); // GPIO_PIN_INTR_POSEDGE | GPIO_PIN_INTR_NEGEDGE ? // разрешить прерывания GPIOs GPIO_STATUS_W1TC = pins_mask; ets_isr_unmask(1 << ETS_GPIO_INUM); GPIO_INTR_INIT = 1; GPIO_INT_init_flg = 1; os_printf("GPIOs_intr init (%d,%d) ", GPIO_TEST1, GPIO_TEST2); }
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; }
void timer0_init(void *func, uint32 par) #endif { #if DEBUGSOO > 3 os_printf("timer0_init(%d)\n", flg); #endif timer0_stop(); timer0_cb = func; timer0_arg = par; #ifdef TIMER0_USE_NMI_VECTOR if(nmi_flg) { DPORT_BASE[0] |= 0x0F; } else #endif { DPORT_BASE[0] = 0; ets_isr_attach(ETS_FRC_TIMER0_INUM, _timer0_isr, NULL); } ets_isr_unmask(BIT(ETS_FRC_TIMER0_INUM)); }
void ICACHE_FLASH_ATTR timer0_start(uint32 us, bool repeat_flg) { TIMER0_LOAD = 0xFFFFFFFF; if(repeat_flg) { TIMER0_CTRL = TM_DIVDED_BY_16 | TM_AUTO_RELOAD_CNT | TM_ENABLE_TIMER | TM_EDGE_INT; } else { TIMER0_CTRL = TM_DIVDED_BY_16 | TM_ENABLE_TIMER | TM_EDGE_INT; } if(us < 5) { TIMER0_LOAD = 40; } else if(us <= 1677721) { TIMER0_LOAD = us * 5; } ets_isr_unmask(BIT(ETS_FRC_TIMER0_INUM)); INTC_EDGE_EN |= BIT(1); }
//Initialize I2S subsystem for DMA circular buffer use void ICACHE_FLASH_ATTR ws2812_init() { int x, y; //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); i2sBufDescOut.owner = 1; i2sBufDescOut.eof = 1; i2sBufDescOut.sub_sof = 0; i2sBufDescOut.datalen = WS_BLOCKSIZE; //Size (in bytes) i2sBufDescOut.blocksize = WS_BLOCKSIZE; //Size (in bytes) i2sBufDescOut.buf_ptr=(uint32_t)&i2sBlock[0]; i2sBufDescOut.unused=0; i2sBufDescOut.next_link_ptr=(uint32_t)&i2sBufDescZeroes; //At the end, just redirect the DMA to the zero buffer. i2sBufDescZeroes.owner = 1; i2sBufDescZeroes.eof = 1; i2sBufDescZeroes.sub_sof = 0; i2sBufDescZeroes.datalen = 32; i2sBufDescZeroes.blocksize = 32; i2sBufDescZeroes.buf_ptr=(uint32_t)&i2sZeroes[0]; i2sBufDescZeroes.unused=0; i2sBufDescZeroes.next_link_ptr=(uint32_t)&i2sBufDescOut; for( x = 0; x < 32; x++ ) { i2sZeroes[x] = 0x00; } for( x = 0; x < WS_BLOCKSIZE/4; x++ ) { i2sBlock[x] = 0x00000000;//(x == 0 || x == 999)?0xaa:0x00; /* uint16_t * tt = (uint16_t*)&i2sBlock[x]; (*(tt+0)) = 0xA0F0; (*(tt+1)) = 0xC0E0;*/ } // CLEAR_PERI_REG_MASK(SLC_TX_LINK,SLC_TXLINK_DESCADDR_MASK); // SET_PERI_REG_MASK(SLC_TX_LINK, ((uint32)&i2sBufDescZeroes) & 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)&i2sBufDescOut) & SLC_RXLINK_DESCADDR_MASK); #ifdef USE_2812_INTERRUPTS //Attach the DMA interrupt ets_isr_attach(ETS_SLC_INUM, slc_isr); //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 ets_isr_unmask(1<<ETS_SLC_INUM); #endif //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); // PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_I2SO_BCK); //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)); #ifdef USE_2812_INTERRUPTS //Clear int SET_PERI_REG_MASK(I2SINT_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_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); #endif //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| (((WS_I2S_BCK-1)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)| (((WS_I2S_DIV-1)&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_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); CLEAR_PERI_REG_MASK(I2SINT_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_RX_REMPTY_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA); //Start transmission SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START); }
void cmd_loop() { while(1) { /* Wait for a command */ while(ub.command == NULL) { } esp_command_req_t *command = ub.command; ub.command = NULL; /* provide easy access for 32-bit data words */ uint32_t *data_words = (uint32_t *)command->data_buf; /* Send command response header */ esp_command_response_t resp = { .resp = 1, .op_ret = command->op, .len_ret = 0, /* esptool.py ignores this value */ .value = 0, }; /* ESP_READ_REG is the only command that needs to write into the 'resp' structure before we send it back. */ if (command->op == ESP_READ_REG && command->data_len == 4) { resp.value = REG_READ(data_words[0]); } /* Send the command response. */ SLIP_send_frame_delimiter(); SLIP_send_frame_data_buf(&resp, sizeof(esp_command_response_t)); if(command->data_len > MAX_WRITE_BLOCK+16) { SLIP_send_frame_data(ESP_BAD_DATA_LEN); SLIP_send_frame_data(0xEE); SLIP_send_frame_delimiter(); continue; } /* ... some commands will insert in-frame response data between here and when we send the end of the frame */ esp_command_error error = ESP_CMD_NOT_IMPLEMENTED; int status = 0; /* First stage of command processing - before sending error/status */ switch (command->op) { case ESP_ERASE_FLASH: error = verify_data_len(command, 0) || SPIEraseChip(); break; case ESP_ERASE_REGION: /* Params for ERASE_REGION are addr, len */ error = verify_data_len(command, 8) || handle_flash_erase(data_words[0], data_words[1]); break; case ESP_SET_BAUD: /* ESP_SET_BAUD sends two args, we ignore the second one */ error = verify_data_len(command, 8); /* actual baud setting happens after we send the reply */ break; case ESP_READ_FLASH: error = verify_data_len(command, 16); /* actual data is sent after we send the reply */ break; case ESP_FLASH_VERIFY_MD5: /* unsure why the MD5 command has 4 params but we only pass 2 of them, but this is in ESP32 ROM so we can't mess with it. */ error = verify_data_len(command, 16) || handle_flash_get_md5sum(data_words[0], data_words[1]); break; case ESP_FLASH_BEGIN: /* parameters (interpreted differently to ROM flasher): 0 - erase_size (used as total size to write) 1 - num_blocks (ignored) 2 - block_size (should be MAX_WRITE_BLOCK, relies on num_blocks * block_size >= erase_size) 3 - offset (used as-is) */ if (command->data_len == 16 && data_words[2] != MAX_WRITE_BLOCK) { error = ESP_BAD_BLOCKSIZE; } else { error = verify_data_len(command, 16) || handle_flash_begin(data_words[0], data_words[3]); } break; case ESP_FLASH_DEFLATED_BEGIN: /* parameters: 0 - uncompressed size 1 - num_blocks (based on compressed size) 2 - block_size (should be MAX_WRITE_BLOCK, total bytes over serial = num_blocks * block_size) 3 - offset (used as-is) */ if (command->data_len == 16 && data_words[2] != MAX_WRITE_BLOCK) { error = ESP_BAD_BLOCKSIZE; } else { error = verify_data_len(command, 16) || handle_flash_deflated_begin(data_words[0], data_words[1] * data_words[2], data_words[3]); } break; case ESP_FLASH_DATA: case ESP_FLASH_DEFLATED_DATA: /* ACK DATA commands immediately, then process them a few lines down, allowing next command to buffer */ if(is_in_flash_mode()) { error = get_flash_error(); int payload_len = command->data_len - 16; if (data_words[0] != payload_len) { /* First byte of data payload header is length (repeated) as a word */ error = ESP_BAD_DATA_LEN; } uint8_t data_checksum = calculate_checksum(command->data_buf + 16, payload_len); if (data_checksum != command->checksum) { error = ESP_BAD_DATA_CHECKSUM; } } else { error = ESP_NOT_IN_FLASH_MODE; } break; case ESP_FLASH_END: case ESP_FLASH_DEFLATED_END: error = handle_flash_end(); break; case ESP_SPI_SET_PARAMS: /* data params: fl_id, total_size, block_size, sector_Size, page_size, status_mask */ error = verify_data_len(command, 24) || handle_spi_set_params(data_words, &status); break; case ESP_SPI_ATTACH: /* parameter is 'hspi mode' (0, 1 or a pin mask for ESP32. Ignored on ESP8266.) */ error = verify_data_len(command, 4) || handle_spi_attach(data_words[0]); break; case ESP_WRITE_REG: /* params are addr, value, mask (ignored), delay_us (ignored) */ error = verify_data_len(command, 16); if (error == ESP_OK) { REG_WRITE(data_words[0], data_words[1]); } break; case ESP_READ_REG: /* actual READ_REG operation happens higher up */ error = verify_data_len(command, 4); break; case ESP_MEM_BEGIN: error = verify_data_len(command, 16) || handle_mem_begin(data_words[0], data_words[3]); break; case ESP_MEM_DATA: error = handle_mem_data(command->data_buf + 16, command->data_len - 16); break; case ESP_MEM_END: error = verify_data_len(command, 8) || handle_mem_finish(); break; case ESP_RUN_USER_CODE: /* Returning from here will run user code, ie standard boot process This command does not send a response. */ return; } SLIP_send_frame_data(error); SLIP_send_frame_data(status); SLIP_send_frame_delimiter(); /* Some commands need to do things after after sending this response */ if (error == ESP_OK) { switch(command->op) { case ESP_SET_BAUD: ets_delay_us(10000); uart_div_modify(0, baud_rate_to_divider(data_words[0])); ets_delay_us(1000); break; case ESP_READ_FLASH: /* args are: offset, length, block_size, max_in_flight */ handle_flash_read(data_words[0], data_words[1], data_words[2], data_words[3]); break; case ESP_FLASH_DATA: /* drop into flashing mode, discard 16 byte payload header */ handle_flash_data(command->data_buf + 16, command->data_len - 16); break; case ESP_FLASH_DEFLATED_DATA: handle_flash_deflated_data(command->data_buf + 16, command->data_len - 16); break; case ESP_FLASH_DEFLATED_END: case ESP_FLASH_END: /* passing 0 as parameter for ESP_FLASH_END means reboot now */ if (data_words[0] == 0) { /* Flush the FLASH_END response before rebooting */ #ifdef ESP32 uart_tx_flush(0); #endif ets_delay_us(10000); software_reset(); } break; case ESP_MEM_END: if (data_words[1] != 0) { void (*entrypoint_fn)(void) = (void (*))data_words[1]; /* this is a little different from the ROM loader, which exits the loader routine and _then_ calls this function. But for our purposes so far, having a bit of extra stuff on the stack doesn't really matter. */ entrypoint_fn(); } break; } } } } extern uint32_t _bss_start; extern uint32_t _bss_end; void __attribute__((used)) stub_main(); #ifdef ESP8266 __asm__ ( ".global stub_main_8266\n" ".literal_position\n" ".align 4\n" "stub_main_8266:\n" /* ESP8266 wrapper for "stub_main()" manipulates the return address in * a0, so 'return' from here runs user code. * * After setting a0, we jump directly to stub_main_inner() which is a * normal C function * * Adapted from similar approach used by Cesanta Software for ESP8266 * flasher stub. * */ "movi a0, 0x400010a8;" "j stub_main;"); #endif /* This function is called from stub_main, with return address reset to point to user code. */ void stub_main() { const uint32_t greeting = 0x4941484f; /* OHAI */ /* this points to stub_main now, clear for next boot */ ets_set_user_start(0); /* zero bss */ for(uint32_t *p = &_bss_start; p < &_bss_end; p++) { *p = 0; } SLIP_send(&greeting, 4); /* All UART reads come via uart_isr */ ub.reading_buf = ub.buf_a; ets_isr_attach(ETS_UART0_INUM, uart_isr, NULL); SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RX_INTS); ets_isr_unmask(1 << ETS_UART0_INUM); /* Configure default SPI flash functionality. Can be overriden later by esptool.py. */ #ifdef ESP8266 SelectSpiFunction(); #else uint32_t spiconfig = ets_efuse_get_spiconfig(); uint32_t strapping = REG_READ(GPIO_STRAP_REG); /* If GPIO1 (U0TXD) is pulled low and no other boot mode is set in efuse, assume HSPI flash mode (same as normal boot) */ if (spiconfig == 0 && (strapping & 0x1c) == 0x08) { spiconfig = 1; /* HSPI flash mode */ } spi_flash_attach(spiconfig, 0); #endif SPIParamCfg(0, 16*1024*1024, FLASH_BLOCK_SIZE, FLASH_SECTOR_SIZE, FLASH_PAGE_SIZE, FLASH_STATUS_MASK); cmd_loop(); /* if cmd_loop returns, it's due to ESP_RUN_USER_CODE command. */ return; }
void ws2812_dma(sdio_queue_t *i2s_pixels_queue) { // 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); // configure DMA descriptor CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK); SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)i2s_pixels_queue) & SLC_RXLINK_DESCADDR_MASK); #if WS2812_USE_INTERRUPT == 1 // Attach the DMA interrupt ets_isr_attach(ETS_SLC_INUM, (int_handler_t)ws2812_isr , (void *)0); //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 ets_isr_unmask(1<<ETS_SLC_INUM); #endif //Start transmission 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); //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); //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| (((WS_I2S_BCK-1)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)| (((WS_I2S_DIV-1)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)); #if WS2812_USE_INTERRUPT == 1 //clear int SET_PERI_REG_MASK(I2SINT_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_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_RX_REMPTY_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA); #endif //Start transmission SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START); }