size_t HardwareSerial::write(uint8_t c)
{
  _written = true;
  // If the buffer and the data register is empty, just write the byte
  // to the data register and be done. This shortcut helps
  // significantly improve the effective datarate at high (>
  // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
  if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) {
#ifdef __HWSERIAL9BIT
    if(bit_is_set(*_ucsrb, UCSZ02)) {
      // Uart is configured for 9 bit mode
      cbi(*_ucsrb, TXB80); // 9th bit clear
    }
#endif
    *_udr = c;
    sbi(*_ucsra, TXC0);
    return 1;
  }
  tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;
	
  // If the output buffer is full, there's nothing for it other than to 
  // wait for the interrupt handler to empty it a bit
  while (i == _tx_buffer_tail) {
    if (bit_is_clear(SREG, SREG_I)) {
      // Interrupts are disabled, so we'll have to poll the data
      // register empty flag ourselves. If it is set, pretend an
      // interrupt has happened and call the handler to free up
      // space for us.
      if(bit_is_set(*_ucsra, UDRE0))
	_tx_udr_empty_irq();
    } else {
      // nop, the interrupt handler will free up space for us
    }
  }

  _tx_buffer[_tx_buffer_head] = c;
#ifdef __HWSERIAL9BIT
  __HWSERIAL9BIT_bitClear(_tx_9bit, _tx_buffer_head);
#endif // __HWSERIAL9BIT
  _tx_buffer_head = i;
	
  sbi(*_ucsrb, UDRIE0);
  
  return 1;
}
Ejemplo n.º 2
0
  void MarlinSerial::flushTX(void) {
    // TX
    // If we have never written a byte, no need to flush. This special
    // case is needed since there is no way to force the TXC (transmit
    // complete) bit to 1 during initialization
    if (!_written)
      return;

    while (TEST(M_UCSRxB, M_UDRIEx) || !TEST(M_UCSRxA, M_TXCx)) {
      if (!TEST(SREG, SREG_I) && TEST(M_UCSRxB, M_UDRIEx))
        // Interrupts are globally disabled, but the DR empty
        // interrupt should be enabled, so poll the DR empty flag to
        // prevent deadlock
        if (TEST(M_UCSRxA, M_UDREx))
          _tx_udr_empty_irq();
    }
    // If we get here, nothing is queued anymore (DRIE is disabled) and
    // the hardware finished tranmission (TXC is set).
}
Ejemplo n.º 3
0
void HardwareSerial::flush()
{
  // If we have never written a byte, no need to flush. This special
  // case is needed since there is no way to force the TXC (transmit
  // complete) bit to 1 during initialization
  if (!_written)
    return;

  while (bit_is_set(*_ucsrb, UDRIE0) || bit_is_clear(*_ucsra, TXC0)) {
    if (bit_is_clear(SREG, SREG_I) && bit_is_set(*_ucsrb, UDRIE0))
	// Interrupts are globally disabled, but the DR empty
	// interrupt should be enabled, so poll the DR empty flag to
	// prevent deadlock
	if (bit_is_set(*_ucsra, UDRE0))
	  _tx_udr_empty_irq();
  }
  // If we get here, nothing is queued anymore (DRIE is disabled) and
  // the hardware finished tranmission (TXC is set).
}
Ejemplo n.º 4
0
    void MarlinSerial::write(const uint8_t c) {
      _written = true;
      CRITICAL_SECTION_START;
        bool emty = (tx_buffer.head == tx_buffer.tail);
      CRITICAL_SECTION_END;
      // If the buffer and the data register is empty, just write the byte
      // to the data register and be done. This shortcut helps
      // significantly improve the effective datarate at high (>
      // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
      if (emty && TEST(M_UCSRxA, M_UDREx)) {
        CRITICAL_SECTION_START;
          M_UDRx = c;
          SBI(M_UCSRxA, M_TXCx);
        CRITICAL_SECTION_END;
        return;
      }
      const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);

      // If the output buffer is full, there's nothing for it other than to
      // wait for the interrupt handler to empty it a bit
      while (i == tx_buffer.tail) {
        if (!TEST(SREG, SREG_I)) {
          // Interrupts are disabled, so we'll have to poll the data
          // register empty flag ourselves. If it is set, pretend an
          // interrupt has happened and call the handler to free up
          // space for us.
          if (TEST(M_UCSRxA, M_UDREx))
            _tx_udr_empty_irq();
        }
        else {
          // nop, the interrupt handler will free up space for us
        }
      }

      tx_buffer.buffer[tx_buffer.head] = c;
      { CRITICAL_SECTION_START;
          tx_buffer.head = i;
          SBI(M_UCSRxB, M_UDRIEx);
        CRITICAL_SECTION_END;
      }
      return;
    }
Ejemplo n.º 5
0
  void MarlinSerial<Cfg>::flushTX(void) {

    if (Cfg::TX_SIZE == 0) {
      // No bytes written, no need to flush. This special case is needed since there's
      // no way to force the TXC (transmit complete) bit to 1 during initialization.
      if (!_written) return;

      // Wait until everything was transmitted
      while (!B_TXC) sw_barrier();

      // At this point nothing is queued anymore (DRIE is disabled) and
      // the hardware finished transmission (TXC is set).

    }
    else {

      // No bytes written, no need to flush. This special case is needed since there's
      // no way to force the TXC (transmit complete) bit to 1 during initialization.
      if (!_written) return;

      // If global interrupts are disabled (as the result of being called from an ISR)...
      if (!ISRS_ENABLED()) {

        // Wait until everything was transmitted - We must do polling, as interrupts are disabled
        while (tx_buffer.head != tx_buffer.tail || !B_TXC) {

          // If there is more space, send an extra character
          if (B_UDRE) _tx_udr_empty_irq();

          sw_barrier();
        }

      }
      else {
        // Wait until everything was transmitted
        while (tx_buffer.head != tx_buffer.tail || !B_TXC) sw_barrier();
      }

      // At this point nothing is queued anymore (DRIE is disabled) and
      // the hardware finished transmission (TXC is set).
    }
  }
Ejemplo n.º 6
0
int8_t serialWrite(uint8_t c)
{
    // If the buffer and the data register is empty, just write the byte
    // to the data register and be done. This shortcut helps
    // significantly improve the effective datarate at high (>
    // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
    if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(_ucsra, UDRE0)) {
        _udr = c;
        sbi(_ucsra, TXC0);
        return 1;
    }
    tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;

    // If the output buffer is full, there's nothing for it other than to
    // wait for the interrupt handler to empty it a bit
    while (i == _tx_buffer_tail) {
        if (bit_is_clear(SREG, SREG_I)) {
            // Interrupts are disabled, so we'll have to poll the data
            // register empty flag ourselves. If it is set, pretend an
            // interrupt has happened and call the handler to free up
            // space for us.
            if(bit_is_set(_ucsra, UDRE0))
                _tx_udr_empty_irq();
        } else {
            // nop, the interrupt handler will free up space for us
        }
    }

    _tx_buffer[_tx_buffer_head] = c;
    _tx_buffer_head = i;

    sbi(_ucsrb, UDRIE0);
    _written = 1;

    return 1;
}