Bagaimana Arduino menangani buffer overflow serial?

27

Bagaimana Arduino menangani buffer overflow serial? Apakah itu membuang data yang masuk terbaru atau yang tertua? Berapa banyak byte yang bisa ditampung oleh buffer?


sumber

Jawaban:

13

Untuk port serial perangkat keras Anda dapat melihat di HardwareSerial.cpp bahwa ukuran buffer bervariasi tergantung pada jumlah RAM yang tersedia pada AVR tertentu:

#if (RAMEND < 1000)
    #define SERIAL_BUFFER_SIZE 16
#else
    #define SERIAL_BUFFER_SIZE 64
#endif

Untuk port serial perangkat lunak di SoftwareSerial.h ukuran buffer penerima _SS_MAX_RX_BUFFdidefinisikan sebagai 64 byte. Dalam kedua kasus itu berhenti mencoba untuk memasukkan data yang diterima ke dalam antrian ketika sudah penuh, sehingga Anda bisa mendapatkan campuran ke data lama dan baru tergantung pada bagaimana Anda mengambil data dari antrian.

Idealnya akan lebih baik untuk memastikan buffer selalu dikosongkan secara cepat untuk menghindari pengisian buffer. Mungkin lihat timer dan menerapkan mesin negara sederhana jika masalah Anda terkait dengan kode lain memblokir loop utama.

PeterJ
sumber
Saya mendapat kesan bahwa jika saya mengirimkan data ke Arduino dan tidak memiliki "penarik" data aktif di sisi Arduino maka jika lebih banyak data yang masuk daripada yang bisa muat dalam buffer, itu akan dibuang. Bisakah Anda mengonfirmasi itu? Saya secara naif berasumsi bahwa pemancar akan memblokir sampai ruang yang tersedia untuk menampung data tersedia.
Kolban
Saya baru saja melihat semua kode itu (di bawah / usr / share / arduino / hardware / arduino / core / arduino / HardwareSer‌ ial.cpp) dan dapat mengkonfirmasi apa yang Anda tulis di sini. Satu-satunya hal yang akan saya tambahkan adalah karena SRAM adalah 2K (RAMEND> 1000) maka pernyataan tersebut akan selalu menggunakan 64 daripada 16 pada Nano atau Uno. Jadi jika seseorang ingin memperluas ukuran buffer cincin yang akan menjadi tempat untuk mengubahnya
SDsolar
5

Menerima

Anda dapat melihat dari sumber HardwareSerial bahwa jika byte yang masuk menemukan buffer cincin penuh, itu dibuang:

inline void store_char(unsigned char c, ring_buffer *buffer)
{
  int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != buffer->tail) {
    buffer->buffer[buffer->head] = c;
    buffer->head = i;
  }
}

Saya mendapat kesan bahwa jika saya mengirimkan data ke Arduino dan tidak memiliki "penarik" data aktif di sisi Arduino maka jika lebih banyak data yang masuk daripada yang bisa muat dalam buffer, itu akan dibuang. Bisakah Anda mengonfirmasi itu?

Ya itu akan dibuang. Tidak ada kontrol aliran perangkat lunak atau perangkat keras, kecuali jika Anda menerapkan sendiri.

Namun dengan buffer 64-byte, dan menerima data pada (katakanlah) 9600 baud, Anda mendapatkan satu byte setiap 1,04 ms, dan dengan demikian dibutuhkan 66,6 ms untuk mengisi buffer. Pada prosesor 16 MHz Anda harus dapat memeriksa buffer cukup sering sehingga tidak mengisi. Yang harus Anda lakukan adalah memindahkan data dari buffer HardwareSerial ke milik Anda sendiri, jika Anda tidak ingin memprosesnya sekarang.

Anda dapat melihat dari #if (RAMEND < 1000)cek bahwa prosesor dengan 1000+ byte RAM mendapatkan buffer 64-byte, yang akan lebih sedikit RAM mendapatkan buffer 16-byte.


Mengirim

Data yang Anda tulis ditempatkan di buffer berukuran sama (16 atau 64 byte). Dalam hal pengiriman jika buffer mengisi kode "blok" menunggu interupsi untuk mengirim byte berikutnya keluar dari port serial.

Jika interupsi dimatikan, ini tidak akan pernah terjadi, jadi Anda tidak melakukan pencetakan Serial di dalam Rutin Layanan Interupsi.

Nick Gammon
sumber
Saya percaya Anda tidak aktif dengan urutan besarnya: pada 9600 baud, Anda mendapatkan byte setiap ~ 0,1 ms, jadi hanya butuh 6,6 ms untuk mengisi buffer.
Eric Dand
1
Pada 9600 baud Anda mendapatkan 9600 bit per detik. Karena setiap byte adalah 10 bit (8 data + 1 bit mulai + 1 stop bit) maka Anda mendapatkan 960 byte per detik. 1/960 = 0.001042 s- yaitu satu byte setiap 1,04 ms.
Nick Gammon
Ahh tentu saja, bit bukan byte! Terima kasih atas koreksinya.
Eric Dand
Jadi Nick, tolong jawab ini untuk saya: Jika saya memiliki Pi menjalankan Python duduk di ser.readline () menunggu input sebagai data logger, dan itu dimasukkan melalui serial oleh Arduino mengambil bacaan kemudian mengirimkannya sebagai batch dengan tab delimeter, kemudian menggunakan penundaan (120000) sehingga bets datang setiap dua menit, jeroan Python mungkin segera membaca di setiap karakter sampai menemukan baris baru, di mana titik itu melepaskan seluruh baris sebagai nilai kembali. Jadi saya tidak perlu khawatir tentang ukuran buffer Arduino bahkan jika saya mengirim total 80 karakter, eh? Apakah itu asumsi yang bagus?
SDsolar
Ya, ukuran buffer pengiriman tidak masalah dalam skenario ini. Sebuah buffer kecil akan memperlambat pengiriman (sedikit) tetapi jika Anda melakukan penundaan yang lama Anda tidak akan peduli.
Nick Gammon