Skip to content

Commit 123574e

Browse files
makarenyafpistm
authored andcommitted
[USB CDC] Set of fixes for queue
1 parent 250eedf commit 123574e

File tree

2 files changed

+55
-38
lines changed

2 files changed

+55
-38
lines changed

cores/arduino/stm32/usb/cdc/cdc_queue.c

+54-37
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,22 @@ int CDC_TransmitQueue_ReadSize(CDC_TransmitQueue_TypeDef *queue) {
5959
}
6060

6161
// Write provided data into queue.
62-
void CDC_TransmitQueue_Enqueue(CDC_TransmitQueue_TypeDef *queue, const uint8_t *buffer,
63-
uint32_t size) {
62+
void CDC_TransmitQueue_Enqueue(CDC_TransmitQueue_TypeDef *queue,
63+
const uint8_t *buffer, uint32_t size) {
6464
uint32_t sizeToEnd = CDC_TRANSMIT_QUEUE_BUFFER_SIZE - queue->write;
6565
if (sizeToEnd > size) {
6666
memcpy(&queue->buffer[queue->write], &buffer[0], size);
6767
} else {
6868
memcpy(&queue->buffer[queue->write], &buffer[0], sizeToEnd);
6969
memcpy(&queue->buffer[0], &buffer[sizeToEnd], size - sizeToEnd);
7070
}
71-
queue->write = (uint16_t)((queue->write + size) % CDC_TRANSMIT_QUEUE_BUFFER_SIZE);
71+
queue->write = (uint16_t)((queue->write + size) %
72+
CDC_TRANSMIT_QUEUE_BUFFER_SIZE);
7273
}
7374

74-
// Read flat block from queue (biggest as possible, but max CDC_QUEUE_MAX_PACKET_SIZE).
75-
uint8_t *CDC_TransmitQueue_ReadBlock(CDC_TransmitQueue_TypeDef *queue, uint16_t *size) {
75+
// Read flat block from queue biggest as possible, but max QUEUE_MAX_PACKET_SIZE
76+
uint8_t *CDC_TransmitQueue_ReadBlock(CDC_TransmitQueue_TypeDef *queue,
77+
uint16_t *size) {
7678
if (queue->write >= queue->read) {
7779
*size = queue->write - queue->read;
7880
} else {
@@ -83,7 +85,8 @@ uint8_t *CDC_TransmitQueue_ReadBlock(CDC_TransmitQueue_TypeDef *queue, uint16_t
8385
}
8486

8587
void CDC_TransmitQueue_CommitRead(CDC_TransmitQueue_TypeDef *queue) {
86-
queue->read = (queue->read + queue->reserved) % CDC_TRANSMIT_QUEUE_BUFFER_SIZE;
88+
queue->read = (queue->read + queue->reserved) %
89+
CDC_TRANSMIT_QUEUE_BUFFER_SIZE;
8790
}
8891

8992
// Initialize read and write position of queue.
@@ -95,23 +98,33 @@ void CDC_ReceiveQueue_Init(CDC_ReceiveQueue_TypeDef *queue) {
9598

9699
// Reserve block in queue and return pointer to it.
97100
uint8_t *CDC_ReceiveQueue_ReserveBlock(CDC_ReceiveQueue_TypeDef *queue) {
98-
if ((uint16_t)(CDC_RECEIVE_QUEUE_BUFFER_SIZE - queue->write) >= CDC_QUEUE_MAX_PACKET_SIZE &&
99-
(queue->read <= queue->write || (uint16_t)(queue->read - queue->write) >= CDC_QUEUE_MAX_PACKET_SIZE)) {
100-
// have enough space on the rest of buffer to store full-length packet
101-
return &queue->buffer[queue->write];
102-
} else if (queue->read >= CDC_QUEUE_MAX_PACKET_SIZE && queue->read <= queue->write) {
103-
// have enough space on the beginning of buffer to store full-length packet
104-
queue->length = queue->write;
105-
queue->write = 0;
106-
return &queue->buffer[queue->write];
107-
} else {
108-
// have no space to store full-length packet
109-
return 0;
101+
const uint16_t limit =
102+
CDC_RECEIVE_QUEUE_BUFFER_SIZE - CDC_QUEUE_MAX_PACKET_SIZE;
103+
volatile uint16_t read = queue->read;
104+
105+
if (read <= queue->write) {
106+
// if write is limited only by buffer size.
107+
if (queue->write < limit || (queue->write == limit && read > 0)) {
108+
// if size in the rest of buffer is enough for full packet plus 1 byte
109+
// or if it tight enough and write position can be set to 0
110+
return queue->buffer + queue->write;
111+
} else if (read > CDC_QUEUE_MAX_PACKET_SIZE) {
112+
// if size in the rest is not enough, but enough size in head
113+
queue->length = queue->write;
114+
queue->write = 0;
115+
return queue->buffer + queue->write;
116+
}
117+
} else if (queue->write + CDC_QUEUE_MAX_PACKET_SIZE < read) {
118+
// write position must be less than read position
119+
// after reading largest possible packet
120+
return queue->buffer + queue->write;
110121
}
122+
return 0;
111123
}
112124

113125
// Commits block in queue and make it available for reading
114-
void CDC_ReceiveQueue_CommitBlock(CDC_ReceiveQueue_TypeDef *queue, uint16_t size) {
126+
void CDC_ReceiveQueue_CommitBlock(CDC_ReceiveQueue_TypeDef *queue,
127+
uint16_t size) {
115128
queue->write += size;
116129
if (queue->write >= queue->length) {
117130
queue->length = CDC_RECEIVE_QUEUE_BUFFER_SIZE;
@@ -123,38 +136,45 @@ void CDC_ReceiveQueue_CommitBlock(CDC_ReceiveQueue_TypeDef *queue, uint16_t size
123136

124137
// Determine size, available for read
125138
int CDC_ReceiveQueue_ReadSize(CDC_ReceiveQueue_TypeDef *queue) {
126-
if (queue->write >= queue->read) {
127-
return queue->write - queue->read;
128-
} else {
129-
return queue->length + queue->write - queue->read;
139+
// reading length after write make guarantee, that length >= write
140+
// and determined reading size will be smaller or equal than real one.
141+
volatile uint16_t write = queue->write;
142+
volatile uint16_t length = queue->length;
143+
if (write >= queue->read) {
144+
return write - queue->read;
130145
}
146+
return length + write - queue->read;
131147
}
132148

133149
// Read one byte from queue.
134150
int CDC_ReceiveQueue_Dequeue(CDC_ReceiveQueue_TypeDef *queue) {
135-
if (queue->write == queue->read) return -1;
151+
volatile uint16_t write = queue->write;
152+
volatile uint16_t length = queue->length;
153+
if (queue->read == length) queue->read = 0;
154+
if (write == queue->read) return -1;
136155
uint8_t ch = queue->buffer[queue->read++];
137-
if (queue->read >= queue->length) {
156+
if (queue->read >= length) {
138157
queue->read = 0;
139158
}
140159
return ch;
141160
}
142161

143162
// Peek byte from queue.
144163
int CDC_ReceiveQueue_Peek(CDC_ReceiveQueue_TypeDef *queue) {
145-
if (queue->write == queue->read) return -1;
164+
volatile uint16_t write = queue->write;
165+
volatile uint16_t length = queue->length;
166+
if (queue->read >= length) queue->read = 0;
167+
if (write == queue->read) return -1;
146168
return queue->buffer[queue->read];
147169
}
148170

149-
uint16_t CDC_ReceiveQueue_Read(CDC_ReceiveQueue_TypeDef *queue, uint8_t *buffer, uint16_t size) {
171+
uint16_t CDC_ReceiveQueue_Read(CDC_ReceiveQueue_TypeDef *queue,
172+
uint8_t *buffer, uint16_t size) {
150173
volatile uint16_t write = queue->write;
151174
volatile uint16_t length = queue->length;
152175
uint16_t available;
153-
while(write != queue->write || length != queue->length) {
154-
write = queue->write;
155-
length = queue->length;
156-
}
157176

177+
if (queue->read >= length) queue->read = 0;
158178
if (write >= queue->read) {
159179
available = write - queue->read;
160180
} else {
@@ -172,16 +192,13 @@ uint16_t CDC_ReceiveQueue_Read(CDC_ReceiveQueue_TypeDef *queue, uint8_t *buffer,
172192
return size;
173193
}
174194

175-
bool CDC_ReceiveQueue_ReadUntil(CDC_ReceiveQueue_TypeDef *queue, uint8_t terminator, uint8_t *buffer,
176-
uint16_t size, uint16_t* fetched) {
195+
bool CDC_ReceiveQueue_ReadUntil(CDC_ReceiveQueue_TypeDef *queue,
196+
uint8_t terminator, uint8_t *buffer, uint16_t size, uint16_t* fetched) {
177197
volatile uint16_t write = queue->write;
178198
volatile uint16_t length = queue->length;
179199
uint16_t available;
180-
while(write != queue->write || length != queue->length) {
181-
write = queue->write;
182-
length = queue->length;
183-
}
184200

201+
if (queue->read >= length) queue->read = 0;
185202
if (write >= queue->read) {
186203
available = write - queue->read;
187204
} else {

cores/arduino/stm32/usb/cdc/cdc_queue.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
#define CDC_QUEUE_MAX_PACKET_SIZE USB_FS_MAX_PACKET_SIZE
5454
#endif
5555
#define CDC_TRANSMIT_QUEUE_BUFFER_SIZE ((uint16_t)(CDC_QUEUE_MAX_PACKET_SIZE * 2))
56-
#define CDC_RECEIVE_QUEUE_BUFFER_SIZE ((uint16_t)(CDC_QUEUE_MAX_PACKET_SIZE * 2))
56+
#define CDC_RECEIVE_QUEUE_BUFFER_SIZE ((uint16_t)(CDC_QUEUE_MAX_PACKET_SIZE * 3))
5757

5858
typedef struct {
5959
uint8_t buffer[CDC_TRANSMIT_QUEUE_BUFFER_SIZE];

0 commit comments

Comments
 (0)