Fixed problem with OTG buffers alignment.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8281 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
gdisirio 2015-09-06 09:31:49 +00:00
parent 4c19d32590
commit fa1c7f8bd2
2 changed files with 61 additions and 123 deletions

View File

@ -229,30 +229,6 @@ static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
return next;
}
/**
* @brief Pushes a series of words into a FIFO.
*
* @param[in] fifop pointer to the FIFO register
* @param[in] buf pointer to the words buffer, not necessarily word
* aligned
* @param[in] n number of words to push
*
* @return A pointer after the last word pushed.
*
* @notapi
*/
static uint8_t *otg_do_push(volatile uint32_t *fifop, uint8_t *buf, size_t n) {
while (n > 0) {
/* Note, this line relies on the Cortex-M3/M4 ability to perform
unaligned word accesses and on the LSB-first memory organization.*/
*fifop = *((PACKED_VAR uint32_t *)buf);
buf += 4;
n--;
}
return buf;
}
/**
* @brief Writes to a TX FIFO.
*
@ -265,8 +241,25 @@ static uint8_t *otg_do_push(volatile uint32_t *fifop, uint8_t *buf, size_t n) {
static void otg_fifo_write_from_buffer(volatile uint32_t *fifop,
const uint8_t *buf,
size_t n) {
uint32_t w;
size_t i;
otg_do_push(fifop, (uint8_t *)buf, (n + 3) / 4);
/* Pushing all complete words.*/
i = 0;
w = 0;
while (i < n) {
w |= (uint32_t)*buf++ << ((i & 3) * 8);
i++;
if ((i & 3) == 0) {
*fifop = w;
w = 0;
}
}
/* Remaining bytes.*/
if ((i & 3) != 0) {
*fifop = w;
}
}
/**
@ -281,40 +274,27 @@ static void otg_fifo_write_from_buffer(volatile uint32_t *fifop,
static void otg_fifo_write_from_queue(volatile uint32_t *fifop,
output_queue_t *oqp,
size_t n) {
size_t ntogo;
uint32_t w;
size_t i;
ntogo = n;
while (ntogo > 0) {
uint32_t w, i;
size_t nw = ntogo / 4;
if (nw > 0) {
size_t streak;
uint32_t nw2end = (oqp->q_top - oqp->q_rdptr) / 4;
ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4;
oqp->q_rdptr = otg_do_push(fifop, oqp->q_rdptr, streak);
if (oqp->q_rdptr >= oqp->q_top) {
oqp->q_rdptr = oqp->q_buffer;
continue;
}
/* Pushing all complete words.*/
i = 0;
w = 0;
while (i < n) {
w |= (uint32_t)*oqp->q_rdptr << ((i & 3) * 8);
oqp->q_rdptr++;
if (oqp->q_rdptr >= oqp->q_top) {
oqp->q_rdptr = oqp->q_buffer;
}
/* If this condition is not satisfied then there is a word lying across
queue circular buffer boundary or there are some remaining bytes.*/
if (ntogo <= 0)
break;
/* One byte at time.*/
w = 0;
i = 0;
while ((ntogo > 0) && (i < 4)) {
w |= (uint32_t)*oqp->q_rdptr++ << (i * 8);
if (oqp->q_rdptr >= oqp->q_top)
oqp->q_rdptr = oqp->q_buffer;
ntogo--;
i++;
i++;
if ((i & 3) == 0) {
*fifop = w;
w = 0;
}
}
/* Remaining bytes.*/
if ((i & 3) != 0) {
*fifop = w;
}
@ -326,31 +306,6 @@ static void otg_fifo_write_from_queue(volatile uint32_t *fifop,
osalSysUnlock();
}
/**
* @brief Pops a series of words from a FIFO.
*
* @param[in] fifop pointer to the FIFO register
* @param[in] buf pointer to the words buffer, not necessarily word
* aligned
* @param[in] n number of words to push
*
* @return A pointer after the last word pushed.
*
* @notapi
*/
static uint8_t *otg_do_pop(volatile uint32_t *fifop, uint8_t *buf, size_t n) {
while (n > 0) {
uint32_t w = *fifop;
/* Note, this line relies on the Cortex-M3/M4 ability to perform
unaligned word accesses and on the LSB-first memory organization.*/
*((PACKED_VAR uint32_t *)buf) = w;
buf += 4;
n--;
}
return buf;
}
/**
* @brief Reads a packet from the RXFIFO.
*
@ -365,19 +320,19 @@ static void otg_fifo_read_to_buffer(volatile uint32_t *fifop,
uint8_t *buf,
size_t n,
size_t max) {
uint32_t w;
size_t i;
n = (n + 3) / 4;
max = (max + 3) / 4;
while (n) {
uint32_t w = *fifop;
if (max) {
/* Note, this line relies on the Cortex-M3/M4 ability to perform
unaligned word accesses and on the LSB-first memory organization.*/
*((PACKED_VAR uint32_t *)buf) = w;
buf += 4;
max--;
i = 0;
while (i < n) {
if ((i & 3) == 0){
w = *fifop;
}
n--;
if (i < max) {
*buf++ = (uint8_t)w;
w >>= 8;
}
i++;
}
}
@ -393,40 +348,21 @@ static void otg_fifo_read_to_buffer(volatile uint32_t *fifop,
static void otg_fifo_read_to_queue(volatile uint32_t *fifop,
input_queue_t *iqp,
size_t n) {
size_t ntogo;
uint32_t w;
size_t i;
ntogo = n;
while (ntogo > 0) {
uint32_t w, i;
size_t nw = ntogo / 4;
if (nw > 0) {
size_t streak;
uint32_t nw2end = (iqp->q_wrptr - iqp->q_wrptr) / 4;
ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4;
iqp->q_wrptr = otg_do_pop(fifop, iqp->q_wrptr, streak);
if (iqp->q_wrptr >= iqp->q_top) {
iqp->q_wrptr = iqp->q_buffer;
continue;
}
i = 0;
while (i < n) {
if ((i & 3) == 0){
w = *fifop;
}
/* If this condition is not satisfied then there is a word lying across
queue circular buffer boundary or there are some remaining bytes.*/
if (ntogo <= 0)
break;
/* One byte at time.*/
w = *fifop;
i = 0;
while ((ntogo > 0) && (i < 4)) {
*iqp->q_wrptr++ = (uint8_t)(w >> (i * 8));
if (iqp->q_wrptr >= iqp->q_top)
iqp->q_wrptr = iqp->q_buffer;
ntogo--;
i++;
*iqp->q_wrptr = (uint8_t)w;
iqp->q_wrptr++;
if (iqp->q_wrptr >= iqp->q_top) {
iqp->q_wrptr = iqp->q_buffer;
}
w >>= 8;
i++;
}
/* Updating queue.*/

View File

@ -73,6 +73,8 @@
*****************************************************************************
*** 3.1.0 ***
- HAL: STM32 OTG buffers and queues do not more require to be aligned in
position and size.
- VAR: Improved GCC rules.ld, now it is possible to assign the heap to any
of the available RAM regions.
- HAL: STM32 GPT, ICU and PWM driver enhancements. Now it is possible to