Skip to content

Commit 15d1b93

Browse files
authored
Merge pull request #15284 from ramielkhatibPQS/master
Fix MPS2 CM3DS ethernet driver
2 parents e2e927e + fdf37c3 commit 15d1b93

File tree

4 files changed

+54
-166
lines changed

4 files changed

+54
-166
lines changed

connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,13 @@ emac_mem_buf_t *SMSC9220_EMAC::low_level_input()
8989
message_length -= CRC_LENGTH_BYTES;
9090
}
9191
92-
p = _memory_manager->alloc_heap(SMSC9220_ETH_MAX_FRAME_SIZE,
92+
p = _memory_manager->alloc_heap(message_length,
9393
SMSC9220_BUFF_ALIGNMENT);
9494
9595
if (p != NULL) {
9696
_RXLockMutex.lock();
97-
received_bytes = smsc9220_receive_by_chunks(dev,
98-
(char*)_memory_manager->get_ptr(p),
99-
_memory_manager->get_len(p));
97+
received_bytes = smsc9220_receive_packet(dev,
98+
_memory_manager->get_ptr(p));
10099
if(received_bytes == 0){
101100
_memory_manager->free(p);
102101
p = nullptr;
@@ -148,7 +147,6 @@ bool SMSC9220_EMAC::link_out(emac_mem_buf_t *buf)
148147
if(buf == NULL) {
149148
return false;
150149
} else {
151-
uint32_t buffer_chain_length = 0;
152150
enum smsc9220_error_t error = SMSC9220_ERROR_NONE;
153151
/* If buffer is chained or not aligned then
154152
* make a contiguous aligned copy of it */
@@ -170,16 +168,12 @@ bool SMSC9220_EMAC::link_out(emac_mem_buf_t *buf)
170168
buf = copy_buf;
171169
}
172170
173-
buffer_chain_length = _memory_manager->get_total_len(buf);
174-
175171
_TXLockMutex.lock();
176-
error = smsc9220_send_by_chunks(dev,
177-
buffer_chain_length,
178-
true,
179-
(const char*)_memory_manager->get_ptr(buf),
172+
error = smsc9220_send_packet(dev,
173+
_memory_manager->get_ptr(buf),
180174
_memory_manager->get_len(buf));
181175
_memory_manager->free(buf);
182-
_TXLockMutex.unlock();
176+
_TXLockMutex.unlock();
183177
return (error == SMSC9220_ERROR_NONE);
184178
}
185179
}
@@ -211,7 +205,7 @@ bool SMSC9220_EMAC::power_up()
211205
this));
212206
213207
/* Initialize the hardware */
214-
enum smsc9220_error_t init_successful = smsc9220_init(dev, &ThisThread::sleep_for);
208+
enum smsc9220_error_t init_successful = smsc9220_init(dev, &thread_sleep_for);
215209
if (init_successful != SMSC9220_ERROR_NONE) {
216210
return false;
217211
}
@@ -237,7 +231,7 @@ bool SMSC9220_EMAC::power_up()
237231
&SMSC9220_EMAC::link_status_task));
238232
239233
/* Allow the Link Status task to detect the initial link state */
240-
ThisThread::sleep_for(10);
234+
ThisThread::sleep_for(10ms);
241235
_link_status_task_handle = mbed::mbed_event_queue()->call_every(
242236
LINK_STATUS_TASK_PERIOD_MS,
243237
mbed::callback(this,

connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac_config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#define FLAG_RX 1U
3737
#define LINK_STATUS_THREAD_PRIORITY (osPriorityNormal)
3838
#define LINK_STATUS_THREAD_STACKSIZE 512U
39-
#define LINK_STATUS_TASK_PERIOD_MS 200U
39+
#define LINK_STATUS_TASK_PERIOD_MS 200ms
4040
#define PHY_STATE_LINK_DOWN false
4141
#define PHY_STATE_LINK_UP true
4242
#define CRC_LENGTH_BYTES 4U

targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth_drv.c

Lines changed: 34 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -284,73 +284,6 @@ enum gpio_cfg_bits_t{
284284
GPIO_CFG_GPIO2_LED_INDEX = 30U /*< GPIO2 set to LED3 */
285285
};
286286

287-
288-
static void fill_tx_fifo(const struct smsc9220_eth_dev_t* dev,
289-
uint8_t *data, uint32_t size_bytes)
290-
{
291-
struct smsc9220_eth_reg_map_t* register_map =
292-
(struct smsc9220_eth_reg_map_t*)dev->cfg->base;
293-
294-
uint32_t tx_data_port_tmp = 0;
295-
uint8_t *tx_data_port_tmp_ptr = (uint8_t *)&tx_data_port_tmp;
296-
297-
/*If the data length is not a multiple of 4, then the beginning of the first
298-
* DWORD of the TX DATA FIFO gets filled up with zeros and a byte offset is
299-
* set accordingly to guarantee proper transmission.*/
300-
uint32_t remainder_bytes = (size_bytes % 4);
301-
uint32_t filler_bytes = (4 - remainder_bytes);
302-
for(uint32_t i = 0; i < 4; i++){
303-
if(i < filler_bytes){
304-
tx_data_port_tmp_ptr[i] = 0;
305-
} else {
306-
tx_data_port_tmp_ptr[i] = data[i-filler_bytes];
307-
}
308-
}
309-
register_map->tx_data_port = tx_data_port_tmp;
310-
size_bytes -= remainder_bytes;
311-
data += remainder_bytes;
312-
313-
while (size_bytes > 0) {
314-
/* Keep the same endianness in data as in the temp variable */
315-
tx_data_port_tmp_ptr[0] = data[0];
316-
tx_data_port_tmp_ptr[1] = data[1];
317-
tx_data_port_tmp_ptr[2] = data[2];
318-
tx_data_port_tmp_ptr[3] = data[3];
319-
register_map->tx_data_port = tx_data_port_tmp;
320-
data += 4;
321-
size_bytes -= 4;
322-
}
323-
}
324-
325-
static void empty_rx_fifo(const struct smsc9220_eth_dev_t* dev,
326-
uint8_t *data, uint32_t size_bytes)
327-
{
328-
struct smsc9220_eth_reg_map_t* register_map =
329-
(struct smsc9220_eth_reg_map_t*)dev->cfg->base;
330-
331-
uint32_t rx_data_port_tmp = 0;
332-
uint8_t *rx_data_port_tmp_ptr = (uint8_t *)&rx_data_port_tmp;
333-
334-
uint32_t remainder_bytes = (size_bytes % 4);
335-
size_bytes -= remainder_bytes;
336-
337-
while (size_bytes > 0) {
338-
/* Keep the same endianness in data as in the temp variable */
339-
rx_data_port_tmp = register_map->rx_data_port;
340-
data[0] = rx_data_port_tmp_ptr[0];
341-
data[1] = rx_data_port_tmp_ptr[1];
342-
data[2] = rx_data_port_tmp_ptr[2];
343-
data[3] = rx_data_port_tmp_ptr[3];
344-
data += 4;
345-
size_bytes -= 4;
346-
}
347-
348-
rx_data_port_tmp = register_map->rx_data_port;
349-
for(uint32_t i = 0; i < remainder_bytes; i++) {
350-
data[i] = rx_data_port_tmp_ptr[i];
351-
}
352-
}
353-
354287
enum smsc9220_error_t smsc9220_mac_regread(
355288
const struct smsc9220_eth_dev_t* dev,
356289
enum smsc9220_mac_reg_offsets_t regoffset,
@@ -949,77 +882,45 @@ enum smsc9220_error_t smsc9220_init(
949882
return SMSC9220_ERROR_NONE;
950883
}
951884

952-
enum smsc9220_error_t smsc9220_send_by_chunks(
885+
enum smsc9220_error_t smsc9220_send_packet (
953886
const struct smsc9220_eth_dev_t* dev,
954-
uint32_t total_payload_length,
955-
bool is_new_packet,
956-
const char *data, uint32_t current_size)
887+
void *data, uint32_t dlen)
957888
{
958889
struct smsc9220_eth_reg_map_t* register_map =
959890
(struct smsc9220_eth_reg_map_t*)dev->cfg->base;
960-
bool is_first_segment = false;
961-
bool is_last_segment = false;
962-
uint32_t txcmd_a, txcmd_b = 0;
891+
uint32_t txcmd_a = 0, txcmd_b = 0;
963892
uint32_t tx_buffer_free_space = 0;
964-
volatile uint32_t xmit_stat = 0;
965893

966894
if (!data) {
967895
return SMSC9220_ERROR_PARAM;
968896
}
969897

970-
if (is_new_packet) {
971-
is_first_segment = true;
972-
dev->data->ongoing_packet_length = total_payload_length;
973-
dev->data->ongoing_packet_length_sent = 0;
974-
} else if (dev->data->ongoing_packet_length != total_payload_length ||
975-
dev->data->ongoing_packet_length_sent >= total_payload_length) {
976-
return SMSC9220_ERROR_PARAM;
977-
}
978-
979898
/* Would next chunk fit into buffer? */
980899
tx_buffer_free_space = GET_BIT_FIELD(register_map->tx_fifo_inf,
981900
FIFO_USED_SPACE_MASK,
982901
DATA_FIFO_USED_SPACE_POS);
983-
if (current_size > tx_buffer_free_space) {
902+
if (dlen > tx_buffer_free_space) {
984903
return SMSC9220_ERROR_INTERNAL; /* Not enough space in FIFO */
985904
}
986-
if ((dev->data->ongoing_packet_length_sent + current_size) ==
987-
total_payload_length) {
988-
is_last_segment = true;
989-
}
990-
991-
txcmd_a = 0;
992-
txcmd_b = 0;
993-
994-
if (is_last_segment) {
995-
SET_BIT(txcmd_a, TX_COMMAND_A_LAST_SEGMENT_INDEX);
996-
}
997-
if (is_first_segment) {
998-
SET_BIT(txcmd_a, TX_COMMAND_A_FIRST_SEGMENT_INDEX);
999-
}
1000-
1001-
uint32_t data_start_offset_bytes = (4 - (current_size % 4));
1002-
1003-
SET_BIT_FIELD(txcmd_a, TX_CMD_PKT_LEN_BYTES_MASK, 0, current_size);
1004-
SET_BIT_FIELD(txcmd_a, TX_CMD_DATA_START_OFFSET_BYTES_MASK,
1005-
TX_CMD_DATA_START_OFFSET_BYTES_POS,
1006-
data_start_offset_bytes);
1007-
1008-
SET_BIT_FIELD(txcmd_b, TX_CMD_PKT_LEN_BYTES_MASK, 0, current_size);
1009-
SET_BIT_FIELD(txcmd_b, TX_CMD_PKT_TAG_MASK, TX_CMD_PKT_TAG_POS,
1010-
current_size);
1011905

906+
SET_BIT(txcmd_a, TX_COMMAND_A_LAST_SEGMENT_INDEX);
907+
SET_BIT(txcmd_a, TX_COMMAND_A_FIRST_SEGMENT_INDEX);
908+
SET_BIT_FIELD(txcmd_a, TX_CMD_PKT_LEN_BYTES_MASK, 0, dlen);
909+
SET_BIT_FIELD(txcmd_b, TX_CMD_PKT_LEN_BYTES_MASK, 0, dlen);
910+
SET_BIT_FIELD(txcmd_b, TX_CMD_PKT_TAG_MASK, TX_CMD_PKT_TAG_POS, dlen);
1012911
register_map->tx_data_port = txcmd_a;
1013912
register_map->tx_data_port = txcmd_b;
1014913

1015-
fill_tx_fifo(dev, (uint8_t *)data, current_size);
1016-
1017-
if (is_last_segment) {
1018-
/* Pop status port for error check */
1019-
xmit_stat = register_map->tx_status_port;
1020-
(void)xmit_stat;
914+
/* Ethernet data port is padding to 32bit aligned data */
915+
uint32_t dwords_to_write = (dlen + 3) >> 2;
916+
uint32_t *data_ptr = (uint32_t *) data;
917+
for(uint32_t i = 0; i < dwords_to_write; i++) {
918+
register_map->tx_data_port = data_ptr[i];
1021919
}
1022-
dev->data->ongoing_packet_length_sent += current_size;
920+
921+
/* Pop status port for error check */
922+
(void) (register_map->tx_status_port);
923+
1023924
return SMSC9220_ERROR_NONE;
1024925
}
1025926

@@ -1033,10 +934,9 @@ uint32_t smsc9220_get_rxfifo_data_used_space(const struct
1033934
DATA_FIFO_USED_SPACE_POS);
1034935
}
1035936

1036-
uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev,
1037-
char *data, uint32_t dlen)
937+
uint32_t smsc9220_receive_packet(const struct smsc9220_eth_dev_t* dev,
938+
void *data)
1038939
{
1039-
uint32_t rxfifo_inf = 0;
1040940
uint32_t rxfifo_stat = 0;
1041941
uint32_t packet_length_byte = 0;
1042942
struct smsc9220_eth_reg_map_t* register_map =
@@ -1045,22 +945,22 @@ uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev,
1045945
if (!data) {
1046946
return 0; /* Invalid input parameter, cannot read */
1047947
}
1048-
rxfifo_inf = register_map->rx_fifo_inf;
1049-
1050-
if(rxfifo_inf & 0xFFFF) { /* If there's data */
1051-
rxfifo_stat = register_map->rx_status_port;
1052-
if(rxfifo_stat != 0) { /* Fetch status of this packet */
1053-
/* Ethernet controller is padding to 32bit aligned data */
1054-
packet_length_byte = GET_BIT_FIELD(rxfifo_stat,
1055-
RX_FIFO_STATUS_PKT_LENGTH_MASK,
1056-
RX_FIFO_STATUS_PKT_LENGTH_POS);
1057-
packet_length_byte -= 4;
1058-
dev->data->current_rx_size_words = packet_length_byte;
1059-
}
948+
949+
/* Status port not empty from smsc9220_peek_next_packet_size */
950+
rxfifo_stat = register_map->rx_status_port;
951+
packet_length_byte = GET_BIT_FIELD(rxfifo_stat,
952+
RX_FIFO_STATUS_PKT_LENGTH_MASK,
953+
RX_FIFO_STATUS_PKT_LENGTH_POS);
954+
packet_length_byte -= 4; /* Discard last word (CRC) */
955+
956+
/* Ethernet data port is padding to 32bit aligned data */
957+
uint32_t dwords_to_read = (packet_length_byte + 3) >> 2;
958+
uint32_t *data_ptr = (uint32_t *) data;
959+
for(uint32_t i = 0; i < dwords_to_read; i++) {
960+
data_ptr[i] = register_map->rx_data_port;
1060961
}
962+
(void) (register_map->rx_data_port); /* Discard last word (CRC) */
1061963

1062-
empty_rx_fifo(dev, (uint8_t *)data, packet_length_byte);
1063-
dev->data->current_rx_size_words = 0;
1064964
return packet_length_byte;
1065965
}
1066966

targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/smsc9220_eth_drv.h

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -480,40 +480,34 @@ uint32_t smsc9220_get_tx_data_fifo_size(const struct
480480

481481
/**
482482
* \brief Sends data from the given buffer as an Ethernet packet.
483-
* The full packet length must be specified at the beginning
484-
* of a new packet transmission.
483+
* The data to send must be a full packet.
485484
*
486485
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
487-
* \param[in] total_payload_length Length of the ethernet payload.
488-
* Should be equal to the sum of passed buffers within a packet.
489-
* \param[in] is_new_packet Should be set to true if the input buffer has to
490-
* be sent as the start of a new packet or as a full packet.
491-
* \param[in] data Pointer to the data buffer to be sent.
492-
* \param[in] current_size Size of the data in bytes.
486+
* \param[in] data Pointer to the word aligned packet buffer to be sent.
487+
* \param[in] dlen Size of the packet in bytes.
493488
*
494489
* \return error code /ref smsc9220_error_t
495490
*/
496-
enum smsc9220_error_t smsc9220_send_by_chunks(
491+
enum smsc9220_error_t smsc9220_send_packet(
497492
const struct smsc9220_eth_dev_t* dev,
498-
uint32_t total_payload_length,
499-
bool is_new_packet,
500-
const char *data, uint32_t current_size);
493+
void *data, uint32_t dlen);
501494

502495
/**
503496
* \brief Reads an incoming Ethernet packet into the given buffer.
504497
* Stops reading at packet border.
505498
*
506499
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
507-
* \param[in,out] data Pointer to a pre-allocated input buffer.
508-
* Allocating sufficient memory space is the caller's
500+
* \param[in,out] data Pointer to a pre-allocated word aligned input buffer.
501+
* Availability of packets, as well as, alignment and
502+
* allocating sufficient memory space is the caller's
509503
* responsibility, which is typically done by calling
510504
* \ref smsc9220_peek_next_packet_size.
511-
* \param[in] dlen Length of the allocated data in bytes.
512505
*
513506
* \return Number of bytes read from the Rx FIFO into the given buffer.
514507
*/
515-
uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev,
516-
char *data, uint32_t dlen);
508+
uint32_t smsc9220_receive_packet(
509+
const struct smsc9220_eth_dev_t* dev,
510+
void *data);
517511

518512
/**
519513
* \brief Get the used space of Rx fifo in bytes.

0 commit comments

Comments
 (0)