|
16 | 16 | #include <mios/mios.h> |
17 | 17 | #include <mios/eventlog.h> |
18 | 18 | #include <mios/sys.h> |
| 19 | +#include <mios/type_macros.h> |
19 | 20 |
|
20 | 21 | #include <util/crc32.h> |
21 | 22 |
|
22 | 23 | #include "irq.h" |
23 | 24 |
|
| 25 | +#define MAC_NAME "stm32f4-eth" |
| 26 | + |
24 | 27 | #define DMA_BUFFER_PAD 2 |
25 | 28 |
|
26 | 29 | #define ETH_TX_RING_SIZE 16 |
@@ -132,7 +135,6 @@ typedef struct stm32f4_eth { |
132 | 135 | timer_t se_periodic; |
133 | 136 |
|
134 | 137 | #ifdef ENABLE_NET_PTP |
135 | | - int64_t se_accumulated_drift_ppb; |
136 | 138 | uint32_t se_addend; |
137 | 139 | int32_t se_ppb_scale_mult; |
138 | 140 | int32_t se_ppb_scale_div; |
@@ -195,14 +197,12 @@ stm32f4_eth_print_info(struct device *dev, struct stream *st) |
195 | 197 | strtbl(mactxfcstatus, (macdbg >> 17) & 3), |
196 | 198 | macdbg & (1 << 16) ? "MMTEA " : ""); |
197 | 199 | #ifdef ENABLE_NET_PTP |
198 | | - stprintf(st, "MAC time: %u.%u\n", |
199 | | - reg_rd(ETH_PTPTSHR), |
200 | | - reg_rd(ETH_PTPTSLR)); |
201 | | - ptp_print_info(st, &se->se_eni); |
| 200 | + if(ptp_print_info(st, &se->se_eni)) { |
| 201 | + stprintf(st, " Hardware time: %u.%u\n", |
| 202 | + reg_rd(ETH_PTPTSHR), |
| 203 | + reg_rd(ETH_PTPTSLR)); |
| 204 | + } |
202 | 205 | #endif |
203 | | - |
204 | | - // if(se->se_ethphy_class && se->se_ethphy_class->print_info) |
205 | | - // se->se_ethphy_class->print_info(st, &stm32f4_eth_mdio, se); |
206 | 206 | } |
207 | 207 |
|
208 | 208 |
|
@@ -534,75 +534,82 @@ stm32f4_periodic(void *opaque, uint64_t now) |
534 | 534 |
|
535 | 535 | #ifdef ENABLE_NET_PTP |
536 | 536 |
|
537 | | -#define PTP_STEP_THRESHOLD_NS 100000000LL // 10 ms |
538 | | -#define MAX_ADJ_PPB 100000 |
539 | | -#define SERVO_KP_SHIFT 2 |
540 | | -#define SERVO_KI_SHIFT 7 |
| 537 | +static void |
| 538 | +stm32f4_clock_set_time(clock_realtime_t *clk, int64_t nsec) |
| 539 | +{ |
| 540 | + reg_wr(ETH_PTPTSHUR, nsec / 1000000000); |
| 541 | + reg_wr(ETH_PTPTSLUR, nsec % 1000000000); |
| 542 | + reg_set_bit(ETH_PTPTSCR, 2); |
| 543 | + while(reg_get_bit(ETH_PTPTSCR, 2)); |
| 544 | +} |
541 | 545 |
|
542 | | -void |
543 | | -ptp_clock_slew(stm32f4_eth_t *se, int64_t offset_ns) |
| 546 | +static int64_t |
| 547 | +stm32f4_clock_get_time(clock_realtime_t *clk) |
544 | 548 | { |
545 | | - int64_t adj_p = offset_ns >> SERVO_KP_SHIFT; |
546 | | - se->se_accumulated_drift_ppb += (offset_ns >> SERVO_KI_SHIFT); |
| 549 | + while(1) { |
| 550 | + uint32_t s = reg_rd(ETH_PTPTSHR); |
| 551 | + uint32_t ns = reg_rd(ETH_PTPTSLR); |
| 552 | + if(s == reg_rd(ETH_PTPTSHR)) { |
| 553 | + return (int64_t)s * 1000000000 + ns; |
| 554 | + } |
| 555 | + } |
| 556 | +} |
547 | 557 |
|
548 | | - // Anti-windup clamping |
549 | | - if(se->se_accumulated_drift_ppb > MAX_ADJ_PPB) |
550 | | - se->se_accumulated_drift_ppb = MAX_ADJ_PPB; |
551 | | - else if(se->se_accumulated_drift_ppb < -MAX_ADJ_PPB) |
552 | | - se->se_accumulated_drift_ppb = -MAX_ADJ_PPB; |
| 558 | +static void |
| 559 | +stm32f4_clock_adj_time(clock_realtime_t *clk, int32_t ppb) |
| 560 | +{ |
| 561 | + stm32f4_eth_t *se = |
| 562 | + container_of(clk, stm32f4_eth_t, se_eni.eni_ptp.pes_clock); |
553 | 563 |
|
554 | | - int64_t total_ppb = adj_p + se->se_accumulated_drift_ppb; |
555 | 564 | int32_t addend_adjustment = |
556 | | - (total_ppb * se->se_ppb_scale_mult) / se->se_ppb_scale_div; |
| 565 | + ((int64_t)ppb * se->se_ppb_scale_mult) / se->se_ppb_scale_div; |
557 | 566 |
|
558 | 567 | uint32_t final_addend = se->se_addend + addend_adjustment; |
559 | 568 | reg_wr(ETH_PTPTSAR, final_addend); |
560 | 569 | reg_set_bit(ETH_PTPTSCR, 5); |
561 | 570 | } |
562 | 571 |
|
563 | | - |
564 | | -int64_t |
565 | | -stm32f4_get_current_mac_time(void) |
566 | | -{ |
567 | | - while(1) { |
568 | | - const uint32_t cur_s = reg_rd(ETH_PTPTSHR); |
569 | | - const uint32_t cur_ns = reg_rd(ETH_PTPTSLR); |
570 | | - if(cur_s == reg_rd(ETH_PTPTSHR)) { |
571 | | - return (int64_t)cur_s * 1000000000 + cur_ns; |
572 | | - } |
573 | | - } |
574 | | -} |
575 | | - |
| 572 | +static const clock_realtime_class_t stm32f4_clock_realtime_class = { |
| 573 | + .name = MAC_NAME, |
| 574 | + .set_time = stm32f4_clock_set_time, |
| 575 | + .get_time = stm32f4_clock_get_time, |
| 576 | + .adj_time = stm32f4_clock_adj_time, |
| 577 | +}; |
576 | 578 |
|
577 | 579 | static void |
578 | | -ptp_clock_step(stm32f4_eth_t *se, int64_t offset_ns) |
| 580 | +stm32f4_ptp_init(stm32f4_eth_t *se) |
579 | 581 | { |
580 | | - int64_t cur_t = stm32f4_get_current_mac_time(); |
581 | | - int64_t ch = cur_t + offset_ns; |
| 582 | + const unsigned int ahb_freq = CPU_SYSTICK_RVR; |
582 | 583 |
|
583 | | - reg_wr(ETH_PTPTSHUR, ch / 1000000000); |
584 | | - reg_wr(ETH_PTPTSLUR, ch % 1000000000); |
585 | | - reg_set_bit(ETH_PTPTSCR, 2); |
586 | | - while(reg_get_bit(ETH_PTPTSCR, 2)); |
| 584 | + uint32_t ssinc = (1000000000 / ahb_freq) + 1; |
587 | 585 |
|
588 | | - se->se_accumulated_drift_ppb = 0; // Reset clock servo integrator |
| 586 | + uint64_t numerator = 1000000000ULL; |
| 587 | + uint64_t denominator = ahb_freq * ssinc; |
| 588 | + se->se_addend = (numerator << 32) / denominator; |
589 | 589 |
|
590 | | - evlog(LOG_DEBUG, "%s: Step adjust %lld", se->se_eni.eni_ni.ni_dev.d_name, |
591 | | - offset_ns); |
592 | | -} |
| 590 | + se->se_ppb_scale_mult = se->se_addend / 1000; |
| 591 | + se->se_ppb_scale_div = 1000000; |
593 | 592 |
|
| 593 | + reg_wr(ETH_PTPTSCR, |
| 594 | + (1 << 11) | // PTPv2 ethernet |
| 595 | + (1 << 10) | // Enable timestamping for PTPv2 |
| 596 | + (1 << 9) | // Rollover ns at 999999999 |
| 597 | + (1 << 1) | // Fine mode |
| 598 | + (1 << 0) | // Enable |
| 599 | + 0); |
594 | 600 |
|
595 | | -static void |
596 | | -stm32f4_eth_set_clock(struct ether_netif *eni, int64_t offset_ns) |
597 | | -{ |
598 | | - stm32f4_eth_t *se = (stm32f4_eth_t *)eni; |
599 | | - int64_t abs_offset = (offset_ns < 0) ? -offset_ns : offset_ns; |
| 601 | + reg_wr(ETH_PTPSSIR, ssinc); |
| 602 | + reg_wr(ETH_PTPTSHUR, 0); |
| 603 | + reg_wr(ETH_PTPTSLUR, 0); |
| 604 | + reg_set_bit(ETH_PTPTSCR, 2); |
600 | 605 |
|
601 | | - if(abs_offset > PTP_STEP_THRESHOLD_NS) { |
602 | | - ptp_clock_step(se, offset_ns); |
603 | | - } else { |
604 | | - ptp_clock_slew(se, offset_ns); |
605 | | - } |
| 606 | + reg_wr(ETH_PTPTSAR, se->se_addend); |
| 607 | + reg_set_bit(ETH_PTPTSCR, 5); |
| 608 | + while(reg_get_bit(ETH_PTPTSCR, 5)); |
| 609 | + |
| 610 | + se->se_eni.eni_ptp.pes_clock.clk_class = &stm32f4_clock_realtime_class; |
| 611 | + clock_servo_init(&se->se_eni.eni_ptp.pes_servo, |
| 612 | + &se->se_eni.eni_ptp.pes_clock); |
606 | 613 | } |
607 | 614 |
|
608 | 615 | #endif |
@@ -657,40 +664,7 @@ stm32f4_thread(stm32f4_eth_t *se, gpio_t phyrst, |
657 | 664 | usleep(10); |
658 | 665 |
|
659 | 666 | #ifdef ENABLE_NET_PTP |
660 | | - if(flags & STM32F4_ETH_ENABLE_PTP_TIMESTAMPING) { |
661 | | - |
662 | | - const unsigned int ahb_freq = CPU_SYSTICK_RVR; |
663 | | - |
664 | | - uint32_t ssinc = (1000000000 / ahb_freq) + 1; |
665 | | - |
666 | | - uint64_t numerator = 1000000000ULL; |
667 | | - uint64_t denominator = ahb_freq * ssinc; |
668 | | - se->se_addend = (numerator << 32) / denominator; |
669 | | - |
670 | | - se->se_ppb_scale_mult = se->se_addend / 1000; |
671 | | - se->se_ppb_scale_div = 1000000; |
672 | | - |
673 | | - reg_wr(ETH_PTPTSCR, |
674 | | - (1 << 11) | // PTPv2 ethernet |
675 | | - (1 << 10) | // Enable timestamping for PTPv2 |
676 | | - (1 << 9) | // Rollover ns at 999999999 |
677 | | - (1 << 1) | // Fine mode |
678 | | - (1 << 0) | // Enable |
679 | | - 0); |
680 | | - |
681 | | - reg_wr(ETH_PTPSSIR, ssinc); |
682 | | - reg_wr(ETH_PTPTSHUR, 0); |
683 | | - reg_wr(ETH_PTPTSLUR, 0); |
684 | | - reg_set_bit(ETH_PTPTSCR, 2); |
685 | | - |
686 | | - reg_wr(ETH_PTPTSAR, se->se_addend); |
687 | | - reg_set_bit(ETH_PTPTSCR, 5); |
688 | | - while(reg_get_bit(ETH_PTPTSCR, 5)); |
689 | | - |
690 | | - se->se_eni.eni_adjust_mac_clock = stm32f4_eth_set_clock; |
691 | | -} |
692 | | - |
693 | | - |
| 667 | + stm32f4_ptp_init(se); |
694 | 668 | #endif |
695 | 669 |
|
696 | 670 | reg_set_bit(ETH_MACCR, 13); // Receive-Own-Disable |
@@ -765,7 +739,7 @@ stm32f4_eth_set_duplex(ether_netif_t *eni, int full) |
765 | 739 |
|
766 | 740 | static const ethmac_device_class_t stm32f4_eth_device_class = { |
767 | 741 | .dc = { |
768 | | - .dc_class_name = "stm32f4 Ethernet NIC", |
| 742 | + .dc_class_name = MAC_NAME, |
769 | 743 | .dc_print_info = stm32f4_eth_print_info, |
770 | 744 | }, |
771 | 745 |
|
|
0 commit comments