summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/lpc24xx/network/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/arm/lpc24xx/network/network.c')
-rw-r--r--c/src/lib/libbsp/arm/lpc24xx/network/network.c280
1 files changed, 158 insertions, 122 deletions
diff --git a/c/src/lib/libbsp/arm/lpc24xx/network/network.c b/c/src/lib/libbsp/arm/lpc24xx/network/network.c
index ede668a3ce..6dc5538eb6 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/network/network.c
+++ b/c/src/lib/libbsp/arm/lpc24xx/network/network.c
@@ -43,6 +43,7 @@
#include <bsp.h>
#include <bsp/lpc24xx.h>
#include <bsp/irq.h>
+#include <bsp/io.h>
#include <bsp/utility.h>
#include <rtems/status-checks.h>
@@ -141,22 +142,17 @@ static char lpc24xx_eth_transmit_buffer [LPC24XX_ETH_TRANSMIT_DATA_SIZE];
(LPC24XX_ETH_TRANSMIT_STATUS_START \
+ LPC24XX_ETH_TRANSMIT_UNIT_NUMBER * ETH_TRANSMIT_STATUS_SIZE)
-#define LPC24XX_ETH_EVENT_TRANSMIT RTEMS_EVENT_1
+#define LPC24XX_ETH_EVENT_INITIALIZE RTEMS_EVENT_1
-#define LPC24XX_ETH_EVENT_TRANSMIT_START RTEMS_EVENT_2
+#define LPC24XX_ETH_EVENT_START RTEMS_EVENT_2
-#define LPC24XX_ETH_EVENT_TRANSMIT_ERROR RTEMS_EVENT_3
-
-#define LPC24XX_ETH_EVENT_RECEIVE RTEMS_EVENT_4
-
-#define LPC24XX_ETH_EVENT_RECEIVE_ERROR RTEMS_EVENT_5
-
-#define LPC24XX_ETH_TIMEOUT 10
+#define LPC24XX_ETH_EVENT_INTERRUPT RTEMS_EVENT_3
#define LPC24XX_ETH_INTERRUPT_RECEIVE \
(ETH_INT_RX_ERROR | ETH_INT_RX_FINISHED | ETH_INT_RX_DONE)
-#define LPC24XX_ETH_INTERRUPT_TRANSMIT (ETH_INT_TX_DONE | ETH_INT_TX_FINISHED | ETH_INT_TX_ERROR)
+#define LPC24XX_ETH_INTERRUPT_TRANSMIT \
+ (ETH_INT_TX_DONE | ETH_INT_TX_FINISHED | ETH_INT_TX_ERROR)
#define LPC24XX_ETH_RX_STAT_ERRORS \
(ETH_RX_STAT_CRC_ERROR \
@@ -272,13 +268,10 @@ static void lpc24xx_eth_interrupt_handler(
/* Check receive interrupts */
if (IS_FLAG_SET( is, ETH_INT_RX_OVERRUN)) {
- re = LPC24XX_ETH_EVENT_RECEIVE_ERROR;
+ re = LPC24XX_ETH_EVENT_INITIALIZE;
++e->receive_fatal_errors;
- /* FIXME */
- printk( "%s: fatal receive error\n", __func__);
- while (1);
} else if (IS_ANY_FLAG_SET( is, LPC24XX_ETH_INTERRUPT_RECEIVE)) {
- re = LPC24XX_ETH_EVENT_RECEIVE;
+ re = LPC24XX_ETH_EVENT_INTERRUPT;
ie = SET_FLAGS( ie, LPC24XX_ETH_INTERRUPT_RECEIVE);
}
@@ -290,13 +283,10 @@ static void lpc24xx_eth_interrupt_handler(
/* Check transmit interrupts */
if (IS_FLAG_SET( is, ETH_INT_TX_UNDERRUN)) {
- te = LPC24XX_ETH_EVENT_TRANSMIT_ERROR;
+ te = LPC24XX_ETH_EVENT_INITIALIZE;
++e->transmit_fatal_errors;
- /* FIXME */
- printk( "%s: fatal transmit error\n", __func__);
- while (1);
} else if (IS_ANY_FLAG_SET( is, LPC24XX_ETH_INTERRUPT_TRANSMIT)) {
- te = LPC24XX_ETH_EVENT_TRANSMIT;
+ te = LPC24XX_ETH_EVENT_INTERRUPT;
ie = SET_FLAGS( ie, LPC24XX_ETH_INTERRUPT_TRANSMIT);
}
@@ -379,7 +369,7 @@ static bool lpc24xx_eth_add_new_mbuf(
struct ifnet *ifp,
volatile lpc24xx_eth_transfer_descriptor *desc,
struct mbuf **mbuf_table,
- unsigned i,
+ uint32_t i,
bool wait
)
{
@@ -416,67 +406,20 @@ static void lpc24xx_eth_receive_task( void *arg)
LPC24XX_ETH_RECEIVE_INFO_START;
struct mbuf **const mbuf_table =
(struct mbuf **) LPC24XX_ETH_RECEIVE_MBUF_START;
- uint32_t index_max = e->receive_unit_number - 1;
+ uint32_t index_max = 0;
uint32_t produce_index = 0;
uint32_t consume_index = 0;
uint32_t receive_index = 0;
LPC24XX_ETH_PRINTF( "%s\n", __func__);
- /* Disable receive interrupts */
- lpc24xx_eth_disable_receive_interrupts();
-
- /* Disable receiver */
- MAC_COMMAND = CLEAR_FLAG( MAC_COMMAND, ETH_CMD_RX_ENABLE);
-
- /* Clear receive interrupts */
- MAC_INTCLEAR = LPC24XX_ETH_INTERRUPT_RECEIVE;
-
- /* Fill receive queue */
- for (produce_index = 0; produce_index <= index_max; ++produce_index) {
- if (
- !lpc24xx_eth_add_new_mbuf( ifp, desc, mbuf_table, produce_index, false)
- ) {
- break;
- }
- }
-
- /* Check if the queue is full */
- if (produce_index == 0) {
- RTEMS_DO_CLEANUP(
- cleanup,
- "no buffers to fill receive queue: terminate receive task\n"
- );
- } else if (produce_index <= index_max) {
- /* Reduce the queue size */
- index_max = produce_index - 1;
-
- RTEMS_SYSLOG_ERROR( "not enough buffers to fill receive queue");
- }
-
- /* Receive descriptor table */
- MAC_RXDESCRIPTORNUM = index_max;
- MAC_RXDESCRIPTOR = (uint32_t) desc;
- MAC_RXSTATUS = (uint32_t) info;
-
- /* Initialize indices */
- produce_index = MAC_RXPRODUCEINDEX;
- consume_index = MAC_RXCONSUMEINDEX;
- receive_index = consume_index;
-
- /* Enable receiver */
- MAC_COMMAND = SET_FLAG( MAC_COMMAND, ETH_CMD_RX_ENABLE);
-
- /* Enable receive interrupts */
- lpc24xx_eth_enable_receive_interrupts();
-
/* Main event loop */
while (true) {
bool wait_for_mbuf = false;
/* Wait for events */
sc = rtems_bsdnet_event_receive(
- LPC24XX_ETH_EVENT_RECEIVE,
+ LPC24XX_ETH_EVENT_INITIALIZE | LPC24XX_ETH_EVENT_INTERRUPT,
RTEMS_EVENT_ANY | RTEMS_WAIT,
RTEMS_NO_TIMEOUT,
&events
@@ -485,6 +428,79 @@ static void lpc24xx_eth_receive_task( void *arg)
LPC24XX_ETH_PRINTF( "rx: wake up: 0x%08" PRIx32 "\n", events);
+ /* Initialize receiver? */
+ if (IS_FLAG_SET( events, LPC24XX_ETH_EVENT_INITIALIZE)) {
+ /* Disable receive interrupts */
+ lpc24xx_eth_disable_receive_interrupts();
+
+ /* Disable receiver */
+ MAC_COMMAND = CLEAR_FLAG( MAC_COMMAND, ETH_CMD_RX_ENABLE);
+
+ /* Wait for inactive status */
+ while (IS_FLAG_SET( MAC_STATUS, ETH_STAT_RX_ACTIVE)) {
+ /* Wait */
+ }
+
+ /* Reset */
+ MAC_COMMAND = SET_FLAG( MAC_COMMAND, ETH_CMD_RX_RESET);
+
+ /* Clear receive interrupts */
+ MAC_INTCLEAR = LPC24XX_ETH_INTERRUPT_RECEIVE;
+
+ /* Index maximum (determines queue size) */
+ index_max = e->receive_unit_number - 1;
+
+ /* Move existing mbufs to the front */
+ consume_index = 0;
+ for (produce_index = 0; produce_index <= index_max; ++produce_index) {
+ if (mbuf_table [produce_index] != NULL) {
+ mbuf_table [consume_index] = mbuf_table [produce_index];
+ ++consume_index;
+ }
+ }
+
+ /* Fill receive queue */
+ for (produce_index = consume_index; produce_index <= index_max; ++produce_index) {
+ if (
+ !lpc24xx_eth_add_new_mbuf( ifp, desc, mbuf_table, produce_index, false)
+ ) {
+ break;
+ }
+ }
+
+ /* Check if the queue is full */
+ if (produce_index == 0) {
+ RTEMS_DO_CLEANUP(
+ cleanup,
+ "no mbufs to fill receive queue: terminate receive task\n"
+ );
+ } else if (produce_index <= index_max) {
+ /* Reduce the queue size */
+ index_max = produce_index - 1;
+
+ RTEMS_SYSLOG_ERROR( "not enough mbufs to fill receive queue");
+ }
+
+ /* Receive descriptor table */
+ MAC_RXDESCRIPTORNUM = index_max;
+ MAC_RXDESCRIPTOR = (uint32_t) desc;
+ MAC_RXSTATUS = (uint32_t) info;
+
+ /* Initialize indices */
+ produce_index = MAC_RXPRODUCEINDEX;
+ consume_index = MAC_RXCONSUMEINDEX;
+ receive_index = consume_index;
+
+ /* Enable receiver */
+ MAC_COMMAND = SET_FLAG( MAC_COMMAND, ETH_CMD_RX_ENABLE);
+
+ /* Enable receive interrupts */
+ lpc24xx_eth_enable_receive_interrupts();
+
+ /* Wait for events */
+ continue;
+ }
+
while (true) {
/* Clear receive interrupt status */
MAC_INTCLEAR = LPC24XX_ETH_INTERRUPT_RECEIVE;
@@ -497,6 +513,9 @@ static void lpc24xx_eth_receive_task( void *arg)
struct mbuf *m = mbuf_table [receive_index];
uint32_t stat = info [receive_index].status;
+ /* Remove mbuf from table */
+ mbuf_table [receive_index] = NULL;
+
if (
IS_FLAG_SET( stat, ETH_RX_STAT_LAST_FLAG)
&& ARE_FLAGS_CLEARED( stat, LPC24XX_ETH_RX_STAT_ERRORS)
@@ -585,6 +604,9 @@ static void lpc24xx_eth_receive_task( void *arg)
cleanup:
+ /* Clear task ID */
+ e->receive_task = RTEMS_ID_NONE;
+
/* Release network semaphore */
rtems_bsdnet_semaphore_release();
@@ -665,42 +687,19 @@ static void lpc24xx_eth_transmit_task( void *arg)
LPC24XX_ETH_PRINTF( "%s\n", __func__);
- /* Disable transmit interrupts */
- lpc24xx_eth_disable_transmit_interrupts();
-
- /* Disable transmitter */
- MAC_COMMAND = CLEAR_FLAG( MAC_COMMAND, ETH_CMD_TX_ENABLE);
-
- /* Clear transmit interrupts */
- MAC_INTCLEAR = LPC24XX_ETH_INTERRUPT_TRANSMIT;
-
/* Initialize descriptor table */
for (produce_index = 0; produce_index <= index_max; ++produce_index) {
desc [produce_index].start =
(uint32_t) (buf + produce_index * LPC24XX_ETH_TRANSMIT_BUFFER_SIZE);
- desc [produce_index].control = 0;
}
- /* Transmit descriptors */
- MAC_TXDESCRIPTORNUM = index_max;
- MAC_TXDESCRIPTOR = (uint32_t) desc;
- MAC_TXSTATUS = (uint32_t) status;
-
- /* Initialize indices */
- produce_index = MAC_TXPRODUCEINDEX;
- consume_index = MAC_TXCONSUMEINDEX;
-
- /* Frame buffer start */
- frame_buffer = (char *) desc [produce_index].start;
-
- /* Enable transmitter */
- MAC_COMMAND = SET_FLAG( MAC_COMMAND, ETH_CMD_TX_ENABLE);
-
/* Main event loop */
while (true) {
/* Wait for events */
sc = rtems_bsdnet_event_receive(
- LPC24XX_ETH_EVENT_TRANSMIT | LPC24XX_ETH_EVENT_TRANSMIT_START,
+ LPC24XX_ETH_EVENT_INITIALIZE
+ | LPC24XX_ETH_EVENT_START
+ | LPC24XX_ETH_EVENT_INTERRUPT,
RTEMS_EVENT_ANY | RTEMS_WAIT,
RTEMS_NO_TIMEOUT,
&events
@@ -709,6 +708,41 @@ static void lpc24xx_eth_transmit_task( void *arg)
LPC24XX_ETH_PRINTF( "tx: wake up: 0x%08" PRIx32 "\n", events);
+ /* Initialize transmitter? */
+ if (IS_FLAG_SET( events, LPC24XX_ETH_EVENT_INITIALIZE)) {
+ /* Disable transmit interrupts */
+ lpc24xx_eth_disable_transmit_interrupts();
+
+ /* Disable transmitter */
+ MAC_COMMAND = CLEAR_FLAG( MAC_COMMAND, ETH_CMD_TX_ENABLE);
+
+ /* Wait for inactive status */
+ while (IS_FLAG_SET( MAC_STATUS, ETH_STAT_TX_ACTIVE)) {
+ /* Wait */
+ }
+
+ /* Reset */
+ MAC_COMMAND = SET_FLAG( MAC_COMMAND, ETH_CMD_TX_RESET);
+
+ /* Clear transmit interrupts */
+ MAC_INTCLEAR = LPC24XX_ETH_INTERRUPT_TRANSMIT;
+
+ /* Transmit descriptors */
+ MAC_TXDESCRIPTORNUM = index_max;
+ MAC_TXDESCRIPTOR = (uint32_t) desc;
+ MAC_TXSTATUS = (uint32_t) status;
+
+ /* Initialize indices */
+ produce_index = MAC_TXPRODUCEINDEX;
+ consume_index = MAC_TXCONSUMEINDEX;
+
+ /* Frame buffer start */
+ frame_buffer = (char *) desc [produce_index].start;
+
+ /* Enable transmitter */
+ MAC_COMMAND = SET_FLAG( MAC_COMMAND, ETH_CMD_TX_ENABLE);
+ }
+
/* Free consumed fragments */
while (true) {
/* Save last known consume index */
@@ -749,9 +783,6 @@ static void lpc24xx_eth_transmit_task( void *arg)
}
}
- /* Reinitialize control field */
- desc [c].control = 0;
-
/* Next consume index */
c = lpc24xx_eth_increment( c, index_max);
}
@@ -849,6 +880,9 @@ static void lpc24xx_eth_transmit_task( void *arg)
cleanup:
+ /* Clear task ID */
+ e->transmit_task = RTEMS_ID_NONE;
+
/* Release network semaphore */
rtems_bsdnet_semaphore_release();
@@ -858,6 +892,7 @@ cleanup:
static void lpc24xx_eth_interface_init( void *arg)
{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
lpc24xx_eth_driver_entry *e = (lpc24xx_eth_driver_entry *) arg;
struct ifnet *ifp = &e->arpcom.ac_if;
@@ -865,28 +900,25 @@ static void lpc24xx_eth_interface_init( void *arg)
if (e->state == LPC24XX_ETH_INITIALIZED) {
#ifndef LPC24XX_HAS_UBOOT
- rtems_interrupt_level level;
-
- rtems_interrupt_disable( level);
-
- /* Enable power */
- PCONP = SET_FLAGS( PCONP, 0x40000000);
+ /* Enable module power */
+ lpc24xx_module_enable(
+ LPC24XX_MODULE_ETHERNET,
+ 0,
+ LPC24XX_MODULE_PCLK_DEFAULT
+ );
- /* Set PIN selects */
+ /* Module IO configuration */
#ifdef LPC24XX_ETHERNET_RMII
- PINSEL2 = SET_FLAGS( PINSEL2, 0x55555555);
+ lpc24xx_io_config( LPC24XX_MODULE_ETHERNET, 0, 0);
#else
- PINSEL2 = SET_FLAGS( PINSEL2, 0x50150105);
+ lpc24xx_io_config( LPC24XX_MODULE_ETHERNET, 0, 1);
#endif
- PINSEL3 = SET_FLAGS( PINSEL3, 0x05);
-
- rtems_interrupt_enable( level);
/* Soft reset */
/* Do soft reset */
- MAC_MAC1 = 0xcf00;
MAC_COMMAND = 0x38;
+ MAC_MAC1 = 0xcf00;
/* Initialize PHY */
/* TODO */
@@ -919,18 +951,14 @@ static void lpc24xx_eth_interface_init( void *arg)
/* Enable receiver */
MAC_MAC1 = 0x03;
#else /* LPC24XX_HAS_UBOOT */
- uint32_t reg = 0;
-
- /* TODO */
+ /* Reset receiver and transmitter */
+ MAC_COMMAND = SET_FLAGS(
+ MAC_COMMAND,
+ ETH_CMD_RX_RESET | ETH_CMD_TX_RESET | ETH_CMD_REG_RESET
+ );
/* MAC configuration */
MAC_MAC1 = 0x3;
-
- /* Disable and reset receiver and transmitter */
- reg = MAC_COMMAND;
- reg = CLEAR_FLAGS( reg, ETH_CMD_RX_ENABLE | ETH_CMD_TX_ENABLE);
- reg = SET_FLAGS( reg, ETH_CMD_RX_RESET | ETH_CMD_TX_RESET);
- MAC_COMMAND = reg;
#endif /* LPC24XX_HAS_UBOOT */
/* Start receive task */
@@ -941,6 +969,8 @@ static void lpc24xx_eth_interface_init( void *arg)
lpc24xx_eth_receive_task,
e
);
+ sc = rtems_event_send( e->receive_task, LPC24XX_ETH_EVENT_INITIALIZE);
+ RTEMS_SYSLOG_ERROR_SC( sc, "send receive initialize event");
}
/* Start transmit task */
@@ -951,6 +981,8 @@ static void lpc24xx_eth_interface_init( void *arg)
lpc24xx_eth_transmit_task,
e
);
+ sc = rtems_event_send( e->transmit_task, LPC24XX_ETH_EVENT_INITIALIZE);
+ RTEMS_SYSLOG_ERROR_SC( sc, "send transmit initialize event");
}
/* Change state */
@@ -983,6 +1015,8 @@ static void lpc24xx_eth_interface_init( void *arg)
static void lpc24xx_eth_interface_stats( const lpc24xx_eth_driver_entry *e)
{
+ rtems_bsdnet_semaphore_release();
+
printf( "received frames: %u\n", e->received_frames);
printf( "receive interrupts: %u\n", e->receive_interrupts);
printf( "transmitted frames: %u\n", e->transmitted_frames);
@@ -1002,6 +1036,8 @@ static void lpc24xx_eth_interface_stats( const lpc24xx_eth_driver_entry *e)
printf( "transmit no descriptor errors: %u\n", e->transmit_no_descriptor_errors);
printf( "transmit overflow errors: %u\n", e->transmit_overflow_errors);
printf( "transmit fatal errors: %u\n", e->transmit_fatal_errors);
+
+ rtems_bsdnet_semaphore_obtain();
}
static int lpc24xx_eth_interface_ioctl(
@@ -1051,7 +1087,7 @@ static void lpc24xx_eth_interface_start( struct ifnet *ifp)
ifp->if_flags = SET_FLAG( ifp->if_flags, IFF_OACTIVE);
- sc = rtems_event_send( e->transmit_task, LPC24XX_ETH_EVENT_TRANSMIT_START);
+ sc = rtems_event_send( e->transmit_task, LPC24XX_ETH_EVENT_START);
RTEMS_SYSLOG_ERROR_SC( sc, "send transmit start event");
}