Exemple #1
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);
}
Exemple #2
0
void mgos_uart_hal_dispatch_rx_top(struct mgos_uart_state *us) {
  bool recd;
  struct cc32xx_uart_state *ds = (struct cc32xx_uart_state *) us->dev_data;
  cs_rbuf_t *irxb = &ds->isr_rx_buf;
  MAP_UARTIntDisable(ds->base, UART_RX_INTS);
recv_more:
  recd = false;
  cc32xx_uart_rx_bytes(ds->base, irxb);
  while (irxb->used > 0 && mgos_uart_rxb_free(us) > 0) {
    int num_recd = 0;
    do {
      uint8_t *data;
      int num_to_get = MIN(mgos_uart_rxb_free(us), irxb->used);
      num_recd = cs_rbuf_get(irxb, num_to_get, &data);
      mbuf_append(&us->rx_buf, data, num_recd);
      cs_rbuf_consume(irxb, num_recd);
      us->stats.rx_bytes += num_recd;
      if (num_recd > 0) recd = true;
      cc32xx_uart_rx_bytes(ds->base, irxb);
    } while (num_recd > 0);
  }
  /* If we received something during this cycle and there is buffer space
   * available, "linger" for some more, maybe there's more to come. */
  if (recd && mgos_uart_rxb_free(us) > 0 && us->cfg.rx_linger_micros > 0) {
    /* Magic constants below are tweaked so that the loop takes at most the
     * configured number of microseconds. */
    int ctr = us->cfg.rx_linger_micros * 31 / 12;
    // HWREG(GPIOA1_BASE + GPIO_O_GPIO_DATA + 8) = 0xFF; /* Pin 64 */
    while (ctr-- > 0) {
      if (MAP_UARTCharsAvail(ds->base)) {
        us->stats.rx_linger_conts++;
        goto recv_more;
      }
    }
    // HWREG(GPIOA1_BASE + GPIO_O_GPIO_DATA + 8) = 0; /* Pin 64 */
  }
  MAP_UARTIntClear(ds->base, UART_RX_INTS);
}
Exemple #3
0
void mgos_uart_hal_dispatch_bottom(struct mgos_uart_state *us) {
  uint32_t int_ena = UART_INFO_INTS;
  /* Determine which interrupts we want. */
  if (us->rx_enabled) {
    if (mgos_uart_rxb_free(us) > 0) {
      int_ena |= UART_RX_INTS;
    }
    if (adj_rx_fifo_full_thresh(us)) {
      int_ena |= UART_RXFIFO_FULL_INT_ENA;
    }
  }
  if (us->tx_buf.len > 0) int_ena |= UART_TX_INTS;
  WRITE_PERI_REG(UART_INT_ENA(us->uart_no), int_ena);
}