1
1
/* mbed Microcontroller Library
2
- * Copyright (c) 2017 ARM Limited
2
+ * Copyright (c) 2017-2018 ARM Limited
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
@@ -426,6 +426,53 @@ static int smsc9220_check_id(void)
426
426
return 0 ;
427
427
}
428
428
429
+ /**
430
+ * \brief Fill the SMSC9220 TX FIFO with a number of words at an aligned
431
+ * address.
432
+ *
433
+ * \param[in] data Pointer to the aligned data that should be sent.
434
+ * \param[in] dwords_to_write Number of data words to write.
435
+ */
436
+ static void fill_tx_fifo_aligned (unsigned int * data ,
437
+ unsigned int dwords_to_write )
438
+ {
439
+ while (dwords_to_write > 0 ) {
440
+ SMSC9220 -> TX_DATA_PORT = * data ;
441
+ data ++ ;
442
+ dwords_to_write -- ;
443
+ }
444
+ }
445
+
446
+ /**
447
+ * \brief Fill the SMSC9220 TX FIFO with a number of words at an unaligned
448
+ * address. This function ensures that loading words at that address will
449
+ * not generate unaligned access which can trigger an exception to the
450
+ * processor.
451
+ *
452
+ * \param[in] data Pointer to the unaligned data that should be sent.
453
+ * \param[in] dwords_to_write Number of data words to write.
454
+ */
455
+ static void fill_tx_fifo_unaligned (uint8_t * data , unsigned int dwords_to_write )
456
+ {
457
+ /*
458
+ * Prevent unaligned word access from data pointer, 4 bytes are copied to
459
+ * this variable for each word that need to be sent.
460
+ */
461
+ unsigned int tx_data_port_tmp = 0 ;
462
+ uint8_t * tx_data_port_tmp_ptr = (uint8_t * )& tx_data_port_tmp ;
463
+
464
+ while (dwords_to_write > 0 ) {
465
+ /* Keep the same endianness in data than in the temp variable */
466
+ tx_data_port_tmp_ptr [0 ] = data [0 ];
467
+ tx_data_port_tmp_ptr [1 ] = data [1 ];
468
+ tx_data_port_tmp_ptr [2 ] = data [2 ];
469
+ tx_data_port_tmp_ptr [3 ] = data [3 ];
470
+ SMSC9220 -> TX_DATA_PORT = tx_data_port_tmp ;
471
+ data += 4 ;
472
+ dwords_to_write -- ;
473
+ }
474
+ }
475
+
429
476
/*----------------------------------------------------------------------------
430
477
Public API
431
478
*----------------------------------------------------------------------------*/
@@ -574,7 +621,6 @@ int smsc9220_send_by_chunks(unsigned int total_packet_length, int is_new_packet,
574
621
int is_last_segment = 0 ; /* signing this is the last segment of the packet to be sent */
575
622
unsigned int txcmd_a , txcmd_b = 0 ;
576
623
unsigned int dwords_to_write = 0 ;
577
- unsigned int * pktptr = 0 ;
578
624
unsigned int xmit_inf = 0 ;
579
625
unsigned int tx_buffer_free_space = 0 ;
580
626
volatile unsigned int xmit_stat = 0 ;
@@ -602,7 +648,6 @@ int smsc9220_send_by_chunks(unsigned int total_packet_length, int is_new_packet,
602
648
is_last_segment = 1 ;
603
649
}
604
650
605
- pktptr = (unsigned int * ) data ;
606
651
txcmd_a = 0 ;
607
652
txcmd_b = 0 ;
608
653
@@ -616,11 +661,16 @@ int smsc9220_send_by_chunks(unsigned int total_packet_length, int is_new_packet,
616
661
SMSC9220 -> TX_DATA_PORT = txcmd_b ;
617
662
dwords_to_write = (current_size + 3 ) >> 2 ;
618
663
619
- /* PIO Copy to FIFO. Could replace this with DMA. */
620
- while (dwords_to_write > 0 ) {
621
- SMSC9220 -> TX_DATA_PORT = * pktptr ;
622
- pktptr ++ ;
623
- dwords_to_write -- ;
664
+ /*
665
+ * Copy to TX FIFO
666
+ * The function to use depends on the alignment of the data pointer on a 32
667
+ * bits boundary.
668
+ */
669
+ if (((unsigned int )data % sizeof (uint32_t )) == 0 ) {
670
+ /* Cast is safe because we know data is aligned */
671
+ fill_tx_fifo_aligned ((unsigned int * )data , dwords_to_write );
672
+ } else {
673
+ fill_tx_fifo_unaligned ((uint8_t * )data , dwords_to_write );
624
674
}
625
675
626
676
if (is_last_segment ) {
0 commit comments