diff --git a/demos/ARM7-AT91SAM7X-WEB-GCC/Makefile b/demos/ARM7-AT91SAM7X-WEB-GCC/Makefile index bb4c21c1a..345cb3d13 100644 --- a/demos/ARM7-AT91SAM7X-WEB-GCC/Makefile +++ b/demos/ARM7-AT91SAM7X-WEB-GCC/Makefile @@ -5,7 +5,7 @@ # Compiler options here. ifeq ($(USE_OPT),) - USE_OPT = -O2 -ggdb -fomit-frame-pointer -mabi=apcs-gnu + USE_OPT = -O0 -ggdb -fomit-frame-pointer -mabi=apcs-gnu endif # C++ specific options here (added to USE_OPT). diff --git a/demos/ARM7-AT91SAM7X-WEB-GCC/web/webthread.c b/demos/ARM7-AT91SAM7X-WEB-GCC/web/webthread.c index 521a40b04..986d7fb03 100644 --- a/demos/ARM7-AT91SAM7X-WEB-GCC/web/webthread.c +++ b/demos/ARM7-AT91SAM7X-WEB-GCC/web/webthread.c @@ -47,21 +47,18 @@ static const struct uip_eth_addr macaddr = { */ static void network_device_send(void) { int i; - MACTransmitDescriptor *tdp; + MACTransmitDescriptor td; for (i = 0; i < SEND_RETRY_MAX; i++) { - if ((tdp = macWaitTransmitDescriptor(&MAC1, uip_len, TIME_IMMEDIATE)) != NULL) { - uint8_t *bp = macGetTransmitBuffer(tdp); - + if (macWaitTransmitDescriptor(Ð1, &td, TIME_IMMEDIATE) == RDY_OK) { if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) - memcpy(bp, &uip_buf[0], uip_len); + macWriteTransmitDescriptor(&td, uip_buf, uip_len); else { - memcpy(bp, &uip_buf[0], UIP_LLH_LEN + UIP_TCPIP_HLEN); - memcpy(bp + UIP_LLH_LEN + UIP_TCPIP_HLEN, - uip_appdata, - uip_len - (UIP_LLH_LEN + UIP_TCPIP_HLEN)); + macWriteTransmitDescriptor(&td, uip_buf, UIP_LLH_LEN + UIP_TCPIP_HLEN); + macWriteTransmitDescriptor(&td, uip_appdata, + uip_len - (UIP_LLH_LEN + UIP_TCPIP_HLEN)); } - macReleaseTransmitDescriptor(&MAC1, tdp); + macReleaseTransmitDescriptor(&td); return; } chThdSleep(SEND_RETRY_INTERVAL); @@ -73,15 +70,14 @@ static void network_device_send(void) { * uIP receive function wrapping the EMAC function. */ static size_t network_device_read(void) { - MACReceiveDescriptor *rdp; + MACReceiveDescriptor rd; size_t size; - uint8_t *bp; - if ((rdp = macWaitReceiveDescriptor(&MAC1, &size, TIME_IMMEDIATE)) == NULL) + if (macWaitReceiveDescriptor(Ð1, &rd, TIME_IMMEDIATE) != RDY_OK) return 0; - bp = macGetReceiveBuffer(rdp); - memcpy(&uip_buf[0], bp, size); - macReleaseReceiveDescriptor(&MAC1, rdp); + size = rd.rd_size; + macReadReceiveDescriptor(&rd, uip_buf, size); + macReleaseReceiveDescriptor(&rd); return size; } @@ -113,7 +109,7 @@ static void PeriodicTimerHandler(eventid_t id) { static void ARPTimerHandler(eventid_t id) { uip_arp_timer(); - (void)macPollLinkStatus(&MAC1); + (void)macPollLinkStatus(Ð1); } /* @@ -156,7 +152,7 @@ msg_t WebThread(void *p) { /* * Event sources setup. */ - chEvtRegister(macGetReceiveEventSource(&MAC1), &el0, FRAME_RECEIVED_ID); + chEvtRegister(macGetReceiveEventSource(Ð1), &el0, FRAME_RECEIVED_ID); chEvtPend(EVENT_MASK(FRAME_RECEIVED_ID)); /* In case some frames are already buffered */ evtInit(&evt1, MS2ST(500)); @@ -170,8 +166,8 @@ msg_t WebThread(void *p) { /* * EMAC settings. */ - macSetAddress(&MAC1, &macaddr.addr[0]); - (void)macPollLinkStatus(&MAC1); + macSetAddress(Ð1, &macaddr.addr[0]); + (void)macPollLinkStatus(Ð1); /* * uIP initialization. diff --git a/os/io/mac.c b/os/io/mac.c index c9ee88317..6754bf78f 100644 --- a/os/io/mac.c +++ b/os/io/mac.c @@ -77,33 +77,32 @@ void macSetAddress(MACDriver *macp, const uint8_t *p) { * invoking thread is queued until one is freed. * * @param[in] macp pointer to the @p MACDriver object - * @param[in] size size of the frame to be transmitted + * @param[out] tdp pointer to a @p MACTransmitDescriptor structure * @param[in] time the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_IMMEDIATE immediate timeout. * - @a TIME_INFINITE no timeout. * . - * @return A pointer to a @p MACTransmitDescriptor structure or @p NULL if - * the operation timed out. + * @return The operation status. + * @retval RDY_OK the descriptor was obtained. + * @retval RDY_TIMEOUT the operation timed out, descriptor not initialized. */ -MACTransmitDescriptor *macWaitTransmitDescriptor(MACDriver *macp, - size_t size, - systime_t time) { - MACTransmitDescriptor *tdp; +msg_t macWaitTransmitDescriptor(MACDriver *macp, + MACTransmitDescriptor *tdp, + systime_t time) { + msg_t msg; - while (((tdp = max_lld_get_transmit_descriptor(macp, size)) == NULL) && + while (((msg = max_lld_get_transmit_descriptor(macp, tdp)) != RDY_OK) && (time > 0)) { chSysLock(); systime_t now = chTimeNow(); - if (chSemWaitTimeoutS(&tdsem, time) == RDY_TIMEOUT) { - tdp = NULL; + if ((msg = chSemWaitTimeoutS(&tdsem, time)) == RDY_TIMEOUT) break; - } if (time != TIME_INFINITE) time -= (chTimeNow() - now); chSysUnlock(); } - return tdp; + return msg; } /** @@ -113,10 +112,9 @@ MACTransmitDescriptor *macWaitTransmitDescriptor(MACDriver *macp, * @param[in] macp pointer to the @p MACDriver object * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure */ -void macReleaseTransmitDescriptor(MACDriver *macp, - MACTransmitDescriptor *tdp) { +void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp) { - mac_lld_release_transmit_descriptor(macp, tdp); + mac_lld_release_transmit_descriptor(tdp); } /** @@ -126,47 +124,45 @@ void macReleaseTransmitDescriptor(MACDriver *macp, * until one is received. * * @param[in] macp pointer to the @p MACDriver object - * @param[out szp size of the received frame + * @param[out] rdp pointer to a @p MACReceiveDescriptor structure * @param[in] time the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_IMMEDIATE immediate timeout. * - @a TIME_INFINITE no timeout. * . - * @return A pointer to a @p MACReceiveDescriptor structure or @p NULL if - * the operation timed out or some transient error happened. + * @return The operation status. + * @retval RDY_OK the descriptor was obtained. + * @retval RDY_TIMEOUT the operation timed out, descriptor not initialized. */ -MACReceiveDescriptor *macWaitReceiveDescriptor(MACDriver *macp, - size_t *szp, - systime_t time) { - MACReceiveDescriptor *rdp; +msg_t macWaitReceiveDescriptor(MACDriver *macp, + MACReceiveDescriptor *rdp, + systime_t time) { + msg_t msg; - while (((rdp = max_lld_get_receive_descriptor(macp, szp)) == NULL) && + while (((msg = max_lld_get_receive_descriptor(macp, rdp)) != RDY_OK) && (time > 0)) { chSysLock(); systime_t now = chTimeNow(); - if (chSemWaitTimeoutS(&rdsem, time) == RDY_TIMEOUT) { - rdp = NULL; + if ((msg = chSemWaitTimeoutS(&rdsem, time)) == RDY_TIMEOUT) break; - } if (time != TIME_INFINITE) time -= (chTimeNow() - now); chSysUnlock(); } - return rdp; + return msg; } /** * @brief Releases a receive descriptor. - * @details The descriptor and its buffer is made available for more incoming + * @details The descriptor and its buffer are made available for more incoming * frames. * * @param[in] macp pointer to the @p MACDriver object * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure */ -void macReleaseReceiveDescriptor(MACDriver *macp, - MACReceiveDescriptor *rdp) { +void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) { - mac_lld_release_receive_descriptor(macp, rdp); + mac_lld_release_receive_descriptor(rdp); } /** diff --git a/os/io/mac.h b/os/io/mac.h index 9bbfa5cef..9a83cc2b8 100644 --- a/os/io/mac.h +++ b/os/io/mac.h @@ -30,23 +30,7 @@ #include "mac_lld.h" /** - * @brief Returns the buffer associated to a @p MACTransmitDescriptor. - * - * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * @return The pointer to the transmit buffer. - */ -#define macGetTransmitBuffer(tdp) mac_lld_get_transmit_buffer(tdp) - -/** - * @brief Returns the buffer associated to a @p MACReceiveDescriptor. - * - * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure - * @return The pointer to the receive buffer. - */ -#define macGetReceiveBuffer(rdp) mac_lld_get_receive_buffer(rdp) - -/** - * @bief Returns the received frames event source. + * @brief Returns the received frames event source. * * @param[in] macp pointer to the @p MACDriver object * @return The pointer to the @p EventSource structure. @@ -55,24 +39,46 @@ #define macGetReceiveEventSource(macp) (&(macp)->md_rdevent) #endif +/** + * @brief Writes to a transmit descriptor's stream. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] buf pointer to the buffer containing the data to be written + * @param[in] size number of bytes to be written + * @return The number of bytes written into the descriptor's stream, this + * value can be less than the amount specified in the parameter + * @p size if the maximum frame size is reached. + */ +#define macWriteTransmitDescriptor(tdp, buf, size) \ + mac_lld_write_transmit_descriptor(tdp, buf, size) + +/** + * @brief Reads from a receive descriptor's stream. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] buf pointer to the buffer that will receive the read data + * @param[in] size number of bytes to be read + * @return The number of bytes read from the descriptor's stream, this + * value can be less than the amount specified in the parameter + * @p size if there are no more bytes to read. + */ +#define macReadReceiveDescriptor(rdp, buf, size) \ + mac_lld_read_receive_descriptor(rdp, buf, size) + #ifdef __cplusplus extern "C" { #endif void macInit(void); void macObjectInit(MACDriver *macp); void macSetAddress(MACDriver *macp, const uint8_t *p); - void macStart(MACDriver *macp); - void macStop(MACDriver *macp); - MACTransmitDescriptor *macWaitTransmitDescriptor(MACDriver *macp, - size_t size, - systime_t time); - void macReleaseTransmitDescriptor(MACDriver *macp, - MACTransmitDescriptor *tdp); - MACReceiveDescriptor *macWaitReceiveDescriptor(MACDriver *macp, - size_t *szp, - systime_t time); - void macReleaseReceiveDescriptor(MACDriver *macp, - MACReceiveDescriptor *rdp); + msg_t macWaitTransmitDescriptor(MACDriver *macp, + MACTransmitDescriptor *tdp, + systime_t time); + void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp); + msg_t macWaitReceiveDescriptor(MACDriver *macp, + MACReceiveDescriptor *rdp, + systime_t time); + void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp); bool_t macPollLinkStatus(MACDriver *macp); #ifdef __cplusplus } diff --git a/os/io/platforms/AT91SAM7X/mac_lld.c b/os/io/platforms/AT91SAM7X/mac_lld.c index 69d45dfbc..7ebee112d 100644 --- a/os/io/platforms/AT91SAM7X/mac_lld.c +++ b/os/io/platforms/AT91SAM7X/mac_lld.c @@ -24,6 +24,8 @@ * @{ */ +#include + #include #include #include @@ -32,9 +34,9 @@ #include "at91lib/aic.h" /** - * @brief EMAC object. + * @brief Ethernet driver 1. */ -MACDriver MAC1; +MACDriver ETH1; #define EMAC_PIN_MASK (AT91C_PB0_ETXCK_EREFCK | AT91C_PB1_ETXEN | \ AT91C_PB2_ETX0 | AT91C_PB3_ETX1 | \ @@ -56,13 +58,16 @@ static bool_t link_up; static uint8_t default_mac[] = {0xAA, 0x55, 0x13, 0x37, 0x01, 0x10}; -static MACReceiveDescriptor rd[EMAC_RECEIVE_BUFFERS] __attribute__((aligned(8))); -static uint8_t rb[EMAC_RECEIVE_BUFFERS * EMAC_RECEIVE_BUFFERS_SIZE] __attribute__((aligned(8))); -static MACReceiveDescriptor *rxptr; - -static MACTransmitDescriptor td[EMAC_TRANSMIT_BUFFERS] __attribute__((aligned(8))); -static uint8_t tb[EMAC_TRANSMIT_BUFFERS * EMAC_TRANSMIT_BUFFERS_SIZE] __attribute__((aligned(8))); -static MACTransmitDescriptor *txptr; +static EMACDescriptor *rxptr; +static EMACDescriptor *txptr; +static EMACDescriptor rd[EMAC_RECEIVE_DESCRIPTORS] + __attribute__((aligned(8))); +static EMACDescriptor td[EMAC_TRANSMIT_DESCRIPTORS] + __attribute__((aligned(8))); +static uint8_t rb[EMAC_RECEIVE_DESCRIPTORS * EMAC_RECEIVE_BUFFERS_SIZE] + __attribute__((aligned(8))); +static uint8_t tb[EMAC_TRANSMIT_DESCRIPTORS * EMAC_TRANSMIT_BUFFERS_SIZE] + __attribute__((aligned(8))); #endif /** @@ -82,9 +87,9 @@ static void serve_interrupt(void) { if ((isr & AT91C_EMAC_RCOMP) || (rsr & RSR_BITS)) { if (rsr & AT91C_EMAC_REC) { chSysLockFromIsr(); - chSemResetI(&MAC1.md_rdsem, 0); + chSemResetI(Ð1.md_rdsem, 0); #if CH_USE_EVENTS - chEvtBroadcastI(&MAC1.md_rdevent); + chEvtBroadcastI(Ð1.md_rdevent); #endif chSysUnlockFromIsr(); } @@ -94,7 +99,7 @@ static void serve_interrupt(void) { if ((isr & AT91C_EMAC_TCOMP) || (tsr & TSR_BITS)) { if (tsr & AT91C_EMAC_COMP) { chSysLockFromIsr(); - chSemResetI(&MAC1.md_tdsem, 0); + chSemResetI(Ð1.md_tdsem, 0); chSysUnlockFromIsr(); } AT91C_BASE_EMAC->EMAC_TSR = TSR_BITS; @@ -121,28 +126,28 @@ void mac_lld_init(void) { unsigned i; phyInit(); - macObjectInit(&MAC1); + macObjectInit(Ð1); /* * Buffers initialization. */ - for (i = 0; i < EMAC_RECEIVE_BUFFERS; i++) { + for (i = 0; i < EMAC_RECEIVE_DESCRIPTORS; i++) { rd[i].w1 = (uint32_t)&rb[i * EMAC_RECEIVE_BUFFERS_SIZE]; rd[i].w2 = 0; } - rd[EMAC_RECEIVE_BUFFERS - 1].w1 |= W1_R_WRAP; + rd[EMAC_RECEIVE_DESCRIPTORS - 1].w1 |= W1_R_WRAP; rxptr = rd; - for (i = 0; i < EMAC_TRANSMIT_BUFFERS; i++) { + for (i = 0; i < EMAC_TRANSMIT_DESCRIPTORS; i++) { td[i].w1 = (uint32_t)&tb[i * EMAC_TRANSMIT_BUFFERS_SIZE]; td[i].w2 = EMAC_TRANSMIT_BUFFERS_SIZE | W2_T_LAST_BUFFER | W2_T_USED; } - td[EMAC_TRANSMIT_BUFFERS - 1].w2 |= W2_T_WRAP; + td[EMAC_TRANSMIT_DESCRIPTORS - 1].w2 |= W2_T_WRAP; txptr = td; /* * Associated PHY initialization. */ - phyReset(&MAC1); + phyReset(Ð1); /* * EMAC pins setup and clock enable. Note, PB18 is not included because it is @@ -168,15 +173,15 @@ void mac_lld_init(void) { AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TE | AT91C_EMAC_RE | AT91C_EMAC_CLRSTAT;/* Initial NCR settings.*/ - mac_lld_set_address(&MAC1, default_mac); + mac_lld_set_address(Ð1, default_mac); #if PHY_HARDWARE == PHY_MICREL_KS8721 /* * PHY device identification. */ AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE; - if ((phyGet(&MAC1, MII_PHYSID1) != (MII_KS8721_ID >> 16)) || - ((phyGet(&MAC1, MII_PHYSID2) & 0xFFF0) != (MII_KS8721_ID & 0xFFF0))) + if ((phyGet(Ð1, MII_PHYSID1) != (MII_KS8721_ID >> 16)) || + ((phyGet(Ð1, MII_PHYSID2) & 0xFFF0) != (MII_KS8721_ID & 0xFFF0))) chSysHalt(); AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE; #endif @@ -213,91 +218,104 @@ void mac_lld_set_address(MACDriver *macp, const uint8_t *p) { * returned. * * @param[in] macp pointer to the @p MACDriver object - * @param[in] size size of the frame to be transmitted - * @return A pointer to a @p MACTransmitDescriptor structure or @p NULL if - * a descriptor is not available. + * @param[out] tdp pointer to a @p MACTransmitDescriptor structure + * @return The operation status. + * @retval RDY_OK the descriptor was obtained. + * @retval RDY_TIMEOUT descriptor not available. */ -MACTransmitDescriptor *max_lld_get_transmit_descriptor(MACDriver *macp, - size_t size) { - MACTransmitDescriptor *tdp; - - chDbgAssert(size <= EMAC_TRANSMIT_BUFFERS_SIZE, - "max_lld_get_transmit_descriptor(), #1", - "unexpected size"); +msg_t max_lld_get_transmit_descriptor(MACDriver *macp, + MACTransmitDescriptor *tdp) { + EMACDescriptor *edp; if (!link_up) - return NULL; + return RDY_TIMEOUT; chSysLock(); - tdp = txptr; - chDbgAssert((tdp->w2 & W2_T_USED) && !(tdp->w2 & W2_T_LOCKED), - "max_lld_get_transmit_descriptor(), #2", "buffer not available"); - if (!(tdp->w2 & W2_T_USED) || (tdp->w2 & W2_T_LOCKED)) { + edp = txptr; + if (!(edp->w2 & W2_T_USED) || (edp->w2 & W2_T_LOCKED)) { chSysUnlock(); - return NULL; + return RDY_TIMEOUT; } /* * Set the buffer size and configuration, the buffer is also marked * as locked. */ - tdp->w2 = size | W2_T_LOCKED | W2_T_USED | W2_T_LAST_BUFFER; - if (++txptr >= &td[EMAC_TRANSMIT_BUFFERS]) { - tdp->w2 |= W2_T_WRAP; + if (++txptr >= &td[EMAC_TRANSMIT_DESCRIPTORS]) { + edp->w2 = W2_T_LOCKED | W2_T_USED | W2_T_LAST_BUFFER | W2_T_WRAP; txptr = td; } + else + edp->w2 = W2_T_LOCKED | W2_T_USED | W2_T_LAST_BUFFER; chSysUnlock(); - return tdp; + tdp->td_offset = 0; + tdp->td_size = EMAC_TRANSMIT_BUFFERS_SIZE; + tdp->td_physdesc = edp; + return RDY_OK; +} + +/** + * @brief Writes to a transmit descriptor's stream. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] buf pointer to the buffer cointaining the data to be written + * @param[in] size number of bytes to be written + * @return The number of bytes written into the descriptor's stream, this + * value can be less than the amount specified in the parameter + * @p size if the maximum frame size is reached. + */ +size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size) { + + if (size > tdp->td_size - tdp->td_offset) + size = tdp->td_size - tdp->td_offset; + if (size > 0) { + memcpy((uint8_t *)(tdp->td_physdesc->w1 & W1_T_ADDRESS_MASK) + + tdp->td_offset, + buf, size); + tdp->td_offset += size; + } + return size; } /** * @brief Releases a transmit descriptor and starts the transmission of the * enqueued data as a single frame. * - * @param[in] macp pointer to the @p MACDriver object * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * @param[in] */ -void mac_lld_release_transmit_descriptor(MACDriver *macp, - MACTransmitDescriptor *tdp) { +void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { chSysLock(); - tdp->w2 &= ~(W2_T_LOCKED | W2_T_USED); + tdp->td_physdesc->w2 = (tdp->td_physdesc->w2 & + ~(W2_T_LOCKED | W2_T_USED | W2_T_LENGTH_MASK)) | + tdp->td_offset; AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART; chSysUnlock(); } /** - * @brief Returns the buffer associated to a @p MACTransmitDescriptor. - * - * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * @return The pointer to the transmit buffer. - */ -uint8_t *mac_lld_get_transmit_buffer(MACTransmitDescriptor *tdp) { - - return (uint8_t *)(tdp->w1 & W1_T_ADDRESS_MASK); -} - -/** - * @brief Returns a received frame. + * @brief Returns a receive descriptor. * * @param[in] macp pointer to the @p MACDriver object - * @param[out szp size of the received frame - * @return A pointer to a @p MACReceiveDescriptor structure or @p NULL if - * the operation timed out or some transient error happened. + * @param[out] rdp pointer to a @p MACReceiveDescriptor structure + * @return The operation status. + * @retval RDY_OK the descriptor was obtained. + * @retval RDY_TIMEOUT descriptor not available. */ -MACReceiveDescriptor *max_lld_get_receive_descriptor(MACDriver *macp, - size_t *szp) { +msg_t max_lld_get_receive_descriptor(MACDriver *macp, + MACReceiveDescriptor *rdp) { unsigned n; - MACReceiveDescriptor *rdp; + EMACDescriptor *edp; - n = EMAC_RECEIVE_BUFFERS; + n = EMAC_RECEIVE_DESCRIPTORS; /* * Skips unused buffers, if any. */ skip: while ((n > 0) && !(rxptr->w1 & W1_R_OWNERSHIP)) { - if (++rxptr >= &rd[EMAC_RECEIVE_BUFFERS]) + if (++rxptr >= &rd[EMAC_RECEIVE_DESCRIPTORS]) rxptr = rd; n--; } @@ -308,7 +326,7 @@ skip: while ((n > 0) && (rxptr->w1 & W1_R_OWNERSHIP) && !(rxptr->w2 & W2_R_FRAME_START)) { rxptr->w1 &= ~W1_R_OWNERSHIP; - if (++rxptr >= &rd[EMAC_RECEIVE_BUFFERS]) + if (++rxptr >= &rd[EMAC_RECEIVE_DESCRIPTORS]) rxptr = rd; n--; } @@ -318,7 +336,7 @@ skip: * or holes... */ restart: - rdp = rxptr; + edp = rxptr; while (n > 0) { if (!(rxptr->w1 & W1_R_OWNERSHIP)) goto skip; /* Empty buffer for some reason... */ @@ -327,58 +345,88 @@ restart: * End Of Frame found. */ if (rxptr->w2 & W2_R_FRAME_END) { - *szp = rxptr->w2 & W2_T_LENGTH_MASK; - return rdp; + rdp->rd_offset = 0; + rdp->rd_size = rxptr->w2 & W2_T_LENGTH_MASK; + rdp->rd_physdesc = edp; + return RDY_OK; } - if ((rdp != rxptr) && (rxptr->w2 & W2_R_FRAME_START)) { + if ((edp != rxptr) && (rxptr->w2 & W2_R_FRAME_START)) { /* Found another start... cleaning up the incomplete frame.*/ do { - rdp->w1 &= ~W1_R_OWNERSHIP; - if (++rdp >= &rd[EMAC_RECEIVE_BUFFERS]) - rdp = rd; + edp->w1 &= ~W1_R_OWNERSHIP; + if (++edp >= &rd[EMAC_RECEIVE_DESCRIPTORS]) + edp = rd; } - while (rdp != rxptr); + while (edp != rxptr); goto restart; /* Another start buffer for some reason... */ } - if (++rxptr >= &rd[EMAC_RECEIVE_BUFFERS]) + if (++rxptr >= &rd[EMAC_RECEIVE_DESCRIPTORS]) rxptr = rd; n--; } - return NULL; + return RDY_TIMEOUT; +} + +/** + * @brief Reads from a receive descriptor's stream. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] buf pointer to the buffer that will receive the read data + * @param[in] size number of bytes to be read + * @return The number of bytes read from the descriptor's stream, this + * value can be less than the amount specified in the parameter + * @p size if there are no more bytes to read. + */ +size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size) { + if (size > rdp->rd_size - rdp->rd_offset) + size = rdp->rd_size - rdp->rd_offset; + if (size > 0) { + uint8_t *src = (uint8_t *)(rdp->rd_physdesc->w1 & W1_R_ADDRESS_MASK) + + rdp->rd_offset; + uint8_t *limit = &rb[EMAC_RECEIVE_DESCRIPTORS * EMAC_RECEIVE_BUFFERS_SIZE]; + if (src + size > limit ) { + memcpy(buf, src, (size_t)(limit - src)); + memcpy(buf, rb, (size_t)(src + size - limit)); + } + else + memcpy(buf, src, size); + rdp->rd_offset += size; + } + return size; } /** * @brief Releases a receive descriptor. - * @details The descriptor and its buffer is made available for more incoming + * @details The descriptor and its buffer are made available for more incoming * frames. * - * @param[in] macp pointer to the @p MACDriver object * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure */ -void mac_lld_release_receive_descriptor(MACDriver *macp, - MACReceiveDescriptor *rdp) { +void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) { + bool_t done; + EMACDescriptor *edp = rdp->rd_physdesc; - unsigned n = EMAC_RECEIVE_BUFFERS; + unsigned n = EMAC_RECEIVE_DESCRIPTORS; do { - rdp->w1 &= ~W1_R_OWNERSHIP; - if (++rdp >= &rd[EMAC_RECEIVE_BUFFERS]) - rdp = rd; + done = ((edp->w2 & W2_R_FRAME_END) != 0); + chDbgAssert(edp->w1 & W1_R_OWNERSHIP, + "mac_lld_release_receive_descriptor(), #1", + "found not owned descriptor"); + edp->w1 &= ~(W1_R_OWNERSHIP | W2_R_FRAME_START | W2_R_FRAME_END); + if (++edp >= &rd[EMAC_RECEIVE_DESCRIPTORS]) + edp = rd; n--; } - while ((n > 0) || !(rxptr->w2 & W2_R_FRAME_END)); -} - -/** - * @brief Returns the buffer associated to a @p MACTransmitDescriptor. - * - * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * @return The pointer to the transmit buffer. - */ -uint8_t *mac_lld_get_receive_buffer(MACReceiveDescriptor *rdp) { - - return (uint8_t *)(rdp->w1 & W1_R_ADDRESS_MASK); + while ((n > 0) && !done); + /* + * Make rxptr point to the descriptor where the next frame will most + * likely appear. + */ + rxptr = edp; } /** diff --git a/os/io/platforms/AT91SAM7X/mac_lld.h b/os/io/platforms/AT91SAM7X/mac_lld.h index f414eb61f..696150572 100644 --- a/os/io/platforms/AT91SAM7X/mac_lld.h +++ b/os/io/platforms/AT91SAM7X/mac_lld.h @@ -32,14 +32,28 @@ /*===========================================================================*/ /** - * @brief Number of available descriptors/buffers. + * @brief Number of available transmit buffers. */ -#if !defined(MAC_TRANSMIT_DESCRIPTORS) || defined(__DOXYGEN__) -#define MAC_TRANSMIT_DESCRIPTORS 2 +#if !defined(MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__) +#define MAC_TRANSMIT_BUFFERS 2 +#endif + +/** + * @brief Number of available receive buffers. + */ +#if !defined(MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__) +#define MAC_RECEIVE_BUFFERS 2 +#endif + +/** + * @brief Maximum supported frame size. + */ +#if !defined(MAC_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define MAC_BUFFERS_SIZE 1518 #endif /*===========================================================================*/ -/* EMAC specific constants and settings. */ +/* EMAC specific settings. */ /*===========================================================================*/ /** @@ -49,10 +63,16 @@ #define EMAC_INTERRUPT_PRIORITY (AT91C_AIC_PRIOR_HIGHEST - 3) #endif -#define EMAC_RECEIVE_BUFFERS 24 +/*===========================================================================*/ +/* EMAC specific constants. */ +/*===========================================================================*/ + #define EMAC_RECEIVE_BUFFERS_SIZE 128 /* Do not modify */ -#define EMAC_TRANSMIT_BUFFERS MAC_TRANSMIT_DESCRIPTORS -#define EMAC_TRANSMIT_BUFFERS_SIZE 1518 +#define EMAC_TRANSMIT_BUFFERS_SIZE MAC_BUFFERS_SIZE +#define EMAC_RECEIVE_DESCRIPTORS \ + (((((MAC_BUFFERS_SIZE - 1) | (EMAC_RECEIVE_BUFFERS_SIZE - 1)) + 1) \ + / EMAC_RECEIVE_BUFFERS_SIZE) * MAC_RECEIVE_BUFFERS) +#define EMAC_TRANSMIT_DESCRIPTORS MAC_TRANSMIT_BUFFERS #define W1_R_OWNERSHIP 0x00000001 #define W1_R_WRAP 0x00000002 @@ -94,33 +114,47 @@ /* Driver data structures and types. */ /*===========================================================================*/ +/** + * @brief Structure representing a buffer physical descriptor. + * @note It represents both descriptor types. + */ +typedef struct { + uint32_t w1; + uint32_t w2; +} EMACDescriptor; + /** * @brief Structure representing a MAC driver. */ typedef struct { - Semaphore md_tdsem; /**< Transmit semaphore.*/ - Semaphore md_rdsem; /**< Receive semaphore.*/ + Semaphore md_tdsem; /**< Transmit semaphore. */ + Semaphore md_rdsem; /**< Receive semaphore. */ #if CH_USE_EVENTS - EventSource md_rdevent; /**< Receive event source.*/ + EventSource md_rdevent; /**< Receive event source. */ #endif + /* End of the mandatory fields.*/ } MACDriver; /** - * @brief Structure representing a transmission descriptor. + * @brief Structure representing a transmit descriptor. */ typedef struct { - - uint32_t w1; - uint32_t w2; + size_t td_offset; /**< Current write offset. */ + size_t td_size; /**< Available space size. */ + /* End of the mandatory fields.*/ + EMACDescriptor *td_physdesc; /**< Pointer to the physical + descriptor. */ } MACTransmitDescriptor; /** * @brief Structure representing a receive descriptor. */ typedef struct { - - uint32_t w1; - uint32_t w2; + size_t rd_offset; /**< Current read offset. */ + size_t rd_size; /**< Available data size. */ + /* End of the mandatory fields.*/ + EMACDescriptor *rd_physdesc; /**< Pointer to the first descriptor + of the buffers chain. */ } MACReceiveDescriptor; /*===========================================================================*/ @@ -128,23 +162,25 @@ typedef struct { /*===========================================================================*/ /** @cond never*/ -extern MACDriver MAC1; +extern MACDriver ETH1; #ifdef __cplusplus extern "C" { #endif void mac_lld_init(void); void mac_lld_set_address(MACDriver *macp, const uint8_t *p); - MACTransmitDescriptor *max_lld_get_transmit_descriptor(MACDriver *macp, - size_t size); - void mac_lld_release_transmit_descriptor(MACDriver *macp, - MACTransmitDescriptor *tdp); - uint8_t *mac_lld_get_transmit_buffer(MACTransmitDescriptor *tdp); - MACReceiveDescriptor *max_lld_get_receive_descriptor(MACDriver *macp, - size_t *szp); - void mac_lld_release_receive_descriptor(MACDriver *macp, - MACReceiveDescriptor *rdp); - uint8_t *mac_lld_get_receive_buffer(MACReceiveDescriptor *rdp); + msg_t max_lld_get_transmit_descriptor(MACDriver *macp, + MACTransmitDescriptor *tdp); + size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size); + void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp); + msg_t max_lld_get_receive_descriptor(MACDriver *macp, + MACReceiveDescriptor *rdp); + size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size); + void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp); bool_t mac_lld_poll_link_status(MACDriver *macp); #ifdef __cplusplus } diff --git a/os/io/templates/mac_lld.c b/os/io/templates/mac_lld.c index a780a32ff..08ffa8d79 100644 --- a/os/io/templates/mac_lld.c +++ b/os/io/templates/mac_lld.c @@ -52,77 +52,87 @@ void mac_lld_set_address(MACDriver *macp, const uint8_t *p) { * returned. * * @param[in] macp pointer to the @p MACDriver object - * @param[in] size size of the frame to be transmitted - * @return A pointer to a @p MACTransmitDescriptor structure or @p NULL if - * a descriptor is not available. + * @param[out] tdp pointer to a @p MACTransmitDescriptor structure + * @return The operation status. + * @retval RDY_OK the descriptor was obtained. + * @retval RDY_TIMEOUT descriptor not available. */ -MACTransmitDescriptor *max_lld_get_transmit_descriptor(MACDriver *macp, - size_t size) { +msg_t max_lld_get_transmit_descriptor(MACDriver *macp, + MACTransmitDescriptor *tdp) { - return NULL; + return RDY_OK; +} + +/** + * @brief Writes to a transmit descriptor's stream. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] buf pointer to the buffer cointaining the data to be written + * @param[in] size number of bytes to be written + * @return The number of bytes written into the descriptor's stream, this + * value can be less than the amount specified in the parameter + * @p size if the maximum frame size is reached. + */ +size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size) { + + return 0; } /** * @brief Releases a transmit descriptor and starts the transmission of the * enqueued data as a single frame. * - * @param[in] macp pointer to the @p MACDriver object * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure */ -void mac_lld_release_transmit_descriptor(MACDriver *macp, - MACTransmitDescriptor *tdp) { +void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { } /** - * @brief Returns the buffer associated to a @p MACTransmitDescriptor. + * @brief Returns a receive descriptor. * - * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * @return The pointer to the transmit buffer. + * @param[in] macp pointer to the @p MACDriver object + * @param[out] rdp pointer to a @p MACReceiveDescriptor structure + * @return The operation status. + * @retval RDY_OK the descriptor was obtained. + * @retval RDY_TIMEOUT descriptor not available. */ -uint8_t *mac_lld_get_transmit_buffer(MACTransmitDescriptor *tdp) { +msg_t max_lld_get_receive_descriptor(MACDriver *macp, + MACReceiveDescriptor *rdp) { - return NULL; + return RDY_OK; } /** - * @brief Returns a received frame. + * @brief Reads from a receive descriptor's stream. * - * @param[in] macp pointer to the @p MACDriver object - * @param[out szp size of the received frame - * @return A pointer to a @p MACReceiveDescriptor structure or @p NULL if - * the operation timed out or some transient error happened. + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] buf pointer to the buffer that will receive the read data + * @param[in] size number of bytes to be read + * @return The number of bytes read from the descriptor's stream, this + * value can be less than the amount specified in the parameter + * @p size if there are no more bytes to read. */ -MACReceiveDescriptor *max_lld_get_receive_descriptor(MACDriver *macp, - size_t *szp) { +size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size) { - return NULL; + return 0; } /** * @brief Releases a receive descriptor. - * @details The descriptor and its buffer is made available for more incoming + * @details The descriptor and its buffer are made available for more incoming * frames. * - * @param[in] macp pointer to the @p MACDriver object * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure */ -void mac_lld_release_receive_descriptor(MACDriver *macp, - MACReceiveDescriptor *rdp) { +void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) { } -/** - * @brief Returns the buffer associated to a @p MACTransmitDescriptor. - * - * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * @return The pointer to the transmit buffer. - */ -uint8_t *mac_lld_get_receive_buffer(MACReceiveDescriptor *rdp) { - - return NULL; -} - /** * @brief Updates and returns the link status. * diff --git a/os/io/templates/mac_lld.h b/os/io/templates/mac_lld.h index 377a18ea1..2b6e19c26 100644 --- a/os/io/templates/mac_lld.h +++ b/os/io/templates/mac_lld.h @@ -32,10 +32,24 @@ /*===========================================================================*/ /** - * @brief Number of available descriptors/buffers. + * @brief Number of available transmit buffers. */ -#if !defined(MAC_TRANSMIT_DESCRIPTORS) || defined(__DOXYGEN__) -#define MAC_TRANSMIT_DESCRIPTORS 2 +#if !defined(MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__) +#define MAC_TRANSMIT_BUFFERS 2 +#endif + +/** + * @brief Number of available receive buffers. + */ +#if !defined(MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__) +#define MAC_RECEIVE_BUFFERS 2 +#endif + +/** + * @brief Maximum supported frame size. + */ +#if !defined(MAC_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define MAC_BUFFERS_SIZE 1518 #endif /*===========================================================================*/ @@ -46,25 +60,30 @@ * @brief Structure representing a MAC driver. */ typedef struct { - Semaphore md_tdsem; /**< Transmit semaphore.*/ - Semaphore md_rdsem; /**< Receive semaphore.*/ + Semaphore md_tdsem; /**< Transmit semaphore. */ + Semaphore md_rdsem; /**< Receive semaphore. */ #if CH_USE_EVENTS - EventSource md_rdevent; /**< Receive event source.*/ + EventSource md_rdevent; /**< Receive event source. */ #endif + /* End of the mandatory fields.*/ } MACDriver; /** - * @brief Structure representing a transmission descriptor. + * @brief Structure representing a transmit descriptor. */ typedef struct { - + size_t td_offset; /**< Current write offset. */ + size_t td_size; /**< Available space size. */ + /* End of the mandatory fields.*/ } MACTransmitDescriptor; /** * @brief Structure representing a receive descriptor. */ typedef struct { - + size_t rd_offset; /**< Current read offset. */ + size_t rd_size; /**< Available data size. */ + /* End of the mandatory fields.*/ } MACReceiveDescriptor; /*===========================================================================*/ @@ -76,16 +95,18 @@ extern "C" { #endif void mac_lld_init(void); void mac_lld_set_address(MACDriver *macp, const uint8_t *p); - MACTransmitDescriptor *max_lld_get_transmit_descriptor(MACDriver *macp, - size_t size); - void mac_lld_release_transmit_descriptor(MACDriver *macp, - MACTransmitDescriptor *tdp); - uint8_t *mac_lld_get_transmit_buffer(MACTransmitDescriptor *tdp); - MACReceiveDescriptor *max_lld_get_receive_descriptor(MACDriver *macp, - size_t *szp); - void mac_lld_release_receive_descriptor(MACDriver *macp, - MACReceiveDescriptor *rdp); - uint8_t *mac_lld_get_receive_buffer(MACReceiveDescriptor *rdp); + msg_t max_lld_get_transmit_descriptor(MACDriver *macp, + MACTransmitDescriptor *tdp); + size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size); + void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp); + msg_t max_lld_get_receive_descriptor(MACDriver *macp, + MACReceiveDescriptor *rdp); + size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size); + void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp); bool_t mac_lld_poll_link_status(MACDriver *macp); #ifdef __cplusplus }