Skip to main content

mpfs_hal/
ethernet.rs

1use core::future::Future;
2use core::task::{Context, Poll, Waker};
3use embassy_net_driver::{Capabilities, Driver, HardwareAddress};
4use paste::paste;
5
6use crate::pac;
7use crate::{Peripheral, PeripheralRef};
8
9#[doc(hidden)]
10#[repr(align(8))]
11pub struct Buffer([u8; pac::MSS_MAC_MAX_RX_BUF_SIZE as usize]);
12
13pub trait MacPeripheral: 'static + core::fmt::Debug + Peripheral {
14    #[doc(hidden)]
15    fn address(&self) -> *mut pac::mss_mac_instance;
16    #[doc(hidden)]
17    fn tx_buffer(&self) -> &'static mut Buffer;
18    #[doc(hidden)]
19    fn rx_buffer(&self, index: usize) -> &'static mut Buffer;
20}
21
22//-------------------------------------------------------------------
23// Create the MAC peripherals
24// Maybe TODO: We're reserving a moderate amount of memory for the RX and TX buffers
25// (10kB x 65 buffers = 650kB x num MACs)
26// This should probably be opt-in.
27
28macro_rules! impl_mac {
29    ($n:expr) => {
30        paste! {
31            impl_mac!([<MAC $n>], [<MAC $n _TAKEN>], [<MAC_RX_BUFFER $n>], [<MAC_TX_BUFFER $n>], [<g_mac $n>]);
32        }
33    };
34
35    // E.g. impl_mac!(MAC0, MAC0_TAKEN, MAC0_RX_BUFFER, MAC0_TX_BUFFER, g_mss_mac_0);
36    ($MAC:ident, $MAC_TAKEN:ident, $RX_BUFFER:ident, $TX_BUFFER:ident, $instance:ident) => {
37        #[derive(Debug)]
38        pub struct $MAC {
39            _private: (),
40        }
41        static mut $MAC_TAKEN: bool = false;
42        static mut $RX_BUFFER: [Buffer; pac::MSS_MAC_RX_RING_SIZE as usize] =
43    [const { Buffer([0; pac::MSS_MAC_MAX_RX_BUF_SIZE as usize]) };
44        pac::MSS_MAC_RX_RING_SIZE as usize];
45
46        // We're only going to support a single TX at a time, since the platform doesn't
47        // _really_ support multiple TXs.
48        static mut $TX_BUFFER: Buffer = Buffer([0; pac::MSS_MAC_MAX_TX_BUF_SIZE as usize]);
49
50        impl Peripheral for $MAC {
51            fn take() -> Option<Self> {
52                critical_section::with(|_| unsafe {
53                    if $MAC_TAKEN {
54                        None
55                    } else {
56                        $MAC_TAKEN = true;
57                        Some(Self { _private: () })
58                    }
59                })
60            }
61
62            unsafe fn steal() -> Self {
63                Self { _private: () }
64            }
65        }
66
67        impl MacPeripheral for $MAC {
68            fn address(&self) -> *mut pac::mss_mac_instance {
69                &raw mut pac::$instance
70            }
71
72            fn tx_buffer(&self) -> &'static mut Buffer {
73                #[allow(static_mut_refs)]
74                unsafe { &mut $TX_BUFFER }
75            }
76
77            fn rx_buffer(&self, index: usize) -> &'static mut Buffer {
78                unsafe { &mut $RX_BUFFER[index] }
79            }
80        }
81    };
82}
83
84macro_rules! impl_eth {
85    ($n:expr) => {
86        paste! {
87            impl_eth!([<ETH $n>], [<ETH $n _TAKEN>], [<MAC $n>]);
88        }
89    };
90
91    // E.g. impl_mac!(MAC0, MAC0_TAKEN, MAC0_RX_BUFFER, MAC0_TX_BUFFER, g_mss_mac_0);
92    ($ETH:ident, $ETH_TAKEN:ident, $MAC:ident) => {
93        static mut $ETH: Option<EthernetDevice<$MAC>> = None;
94        static mut $ETH_TAKEN: bool = false;
95
96        impl PeripheralRef for EthernetDevice<$MAC> {
97            fn take() -> Option<&'static mut Self> {
98                critical_section::with(|_| unsafe {
99                    if $ETH_TAKEN {
100                        None
101                    } else {
102                        if let Some(mac) = $MAC::take() {
103                            $ETH_TAKEN = true;
104                            $ETH = Some(EthernetDevice::new(mac));
105                            #[allow(static_mut_refs)]
106                            Some($ETH.as_mut().unwrap())
107                        } else {
108                            None
109                        }
110                    }
111                })
112            }
113
114            unsafe fn steal() -> &'static mut Self {
115                unsafe {
116                    $ETH = Some(EthernetDevice::new($MAC::steal()));
117                    #[allow(static_mut_refs)]
118                    $ETH.as_mut().unwrap()
119                }
120            }
121        }
122    };
123}
124
125#[cfg(feature = "beaglev-fire")]
126pub use beaglev_fire::*;
127#[cfg(feature = "beaglev-fire")]
128mod beaglev_fire {
129    use super::*;
130
131    impl_mac!(0); // MAC0
132    impl_eth!(0); // EthernetDevice<MAC0>
133
134    pub(crate) fn default_mac_config() -> pac::mss_mac_cfg_t {
135        pac::mss_mac_cfg_t {
136            phy_addr: pac::PHY_RTL8211_MDIO_ADDR,
137            phy_type: pac::MSS_MAC_DEV_PHY_RTL8211,
138            pcs_phy_addr: pac::SGMII_MDIO_ADDR,
139            interface_type: pac::TBI,
140            phy_autonegotiate: Some(pac::MSS_MAC_RTL8211_phy_autonegotiate),
141            phy_mac_autonegotiate: Some(pac::MSS_MAC_RTL8211_mac_autonegotiate),
142            phy_get_link_status: Some(pac::MSS_MAC_RTL8211_phy_get_link_status),
143            phy_init: Some(pac::MSS_MAC_RTL8211_phy_init),
144            phy_set_link_speed: Some(pac::MSS_MAC_RTL8211_phy_set_link_speed),
145            phy_extended_read: Some(pac::NULL_mmd_read_extended_regs),
146            phy_extended_write: Some(pac::NULL_mmd_write_extended_regs),
147            queue_enable: [0; 4],
148            speed_mode: pac::__mss_mac_speed_mode_t_MSS_MAC_SPEED_AN,
149            speed_duplex_select: pac::MSS_MAC_ANEG_ALL_SPEEDS,
150            mac_addr: [0; 6],
151            phy_controller: core::ptr::null_mut(),
152            tx_edc_enable: 0,
153            rx_edc_enable: 0,
154            jumbo_frame_enable: 1,
155            jumbo_frame_default: pac::MSS_MAC_MAX_PACKET_SIZE,
156            length_field_check: 1,
157            append_CRC: 1,
158            fullduplex: 0,
159            loopback: 0,
160            rx_flow_ctrl: 1,
161            tx_flow_ctrl: 1,
162            ipg_multiplier: pac::MSS_MAC_IPG_DEFVAL,
163            ipg_divisor: pac::MSS_MAC_IPG_DEFVAL,
164            phyclk: pac::MSS_MAC_DEF_PHY_CLK,
165            max_frame_length: 0,
166            use_hi_address: 0,
167            use_local_ints: 0,
168            queue0_int_priority: 7,
169            queue1_int_priority: 7,
170            queue2_int_priority: 7,
171            queue3_int_priority: 7,
172            mmsl_int_priority: 7,
173            tsu_clock_select: 1,
174            amba_burst_length: pac::MSS_MAC_AMBA_BURST_16,
175        }
176    }
177}
178
179//-------------------------------------------------------------------
180// Ethernet
181
182#[derive(Debug, Clone, Copy)]
183pub enum LinkSpeed {
184    Speed10MBPS,
185    Speed100MBPS,
186    Speed1000MBPS,
187}
188
189#[derive(Debug, Clone, Copy, PartialEq, Eq)]
190pub enum LinkState {
191    Down,
192    Up,
193}
194
195impl LinkState {
196    pub fn is_up(&self) -> bool {
197        *self == LinkState::Up
198    }
199}
200
201#[derive(Debug)]
202pub struct EthernetTx<M: MacPeripheral> {
203    ethernet: *mut EthernetDevice<M>,
204}
205
206impl<M: MacPeripheral> EthernetTx<M> {
207    pub fn send<R, F>(&mut self, len: usize, f: F) -> R
208    where
209        F: FnOnce(&mut [u8]) -> R,
210    {
211        let ethernet = unsafe { &mut *self.ethernet };
212        ethernet._send(len, f)
213    }
214}
215
216pub struct EthernetRx<M: MacPeripheral> {
217    ethernet: *mut EthernetDevice<M>,
218}
219
220impl<M: MacPeripheral> EthernetRx<M> {
221    pub async fn receive<R, F>(&mut self, f: F) -> R
222    where
223        F: FnOnce(&mut [u8]) -> R,
224    {
225        let ethernet = unsafe { &mut *self.ethernet };
226        ethernet._receive(f).await
227    }
228}
229
230#[derive(Debug)]
231pub enum RxError {
232    Split,
233}
234
235#[derive(Debug)]
236pub enum TxError {
237    Split,
238}
239
240pub struct EthernetDevice<M: MacPeripheral> {
241    mac: M,
242    rx_waker: Option<Waker>,
243    // (index, length)
244    pending_rx: RingBuffer<(usize, usize), { pac::MSS_MAC_RX_RING_SIZE as usize }>,
245    rx_tokens_issued: usize,
246    tx_buffer_in_use: bool,
247    link_speed: LinkSpeed,
248    full_duplex: bool,
249    split: bool,
250}
251
252impl<M: MacPeripheral> EthernetDevice<M> {
253    fn new(mac: M) -> Self {
254        debug!(
255            "Creating EthernetDevice with rx ring size {}",
256            pac::MSS_MAC_RX_RING_SIZE
257        );
258        Self {
259            mac,
260            pending_rx: RingBuffer {
261                buffer: [(0, 0); pac::MSS_MAC_RX_RING_SIZE as usize],
262                head: 0,
263                tail: 0,
264                size: 0,
265            },
266            rx_tokens_issued: 0,
267            tx_buffer_in_use: false,
268            rx_waker: None,
269            link_speed: LinkSpeed::Speed10MBPS,
270            full_duplex: false,
271            split: false,
272        }
273    }
274
275    pub fn init(&self, mac_address: [u8; 6]) {
276        unsafe {
277            let mut config = default_mac_config();
278            config.mac_addr = mac_address;
279            pac::MSS_MAC_init(self.mac.address(), &mut config as *mut _);
280
281            pac::MSS_MAC_set_tx_callback(
282                self.mac.address(),
283                0,
284                Some(packet_tx_complete_handler::<M>),
285            );
286            pac::MSS_MAC_set_rx_callback(self.mac.address(), 0, Some(mac_rx_callback::<M>));
287
288            // Allocate receive buffers for all slots in the ring
289            for i in 0..pac::MSS_MAC_RX_RING_SIZE as usize {
290                let enable_interrupts = if i == (pac::MSS_MAC_RX_RING_SIZE as usize - 1) {
291                    -1 // Enable interrupts for last buffer
292                } else {
293                    0 // Keep interrupts disabled for all other buffers
294                };
295
296                pac::MSS_MAC_receive_pkt(
297                    self.mac.address(),
298                    0,
299                    self.mac.rx_buffer(i).0.as_mut_ptr(),
300                    self as *const _ as *mut core::ffi::c_void,
301                    enable_interrupts,
302                );
303            }
304
305            {
306                // Set up the most significant 32 bits of the tx buffer address
307                // This is done in platform for the RX, but it's omitted for the TX, for some reason.
308                let mac_base = (*self.mac.address()).mac_base;
309                // Disable transmit while configuring queue
310                (*mac_base).NETWORK_CONTROL &= !pac::GEM_ENABLE_TRANSMIT;
311                (*mac_base).UPPER_TX_Q_BASE_ADDR =
312                    (self.mac.tx_buffer().0.as_ptr() as u64 >> 32) as u32;
313                (*mac_base).NETWORK_CONTROL |= pac::GEM_ENABLE_TRANSMIT;
314                core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
315            }
316
317            pac::MSS_MAC_tx_enable(self.mac.address());
318
319            trace!("MAC config: {:#?}", config);
320            debug!("MAC initialized");
321        }
322    }
323
324    pub fn split(&mut self) -> (EthernetTx<M>, EthernetRx<M>) {
325        self.split = true;
326        (
327            EthernetTx {
328                ethernet: self as *mut _,
329            },
330            EthernetRx {
331                ethernet: self as *mut _,
332            },
333        )
334    }
335
336    pub fn link_speed(&self) -> LinkSpeed {
337        self.link_speed
338    }
339
340    pub fn full_duplex(&self) -> bool {
341        self.full_duplex
342    }
343
344    #[doc(hidden)]
345    pub fn debug_mac_queue(&self) {
346        debug!("MAC queue 0: {:#?}", unsafe {
347            (*self.mac.address()).queue[0]
348        });
349    }
350
351    pub fn send<R, F>(&mut self, len: usize, f: F) -> Result<R, TxError>
352    where
353        F: FnOnce(&mut [u8]) -> R,
354    {
355        if self.split {
356            Err(TxError::Split)
357        } else {
358            Ok(self._send(len, f))
359        }
360    }
361
362    fn _send<R, F>(&mut self, len: usize, f: F) -> R
363    where
364        F: FnOnce(&mut [u8]) -> R,
365    {
366        let mut lock_count = 0;
367        loop {
368            if !self.tx_buffer_in_use {
369                let got_lock = critical_section::with(|_| {
370                    // Check again, since we might have lost the lock
371                    if !self.tx_buffer_in_use {
372                        self.tx_buffer_in_use = true;
373                        true
374                    } else {
375                        false
376                    }
377                });
378                if got_lock {
379                    break;
380                }
381            }
382            lock_count += 1;
383
384            // Clear the lock if we get stuck here, since it's possible a bad packet will never get its callback called.
385            if lock_count > 1000 {
386                self.tx_buffer_in_use = false;
387                warn!("Failed to get lock on ethernet TX buffer, resetting");
388            }
389        }
390        if len > self.mac.tx_buffer().0.len() {
391            panic!(
392                "Max ethernet TX packet size {} exceeded",
393                self.mac.tx_buffer().0.len()
394            );
395        }
396        // We own the tx buffer now, so we can send the packet
397        let ret = f(&mut self.mac.tx_buffer().0[0..len]);
398        self.send_pkt(len);
399
400        ret
401    }
402
403    // The packet is expected to be in the tx buffer already
404    fn send_pkt(&mut self, len: usize) {
405        unsafe {
406            let tx_status = pac::MSS_MAC_send_pkt(
407                self.mac.address(),
408                0,
409                self.mac.tx_buffer().0.as_ptr(),
410                len as u32,
411                self as *const _ as *mut core::ffi::c_void,
412            );
413            if tx_status != 1 {
414                error!("Failed to send packet");
415            }
416        }
417    }
418    pub async fn receive<R, F>(&mut self, f: F) -> Result<R, RxError>
419    where
420        F: FnOnce(&mut [u8]) -> R,
421    {
422        if self.split {
423            Err(RxError::Split)
424        } else {
425            Ok(self._receive(f).await)
426        }
427    }
428
429    async fn _receive<R, F>(&mut self, f: F) -> R
430    where
431        F: FnOnce(&mut [u8]) -> R,
432    {
433        let future = RxFuture {
434            ethernet: self as *mut _,
435        };
436        let token = future.await;
437        embassy_net_driver::RxToken::consume(token, f)
438    }
439
440    pub fn link_state(&mut self) -> LinkState {
441        let mut test_speed = pac::__mss_mac_speed_t_MSS_MAC_1000MBPS;
442        let mut test_fullduplex = 0;
443        let test_linkup = unsafe {
444            pac::MSS_MAC_get_link_status(self.mac.address(), &mut test_speed, &mut test_fullduplex)
445        };
446
447        if test_linkup == 0 {
448            return LinkState::Down;
449        }
450        if test_speed == pac::__mss_mac_speed_t_MSS_MAC_1000MBPS {
451            self.link_speed = LinkSpeed::Speed1000MBPS;
452        } else if test_speed == pac::__mss_mac_speed_t_MSS_MAC_100MBPS {
453            self.link_speed = LinkSpeed::Speed100MBPS;
454        } else {
455            self.link_speed = LinkSpeed::Speed10MBPS;
456        }
457
458        self.full_duplex = test_fullduplex != 0;
459
460        LinkState::Up
461    }
462
463    pub fn mac_address(&self) -> [u8; 6] {
464        let mac = unsafe { *self.mac.address() };
465        mac.mac_addr
466    }
467}
468
469impl<M: MacPeripheral> Driver for EthernetDevice<M> {
470    type RxToken<'a> = RxToken<'a, M>;
471    type TxToken<'a> = TxToken<'a, M>;
472
473    fn receive(&mut self, cx: &mut Context<'_>) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
474        critical_section::with(|_| {
475            if !self.split && self.rx_tokens_issued < self.pending_rx.size {
476                self.rx_tokens_issued += 1;
477                Some((
478                    RxToken {
479                        phantom: core::marker::PhantomData,
480                        ethernet: self as *mut _,
481                    },
482                    self.transmit(cx).unwrap(),
483                ))
484            } else {
485                if self.split {
486                    warn!("RX split, not receiving");
487                }
488                self.rx_waker = Some(cx.waker().clone());
489                None
490            }
491        })
492    }
493
494    fn transmit(&mut self, _cx: &mut Context<'_>) -> Option<Self::TxToken<'_>> {
495        // We can actually create as many TxTokens as we want: What matters is that we don't consume
496        // more than one at a time. Consume will take the lock on ethernet.
497        if self.split {
498            warn!("TX split, not transmitting");
499            None
500        } else {
501            Some(TxToken {
502                phantom: core::marker::PhantomData,
503                ethernet: self as *mut _,
504            })
505        }
506    }
507
508    fn link_state(&mut self, cx: &mut Context<'_>) -> embassy_net_driver::LinkState {
509        cx.waker().wake_by_ref();
510        match self.link_state() {
511            LinkState::Up => embassy_net_driver::LinkState::Up,
512            LinkState::Down => embassy_net_driver::LinkState::Down,
513        }
514    }
515
516    fn capabilities(&self) -> Capabilities {
517        let mut caps = Capabilities::default();
518        caps.max_transmission_unit = 9216; // Max allowable according to Capabilities struct
519        caps.max_burst_size = Some(pac::MSS_MAC_RX_RING_SIZE as usize);
520        caps
521    }
522
523    fn hardware_address(&self) -> HardwareAddress {
524        HardwareAddress::Ethernet(self.mac_address())
525    }
526}
527
528//------------------------------------------------------
529// Tokens
530
531pub struct RxToken<'a, M: MacPeripheral> {
532    phantom: core::marker::PhantomData<&'a ()>,
533    ethernet: *mut EthernetDevice<M>,
534}
535
536impl<'a, M: MacPeripheral> embassy_net_driver::RxToken for RxToken<'a, M> {
537    fn consume<R, F>(self, f: F) -> R
538    where
539        F: FnOnce(&mut [u8]) -> R,
540    {
541        let ethernet = unsafe { &mut *self.ethernet };
542
543        let (buffer_number, len) = critical_section::with(|_| ethernet.pending_rx.pop().unwrap());
544        let rx_buf = &mut ethernet.mac.rx_buffer(buffer_number).0[0..len];
545        let ret = f(rx_buf);
546        unsafe {
547            pac::MSS_MAC_receive_pkt(
548                ethernet.mac.address(),
549                0,
550                rx_buf.as_mut_ptr(),
551                self.ethernet as *mut _,
552                1,
553            );
554        }
555        critical_section::with(|_| {
556            ethernet.rx_tokens_issued -= 1;
557        });
558        trace!("Consumed RX token");
559        ret
560    }
561}
562
563pub struct TxToken<'a, M: MacPeripheral> {
564    phantom: core::marker::PhantomData<&'a ()>,
565    ethernet: *mut EthernetDevice<M>,
566}
567
568impl<'a, M: MacPeripheral> embassy_net_driver::TxToken for TxToken<'a, M> {
569    fn consume<R, F>(self, len: usize, f: F) -> R
570    where
571        F: FnOnce(&mut [u8]) -> R,
572    {
573        let ethernet = unsafe { &mut *self.ethernet };
574        ethernet.send(len, f).unwrap()
575    }
576}
577
578//------------------------------------------------------
579
580pub struct RxFuture<M: MacPeripheral> {
581    ethernet: *mut EthernetDevice<M>,
582}
583
584impl<M: MacPeripheral> Future for RxFuture<M> {
585    type Output = RxToken<'static, M>;
586
587    fn poll(mut self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
588        critical_section::with(|_| {
589            let ethernet = unsafe { &mut *self.ethernet };
590            if ethernet.rx_tokens_issued < ethernet.pending_rx.size {
591                ethernet.rx_tokens_issued += 1;
592                Poll::Ready(RxToken {
593                    phantom: core::marker::PhantomData,
594                    ethernet: self.ethernet as *mut _,
595                })
596            } else {
597                ethernet.rx_waker = Some(cx.waker().clone());
598                Poll::Pending
599            }
600        })
601    }
602}
603
604// ----------------------------------------------------
605// Callbacks
606
607extern "C" fn packet_tx_complete_handler<M: MacPeripheral>(
608    _mac: *mut core::ffi::c_void,
609    _queue: u32,
610    _desc: *mut pac::mss_mac_tx_desc,
611    user_data: *mut core::ffi::c_void,
612) {
613    trace!("MAC packet TX callback");
614    unsafe {
615        let ethernet = (user_data as *mut EthernetDevice<M>).as_mut().unwrap();
616        ethernet.tx_buffer_in_use = false;
617    }
618}
619
620extern "C" fn mac_rx_callback<M: MacPeripheral>(
621    _mac: *mut core::ffi::c_void,
622    _queue: u32,
623    rx_buf: *mut u8,
624    rx_size: u32,
625    _rx_desc: *mut pac::mss_mac_rx_desc,
626    user_data: *mut core::ffi::c_void,
627) {
628    trace!("MAC packet RX callback of size: {}", rx_size);
629    unsafe {
630        let ethernet = (user_data as *mut EthernetDevice<M>).as_mut().unwrap();
631        let buffer_number = (rx_buf as usize - (*ethernet).mac.rx_buffer(0).0.as_ptr() as usize)
632            / (pac::MSS_MAC_MAX_RX_BUF_SIZE as usize);
633        let succeeded = critical_section::with(|_| {
634            if let Some(waker) = (*ethernet).rx_waker.take() {
635                waker.wake_by_ref();
636            }
637            (*ethernet)
638                .pending_rx
639                .push((buffer_number, rx_size as usize))
640        });
641        if !succeeded {
642            warn!("Failed to push to pending rx");
643            pac::MSS_MAC_receive_pkt(ethernet.mac.address(), 0, rx_buf, user_data as *mut _, 1);
644        }
645    }
646}
647
648//------------------------------------------------------
649// Ring buffer
650struct RingBuffer<T: core::fmt::Debug, const N: usize> {
651    buffer: [T; N],
652    head: usize,
653    tail: usize,
654    size: usize, // current number of elements
655}
656
657impl<T: core::fmt::Debug, const N: usize> core::fmt::Debug for RingBuffer<T, N> {
658    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
659        write!(f, "RingBuffer[")?;
660
661        // let mut count = 0;
662        // let mut idx = self.tail;
663        // while count < self.size {
664        //     if count > 0 {
665        //         write!(f, ", ")?;
666        //     }
667        //     write!(f, "{:?}", self.buffer[idx])?;
668        //     idx = (idx + 1) % N;
669        //     count += 1;
670        // }
671
672        write!(
673            f,
674            "] (size: {}, head: {}, tail: {})",
675            self.size, self.head, self.tail
676        )
677    }
678}
679
680impl<T: Default + Copy + core::fmt::Debug, const N: usize> RingBuffer<T, N> {
681    #[allow(dead_code)]
682    fn new() -> Self {
683        Self {
684            buffer: [T::default(); N],
685            head: 0,
686            tail: 0,
687            size: 0,
688        }
689    }
690
691    // Returns false if the buffer is full
692    fn push(&mut self, item: T) -> bool {
693        if self.is_full() {
694            return false;
695        }
696        self.buffer[self.head] = item;
697        self.head = (self.head + 1) % N;
698        self.size += 1;
699        true
700    }
701
702    fn is_full(&self) -> bool {
703        self.size == N
704    }
705
706    fn is_empty(&self) -> bool {
707        self.size == 0
708    }
709
710    fn pop(&mut self) -> Option<T> {
711        if self.is_empty() {
712            None
713        } else {
714            let item = self.buffer[self.tail];
715            self.tail = (self.tail + 1) % N;
716            self.size -= 1;
717            Some(item)
718        }
719    }
720}