- Tx FIFO management fixed
This commit is contained in:
		
							parent
							
								
									627e038dbb
								
							
						
					
					
						commit
						0adc9c8664
					
				@ -62,7 +62,7 @@ typedef struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ----------------
 | 
					// ----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define USB_CDC_PCKT_BUFSIZE (120)
 | 
					#define USB_CDC_PCKT_BUFSIZE (128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ----------------
 | 
					// ----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										71
									
								
								usb_driver.c
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								usb_driver.c
									
									
									
									
									
								
							@ -178,11 +178,9 @@ void usbdrv_preload_endpoint_config(uint8_t ep, uint8_t dir, const USBDRV_EpConf
 | 
				
			|||||||
    if (dir == USB_OUT) {
 | 
					    if (dir == USB_OUT) {
 | 
				
			||||||
        gs.ep_OUT[ep] = *cfg;
 | 
					        gs.ep_OUT[ep] = *cfg;
 | 
				
			||||||
        gs.ep_OUT[ep].is_configured = true;
 | 
					        gs.ep_OUT[ep].is_configured = true;
 | 
				
			||||||
        gs.ep_OUT[ep].task_commenced = USB_EPEVT_IDLE;
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        gs.ep_IN[ep] = *cfg;
 | 
					        gs.ep_IN[ep] = *cfg;
 | 
				
			||||||
        gs.ep_IN[ep].is_configured = true;
 | 
					        gs.ep_IN[ep].is_configured = true;
 | 
				
			||||||
        gs.ep_IN[ep].task_commenced = USB_EPEVT_IDLE;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -400,7 +398,7 @@ void usbdrv_set_rx_fifo_size(uint16_t size) {
 | 
				
			|||||||
// stall endpoint
 | 
					// stall endpoint
 | 
				
			||||||
void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall) {
 | 
					void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall) {
 | 
				
			||||||
    USB_OTG_INEndpointTypeDef *inep = USBINEP + ep;
 | 
					    USB_OTG_INEndpointTypeDef *inep = USBINEP + ep;
 | 
				
			||||||
    USB_OTG_OUTEndpointTypeDef *outep = USBOUTEP + ep;
 | 
					    // USB_OTG_OUTEndpointTypeDef *outep = USBOUTEP + ep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (stall) {
 | 
					    if (stall) {
 | 
				
			||||||
        if (dir == USB_IN) {
 | 
					        if (dir == USB_IN) {
 | 
				
			||||||
@ -418,10 +416,6 @@ void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // flush trnasmit FIFO
 | 
					        // flush trnasmit FIFO
 | 
				
			||||||
        usbdrv_flush_tx_fifo(ep);
 | 
					        usbdrv_flush_tx_fifo(ep);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // signal that the endpoint is stalled
 | 
					 | 
				
			||||||
        gs.ep_IN[ep].task_commenced = USB_EPEVT_STALLED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        if (dir == USB_IN) {
 | 
					        if (dir == USB_IN) {
 | 
				
			||||||
            if (ep != 0) {                                     // special treatment for EP0
 | 
					            if (ep != 0) {                                     // special treatment for EP0
 | 
				
			||||||
@ -429,9 +423,6 @@ void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall) {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            CLEAR_BIT(inep->DIEPCTL, USB_OTG_DIEPCTL_STALL); // clear endpoint stall
 | 
					            CLEAR_BIT(inep->DIEPCTL, USB_OTG_DIEPCTL_STALL); // clear endpoint stall
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // signal that the endpoint stalling is over
 | 
					 | 
				
			||||||
        gs.ep_IN[ep].task_commenced = USB_EPEVT_IDLE;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -476,24 +467,24 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
 | 
				
			|||||||
    /*WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_XFRSIZ, len);
 | 
					    /*WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_XFRSIZ, len);
 | 
				
			||||||
    WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_PKTCNT, 1);*/
 | 
					    WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_PKTCNT, 1);*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // endpoint is already armed
 | 
					    // transmission may only be commenced if last transmission has concluded
 | 
				
			||||||
    // if (gs.ep_IN[ep].task_commenced == USB_EPEVT_ARMED) {
 | 
					    if (READ_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA)) {
 | 
				
			||||||
    //     return;
 | 
					        return 0;
 | 
				
			||||||
    // }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // gs.ep_IN[ep].task_commenced = USB_EPEVT_ARMED;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // determine final write size
 | 
					    // determine final write size
 | 
				
			||||||
    uint32_t freeSize = USBINEP[ep].DTXFSTS * sizeof(uint32_t); // get free transmit buffer size
 | 
					    uint32_t freeSize = USBINEP[ep].DTXFSTS * sizeof(uint32_t); // get free transmit buffer size
 | 
				
			||||||
    uint16_t writeSize = MIN(freeSize, len); // limit transmit size to free size
 | 
					    uint16_t writeSize = MIN(freeSize, len);                    // limit transmit size to free size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // calculate packet count based on max packet size
 | 
					    // calculate packet count based on max packet size
 | 
				
			||||||
    uint16_t mps = gs.ep_IN[ep].max_packet_size;
 | 
					    uint16_t mps = gs.ep_IN[ep].max_packet_size;
 | 
				
			||||||
    uint16_t packet_count = 1; // for ZLPs
 | 
					    uint16_t packet_count = 1; // for ZLPs
 | 
				
			||||||
    if (writeSize > 0) {             // if length is nonzero
 | 
					    if (writeSize > 0) {       // if length is nonzero
 | 
				
			||||||
        packet_count = writeSize / mps + (((writeSize % mps) > 0) ? 1 : 0);
 | 
					        packet_count = writeSize / mps + (((writeSize % mps) > 0) ? 1 : 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // TODO: ZLP ending
 | 
					
 | 
				
			||||||
 | 
					    // set zlp_next if transmission size is integer multiple of max packet size
 | 
				
			||||||
 | 
					    gs.ep_IN[ep].zlp_next = (writeSize > 0) && ((writeSize % mps) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // program DIEPTSIZ with transfer length (TODO: currently only a single transfer!)
 | 
					    // program DIEPTSIZ with transfer length (TODO: currently only a single transfer!)
 | 
				
			||||||
    USBINEP[ep].DIEPTSIZ = (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | writeSize;
 | 
					    USBINEP[ep].DIEPTSIZ = (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | writeSize;
 | 
				
			||||||
@ -533,12 +524,8 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// arm OUT endpoint
 | 
					// arm OUT endpoint
 | 
				
			||||||
void usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size) {
 | 
					void usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size) {
 | 
				
			||||||
    // if (gs.ep_OUT[ep].task_commenced == USB_EPEVT_IDLE) { // only effective if endpointis not armed (no double arming!)
 | 
					 | 
				
			||||||
    //     gs.ep_OUT[ep].task_commenced = USB_EPEVT_ARMED;   // step in armed state
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    USBOUTEP[ep].DOEPTSIZ |= USB_OTG_DOEPTSIZ_PKTCNT | size;                     // program DIEPTSIZ with maximum (expected) transfer length and set PCKTCNT to make ready for reception
 | 
					    USBOUTEP[ep].DOEPTSIZ |= USB_OTG_DOEPTSIZ_PKTCNT | size;                     // program DIEPTSIZ with maximum (expected) transfer length and set PCKTCNT to make ready for reception
 | 
				
			||||||
    SET_BIT(USBOUTEP[ep].DOEPCTL, USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK); // enable endpoint and clear NAK
 | 
					    SET_BIT(USBOUTEP[ep].DOEPCTL, USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK); // enable endpoint and clear NAK
 | 
				
			||||||
    //}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ----------------
 | 
					// ----------------
 | 
				
			||||||
@ -618,11 +605,6 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
 | 
				
			|||||||
    case USB_FSM_SETUP_OPERATE: { // expect SETUP transactions first, then everything else as well
 | 
					    case USB_FSM_SETUP_OPERATE: { // expect SETUP transactions first, then everything else as well
 | 
				
			||||||
        switch (evt_code) {
 | 
					        switch (evt_code) {
 | 
				
			||||||
        case USB_EVT_RECEPTION_DONE: { // reception done
 | 
					        case USB_EVT_RECEPTION_DONE: { // reception done
 | 
				
			||||||
 | 
					 | 
				
			||||||
            // for (uint32_t i = 0; i < 100000; i++) {
 | 
					 | 
				
			||||||
            //     __NOP();
 | 
					 | 
				
			||||||
            // }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            USBDRV_EventData evt_data = {0};
 | 
					            USBDRV_EventData evt_data = {0};
 | 
				
			||||||
            usbdrv_process_rx_fifo_top(&evt_data); // process rx fifo top
 | 
					            usbdrv_process_rx_fifo_top(&evt_data); // process rx fifo top
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -641,11 +623,6 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
 | 
				
			|||||||
                } else if (evt_data.rx.pckt_status == USB_PCKT_STATUS_OUT_TRANSFER_CPLT) {
 | 
					                } else if (evt_data.rx.pckt_status == USB_PCKT_STATUS_OUT_TRANSFER_CPLT) {
 | 
				
			||||||
                    stage = UST_DATA;
 | 
					                    stage = UST_DATA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // OUT transaction has fired
 | 
					 | 
				
			||||||
                    if (gs.ep_OUT[0].task_commenced == USB_EPEVT_ARMED) {
 | 
					 | 
				
			||||||
                        gs.ep_OUT[0].task_commenced = USB_EPEVT_IDLE;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    USBMSG("--DATA\n");
 | 
					                    USBMSG("--DATA\n");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -681,11 +658,6 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
 | 
				
			|||||||
                        SET_BIT(USBOUTEP[ep].DOEPINT, USB_OTG_DOEPINT_XFRC);
 | 
					                        SET_BIT(USBOUTEP[ep].DOEPINT, USB_OTG_DOEPINT_XFRC);
 | 
				
			||||||
                        USBMSG("OUT\n");
 | 
					                        USBMSG("OUT\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // reset commenced task state
 | 
					 | 
				
			||||||
                        if (gs.ep_OUT[ep].task_commenced == USB_EPEVT_ARMED) {
 | 
					 | 
				
			||||||
                            gs.ep_OUT[ep].task_commenced = USB_EPEVT_IDLE;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        usbdrv_arm_OUT_endpoint(ep, gs.ep_OUT[ep].max_packet_size);
 | 
					                        usbdrv_arm_OUT_endpoint(ep, gs.ep_OUT[ep].max_packet_size);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -707,32 +679,25 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
 | 
				
			|||||||
                    if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC)) { // timeout done
 | 
					                    if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC)) { // timeout done
 | 
				
			||||||
                        SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC);
 | 
					                        SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC);
 | 
				
			||||||
                        USBMSG("TO\n");
 | 
					                        USBMSG("TO\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        gs.ep_IN[ep].task_commenced = USB_EPEVT_IDLE;
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_XFRC)) { // IN transaction done
 | 
					                    if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_XFRC)) { // IN transaction done
 | 
				
			||||||
                        SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_XFRC);
 | 
					                        SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_XFRC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // reset commenced task state
 | 
					                        // see if a ZLP transmission was queued
 | 
				
			||||||
                        if (gs.ep_IN[ep].task_commenced == USB_EPEVT_ARMED) {
 | 
					                        if (gs.ep_IN[ep].zlp_next) {
 | 
				
			||||||
                            gs.ep_IN[ep].task_commenced = USB_EPEVT_IDLE;
 | 
					                            usbdrv_arm_IN_endpoint(ep, NULL, 0); // send ZLP
 | 
				
			||||||
 | 
					                        } else { // no ZLP
 | 
				
			||||||
 | 
					                            USBMSG("IN [%d]\n", ep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            cbcpd.code = USB_CBC_IN_DONE;
 | 
				
			||||||
 | 
					                            usbcore_process_nonsetup_event(&cbcpd);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        USBMSG("IN [%d]\n", ep);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        cbcpd.code = USB_CBC_IN_DONE;
 | 
					 | 
				
			||||||
                        usbcore_process_nonsetup_event(&cbcpd);
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE)) { // IN endpoint IN token received with Tx FIFO empty interrupt
 | 
					                    if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE)) { // IN endpoint IN token received with Tx FIFO empty interrupt
 | 
				
			||||||
                        SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE);
 | 
					                        SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // reset stalled state
 | 
					 | 
				
			||||||
                        if (gs.ep_IN[ep].task_commenced == USB_EPEVT_STALLED) {
 | 
					 | 
				
			||||||
                            usbdrv_stall_endpoint(ep, USB_IN, false);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // USBMSG("IN FIFOEMPTY [%d]\n", ep);
 | 
					                        // USBMSG("IN FIFOEMPTY [%d]\n", ep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        cbcpd.code = USB_CBC_IN_FIFOEMPTY;
 | 
					                        cbcpd.code = USB_CBC_IN_FIFOEMPTY;
 | 
				
			||||||
 | 
				
			|||||||
@ -26,9 +26,7 @@ typedef struct {
 | 
				
			|||||||
    uint8_t is_configured; // the endpoint is in use
 | 
					    uint8_t is_configured; // the endpoint is in use
 | 
				
			||||||
    uint16_t fifo_address; // address in the FIFO
 | 
					    uint16_t fifo_address; // address in the FIFO
 | 
				
			||||||
    uint16_t fifo_size;    // FIFO size
 | 
					    uint16_t fifo_size;    // FIFO size
 | 
				
			||||||
 | 
					    bool8_t zlp_next; // indicates, that ZLP should be transmitted at the end of the current transfer
 | 
				
			||||||
    // management variables
 | 
					 | 
				
			||||||
    uint8_t task_commenced; // task commenced on endpoint
 | 
					 | 
				
			||||||
} USBDRV_EpConfig;
 | 
					} USBDRV_EpConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,51 +0,0 @@
 | 
				
			|||||||
#include "gen_queue.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <memory.h>
 | 
					 | 
				
			||||||
#include <stdbool.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Queue *q_create(uint32_t length, uint32_t elemSize, uint8_t *mem) {
 | 
					 | 
				
			||||||
    Queue *q = (Queue *)mem;
 | 
					 | 
				
			||||||
    q->length = length;
 | 
					 | 
				
			||||||
    q->elemSize = elemSize;
 | 
					 | 
				
			||||||
    q->readIdx = 0;
 | 
					 | 
				
			||||||
    q->writeIdx = 0;
 | 
					 | 
				
			||||||
    memset(q->elements, 0, length * elemSize);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return q;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void q_clear(Queue *q) {
 | 
					 | 
				
			||||||
    q->readIdx = 0;
 | 
					 | 
				
			||||||
    q->writeIdx = 0;
 | 
					 | 
				
			||||||
    memset(q->elements, 0, q->length * q->elemSize);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint32_t q_avail(const Queue *q) {
 | 
					 | 
				
			||||||
    return q->writeIdx - q->readIdx;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MQ_NEXT(size, current) (((current) + 1) % (size))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool q_push(Queue *q, const void *src) {
 | 
					 | 
				
			||||||
    if (MQ_NEXT(q->length, q->writeIdx) == q->readIdx) { // cannot push, queue is full
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // can push
 | 
					 | 
				
			||||||
    memcpy(q->elements + q->writeIdx * q->elemSize, src, q->elemSize);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // advance write pointer
 | 
					 | 
				
			||||||
    q->writeIdx = MQ_NEXT(q->length, q->writeIdx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void q_top(Queue *q, void *dest) {
 | 
					 | 
				
			||||||
    memcpy(dest, q->elements + q->readIdx, q->elemSize);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void q_pop(Queue *q) {
 | 
					 | 
				
			||||||
    if (q_avail(q) > 0) { // if there's something to pop
 | 
					 | 
				
			||||||
        q->readIdx = MQ_NEXT(q->length, q->readIdx);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,72 +0,0 @@
 | 
				
			|||||||
#ifndef CORE_USB_UTILS_GE_QUEUE
 | 
					 | 
				
			||||||
#define CORE_USB_UTILS_GE_QUEUE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdbool.h>
 | 
					 | 
				
			||||||
#include <stdint.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Generic Queue.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    uint32_t writeIdx;  ///< Next block to write
 | 
					 | 
				
			||||||
    uint32_t readIdx;   ///< Next block to read
 | 
					 | 
				
			||||||
    uint32_t length;    ///< Size of circular buffer
 | 
					 | 
				
			||||||
    uint32_t elemSize;  ///< Element size
 | 
					 | 
				
			||||||
    uint8_t elements[]; ///< Array of packets
 | 
					 | 
				
			||||||
} Queue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Create Queue.
 | 
					 | 
				
			||||||
 * @param length length of circular buffer
 | 
					 | 
				
			||||||
 * @param elemSize element size
 | 
					 | 
				
			||||||
 * @param mem backing memory, should be DWORD-aligned!
 | 
					 | 
				
			||||||
 * @return pointer to Queue instance OR NULL on failure
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
Queue *q_create(uint32_t length, uint32_t elemSize, uint8_t *mem);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Create Queue based on storage type.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define Q_CREATE_T(length, T, mem) q_create((length), sizeof(T), (mem))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Calculate required memory size for allocating a new queue fitting
 | 
					 | 
				
			||||||
 * length elements of type T.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define Q_REQ_MEM_SIZE_T(length, T) (sizeof(Queue) + (length * sizeof(T)))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Clear circular buffer.
 | 
					 | 
				
			||||||
 * @param q pointer to Queue
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void q_clear(Queue *q);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Get number of available elements.
 | 
					 | 
				
			||||||
 * @param q pointer to Queue
 | 
					 | 
				
			||||||
 * @return number of available elements
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
uint32_t q_avail(const Queue *q);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Push element to the Queue.
 | 
					 | 
				
			||||||
 * @param q pointer to Queue
 | 
					 | 
				
			||||||
 * @param raw pointer to raw packet
 | 
					 | 
				
			||||||
 * @return true on success, false on failure (e.g.: queue full)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
bool q_push(Queue *q, const void *src);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Get top element.
 | 
					 | 
				
			||||||
 * @param q pointer to Queue
 | 
					 | 
				
			||||||
 * @return top element (COPY, NOT POINTER!)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void q_top(Queue *q, void *dest);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Pop top element.
 | 
					 | 
				
			||||||
 * @param q pointer to Queue
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void q_pop(Queue *q);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* CORE_USB_UTILS_GE_QUEUE */
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user