static ssize_t IRAM_ATTR uart_read(int fd, void* data, size_t size) { assert(fd >=0 && fd < 3); uint8_t *data_c = (uint8_t *) data; uart_dev_t* uart = s_uarts[fd]; size_t received = 0; _lock_acquire_recursive(&s_uart_locks[fd]); while (uart->status.rxfifo_cnt > 0 && received < size) { uint8_t c = uart->fifo.rw_byte; #if CONFIG_NEWLIB_STDOUT_ADDCR /* Convert \r\n sequences to \n. * If \r is received, it is put into 'buffered_char' until the next * character is received. Then depending on the character, we either * drop \r (if the next one is \n) or output \r and then proceed to output * the new character. */ const int NONE = -1; static int buffered_char = NONE; if (buffered_char != NONE) { if (buffered_char == '\r' && c == '\n') { buffered_char = NONE; } else { data_c[received] = buffered_char; buffered_char = NONE; ++received; if (received == size) { /* We have placed the buffered character into the output buffer * but there won't be enough space for the newly received one. * Keep the new character in buffered_char until read is called * again. */ buffered_char = c; break; } } } if (c == '\r') { buffered_char = c; continue; } #endif //CONFIG_NEWLIB_STDOUT_ADDCR data_c[received] = c; ++received; } _lock_release_recursive(&s_uart_locks[fd]); if (received > 0) { return received; } errno = EWOULDBLOCK; return -1; }
esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr_alloc_flags) { RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK((s_rmt_driver_channels & BIT(channel)) == 0, "RMT driver already installed for channel", ESP_ERR_INVALID_STATE); esp_err_t err = ESP_OK; if(p_rmt_obj[channel] != NULL) { ESP_LOGD(RMT_TAG, "RMT driver already installed"); return ESP_ERR_INVALID_STATE; } p_rmt_obj[channel] = (rmt_obj_t*) malloc(sizeof(rmt_obj_t)); if(p_rmt_obj[channel] == NULL) { ESP_LOGE(RMT_TAG, "RMT driver malloc error"); return ESP_ERR_NO_MEM; } memset(p_rmt_obj[channel], 0, sizeof(rmt_obj_t)); p_rmt_obj[channel]->tx_len_rem = 0; p_rmt_obj[channel]->tx_data = NULL; p_rmt_obj[channel]->channel = channel; p_rmt_obj[channel]->tx_offset = 0; p_rmt_obj[channel]->tx_sub_len = 0; if(p_rmt_obj[channel]->tx_sem == NULL) { p_rmt_obj[channel]->tx_sem = xSemaphoreCreateBinary(); xSemaphoreGive(p_rmt_obj[channel]->tx_sem); } if(p_rmt_obj[channel]->rx_buf == NULL && rx_buf_size > 0) { p_rmt_obj[channel]->rx_buf = xRingbufferCreate(rx_buf_size, RINGBUF_TYPE_NOSPLIT); rmt_set_rx_intr_en(channel, 1); rmt_set_err_intr_en(channel, 1); } _lock_acquire_recursive(&rmt_driver_isr_lock); if(s_rmt_driver_channels == 0) { // first RMT channel using driver err = rmt_isr_register(rmt_driver_isr_default, NULL, intr_alloc_flags, &s_rmt_driver_intr_handle); } if (err == ESP_OK) { s_rmt_driver_channels |= BIT(channel); rmt_set_tx_intr_en(channel, 1); } _lock_release_recursive(&rmt_driver_isr_lock); return err; }
esp_err_t rmt_driver_uninstall(rmt_channel_t channel) { esp_err_t err = ESP_OK; RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK((s_rmt_driver_channels & BIT(channel)) != 0, "No RMT driver for this channel", ESP_ERR_INVALID_STATE); if(p_rmt_obj[channel] == NULL) { return ESP_OK; } xSemaphoreTake(p_rmt_obj[channel]->tx_sem, portMAX_DELAY); rmt_set_rx_intr_en(channel, 0); rmt_set_err_intr_en(channel, 0); rmt_set_tx_intr_en(channel, 0); rmt_set_tx_thr_intr_en(channel, 0, 0xffff); _lock_acquire_recursive(&rmt_driver_isr_lock); s_rmt_driver_channels &= ~BIT(channel); if (s_rmt_driver_channels == 0) { // all channels have driver disabled err = rmt_isr_deregister(s_rmt_driver_intr_handle); s_rmt_driver_intr_handle = NULL; } _lock_release_recursive(&rmt_driver_isr_lock); if (err != ESP_OK) { return err; } if(p_rmt_obj[channel]->tx_sem) { vSemaphoreDelete(p_rmt_obj[channel]->tx_sem); p_rmt_obj[channel]->tx_sem = NULL; } if(p_rmt_obj[channel]->rx_buf) { vRingbufferDelete(p_rmt_obj[channel]->rx_buf); p_rmt_obj[channel]->rx_buf = NULL; } free(p_rmt_obj[channel]); p_rmt_obj[channel] = NULL; return ESP_OK; }
static size_t IRAM_ATTR uart_write(int fd, const void * data, size_t size) { assert(fd >=0 && fd < 3); const char *data_c = (const char *)data; uart_dev_t* uart = s_uarts[fd]; /* * Even though newlib does stream locking on each individual stream, we need * a dedicated UART lock if two streams (stdout and stderr) point to the * same UART. */ _lock_acquire_recursive(&s_uart_locks[fd]); for (size_t i = 0; i < size; i++) { #if CONFIG_NEWLIB_STDOUT_ADDCR if (data_c[i]=='\n') { uart_tx_char(uart, '\r'); } #endif uart_tx_char(uart, data_c[i]); } _lock_release_recursive(&s_uart_locks[fd]); return size; }