Как передать данные между микроконтроллерами на 100 Mbps

    Встала передо мной такая вот проблема — надо передавать данные между двумя микроконтроллерами STM32F407 хотя бы на скорости 100 Mbps. Можно было бы использовать Ethernet (MAC-to-MAC), но вот беда — он занят, именно из него и берутся эти данные…
    Из незадействованной периферии есть разве что SPI — но он только 42 Mbps.

    Как ни странно, ничего готового в сети не нашлось. И я решил реализовать параллельный тактируемый регистр на 8 бит. А что — частоту можно задать в 10 Мгц (то есть, конечно, собственно такты вдвое быстрее, но и 20 Мгц не есть что-то сложное) — так что с такой невысокой частотой не придется мучиться с разводкой платы. А скорость как раз и будет 100 Mbps.

    Сказано — сделано. В общем виде система выглядит так. На передающей стороне используем таймер, один из сигналов сравнения выводим на пин — это будет тактовый сигнал, а второй будем использовать для запуска одной пересылки (burst) для DMA.

    Шина у меня на частоте 82 МГц (из-за потребления тока на большей частоте :), таймер на той же частоте: так что при периоде ARR = 8 получается 10 Мгц примерно (стало быть будет около 80 Mbps, ну да и ладно).

    DMA будет по такту пересылать один байт из памяти (с автоинкрементом, конечно) прямо в порт вывода регистра — в моем случае подошел PORTE — его первые 8 бит как раз и подходят как адрес приемника DMA.

    На приемной стороне тактовый сигнал будем по обоим перепадам использовать для тактирования таймера, с периодом 1, а сигнал update будем использовать для запуска пересылки для DMA, который читает данные из порта (опять подошел порт PORTE) и записывает в память с автоинкрементом.

    Теперь осталось правильно настроить все (код ниже) и запустить. Завершение на обеих сторонах определяется по прерыванию от DMA.

    Однако, для полноты картины нужно конечно включить в код проверки на задержки передачи и обработку ошибок, но это я опускаю.

    В коде ниже у таймера TIM8 использован канал CC2 для вывода сигнала — чтобы посмотреть, что получается.

    volatile int transmit_done;
    volatile int receive_done;
    
    void DMA2_Stream1_IRQHandler(void) {
        TIM8->CR1 &= ~TIM_CR1_CEN;
        DMA2->LIFCR |= 0b1111 << 8;
        receive_done = 1;
    }
    
    void DMA2_Stream4_IRQHandler(void) {
        TIM1->CR1 &= ~TIM_CR1_CEN;
        TIM1->EGR |= TIM_EGR_BG;
        DMA2->HIFCR |= 0b1111101;
        transmit_done = 1;
    }
    
    void ii_receive(uint8_t *data, int len) {
        GPIOE->MODER = (GPIOE->MODER & 0xFFFF0000) | 0x0000;
        DMA2_Stream1->PAR = (uint32_t) &(GPIOE->IDR);
        DMA2_Stream1->M0AR = (uint32_t) data;
        DMA2_Stream1->NDTR = len;
        TIM8->CNT = 0;
        TIM8->BDTR |= TIM_BDTR_MOE;
        receive_done = 0;
        DMA2_Stream1->CR |= DMA_SxCR_EN;
        TIM8->CR1 |= TIM_CR1_CEN;
    }
    
    void ii_transmit(uint8_t *data, int len) {
        GPIOE->MODER = (GPIOE->MODER & 0xFFFF0000) | 0x5555;
        DMA2_Stream4->PAR = (uint32_t) &(GPIOE->ODR);
        DMA2_Stream4->M0AR = (uint32_t) data;
        DMA2_Stream4->NDTR = len;
        TIM1->CNT = 6;
        transmit_done = 0;
        DMA2_Stream4->CR |= DMA_SxCR_EN;
        TIM1->SR |= TIM_SR_BIF;
        TIM1->BDTR |= TIM_BDTR_MOE;
        TIM1->CR1 |= TIM_CR1_CEN;
    }
    
    // tx: TIM1 CH4 on DMA2/stream4/channel6, CH1 on output clock in PE9
    // rx: TIM8 CH2 on DMA2/stream3/channel7, CH1 on input clock in PC6
    void ii_init() {
        __HAL_RCC_GPIOC_CLK_ENABLE();
        __HAL_RCC_GPIOE_CLK_ENABLE();
        __HAL_RCC_TIM1_CLK_ENABLE();
        __HAL_RCC_TIM8_CLK_ENABLE();
        __HAL_RCC_TIM2_CLK_ENABLE();
        __HAL_RCC_DMA2_CLK_ENABLE();
        GPIOC->MODER |= (0b10 << GPIO_MODER_MODE6_Pos)
                | (0b10 << GPIO_MODER_MODE7_Pos);
        GPIOC->PUPDR |= (0b10 << GPIO_PUPDR_PUPD7_Pos);
        GPIOC->AFR[0] |= (GPIO_AF3_TIM8 << 24) | (GPIO_AF3_TIM8 << 28);
        GPIOE->MODER |= (0b10 << GPIO_MODER_MODE9_Pos);
        GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9 | 0xFFFF;
        GPIOE->AFR[1] |= GPIO_AF1_TIM1 << 4;
        GPIOE->PUPDR |= (0b10 << GPIO_PUPDR_PUPD9_Pos);
        TIM1->ARR = 8;
        TIM1->CCR1 = 5;
        TIM1->CCR4 = 1;
        TIM1->EGR |= TIM_EGR_CC4G;
        TIM1->DIER |= TIM_DIER_CC4DE;
        TIM1->CCMR1 |= (0b110 << TIM_CCMR1_OC1M_Pos);
        TIM1->CCER |= TIM_CCER_CC1E;
        TIM1->EGR |= TIM_EGR_BG;
        TIM8->ARR = 1;
        TIM8->CCR2 = 1;
        TIM8->EGR |= TIM_EGR_UG;
        TIM8->DIER |= TIM_DIER_UDE;
        TIM8->SMCR |= (0b100 << TIM_SMCR_TS_Pos) | (0b111 << TIM_SMCR_SMS_Pos);
        TIM8->CCMR1 = (0b01 << TIM_CCMR1_CC1S_Pos) | (0b110 << TIM_CCMR1_OC2M_Pos);
        TIM8->CCER |= (0b11 << TIM_CCER_CC1P_Pos) | TIM_CCER_CC2E;
        DMA2_Stream1->CR = DMA_CHANNEL_7 | DMA_PRIORITY_VERY_HIGH | DMA_MINC_ENABLE
                | (0b00 << DMA_SxCR_DIR_Pos) | DMA_SxCR_TCIE | DMA_SxCR_TEIE
                | DMA_SxCR_DMEIE;
        DMA2_Stream1->FCR |= DMA_FIFOMODE_ENABLE;
        DMA2_Stream4->CR = DMA_CHANNEL_6 | DMA_PRIORITY_VERY_HIGH | DMA_MINC_ENABLE
                | (0b01 << DMA_SxCR_DIR_Pos) | DMA_SxCR_TCIE | DMA_SxCR_TEIE
                | DMA_SxCR_DMEIE;
        DMA2_Stream4->FCR |= DMA_FIFOMODE_ENABLE;
        HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
        HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);
    }
    

    Для тестов была использована одна и та же плата, просто тактовый выход PE9 был соединен с входом PC6. Главный цикл выглядел так:

     ii_receive(rdata, 256);
     ii_transmit(tdata, 256);
     while (!transmit_done);
     while (!receive_done);
    

    По результатам: данные отлично пересылались за 30-31 микросекунду без потерь. Сигналы выглядят как-то так:


    здесь белый — выход таймера TIM8, красный — тактовый сигнал (TIM1), ну а оранжевый — это младший бит данных (0-1-0-1-...).

    Что не нравится при этом — ну нельзя никак запускать DMA от прерывания от входа GPIO, вот и приходится работать с таймерами. Может, кто-нибудь подскажет другой способ?

    P.S. В результате свежих экспериментов выяснилось, что поднятие частоты до 168 МГц закономерно увеличило скорость в 2 раза и данные передались за 14 мксек ( то есть 150 Mbps), а вот при уменьшении границы мастер-таймера ниже 7 начались глюки приемной стороны — не успевает таймер TIM8. При 7 еще работает, но при 6 — уже нет, а ведь это 200 Mbps было бы…
    Поделиться публикацией

    Комментарии 84

      0
      Нк раз такой велосипед изобрелся, то спрошу: не проще ли будет использовать 2+ SPI на максимальной скорости (один для первой половины, второй для второй половины данных)? Пинов отнимите в идеале 6 и еще прием организовать сможете.
        0
        Я так и попробовал вначале — но вот незадача, я могу только SPI1 и SPI3 использовать, тут, во-первых SPI3 только 24 Mbps дает, да и то при 168 МГц, ну и во-вторых, разводка все-же усложняется. А вот пинов хватает, аж остается… Так что такой подход вполне себе жизнеспособен, я думаю. К тому же остается запас по скорости — тут можно и поднять ее хотя бы в 2 раза…
        0
        «Можно было бы использовать Ethernet (MAC-to-MAC), но вот беда — он занят, именно из него и берутся эти данные…»
        А он разве симплексный? Сетевой адаптер разве не может одновременно передавать и получать данные? А данные не могут идти сразу на нужное устройство?
          +1
          Ethernet конечно, дуплекс. Но тут требуется получить пакет из Phy и его обработать, а затем передать на другой контроллер (идет борьба за стоимость :)
            –1
            А при вашем способе передачи его «обработать» не надо?
              0
              не понял ваш вопрос. Я и написал, что надо обработать, а сетевой адаптер просто передаст данные.
                –1
                Ну на FD интерфейсе ничто не мешает данные принять, обработать и отдать, лишь бы проц «обработку» потянул.
                  0
                  а что это — FD интерфейс и где он?
                    –1
                    Режим Full Duplex у Ethernet, позволяет одновременно данные и принимать и отправлять.
                      0
                      У микроконтроллера нет никакого FD, а есть MAC, все пляски тут и происходят — MAC принимает данные, использует выделенный DMA, записывает их в цепочку блоков данных и затем устанавливает прерывание. То же и для отправки (в обратном порядке) надо сделать. Ну а в промежутке обработать пакет (собрать из кусков, проанализировать...). В статье же решалась проблема, когда пакет принят на одном MAC, а передать его надо на другом MAC — одно из решений использовать второй MCU (так как MAC один на контроллер, два очень редко и дорого). Есть еще другие решения — использовать внешний MAC (тут много способов).
                      Ну вот, а ниже MAC лежит PHY, вот у него-то и есть FD — но это совершенно все равно и не интересует, поскольку никак не сказывается на задаче…
                        –1
                        Задача стояла другая принять и отправить данные на скорости 100мбит/с:
                        Встала передо мной такая вот проблема — надо передавать данные между двумя микроконтроллерами STM32F407 хотя бы на скорости 100 Mbps. Можно было бы использовать Ethernet (MAC-to-MAC), но вот беда — он занят, именно из него и берутся эти данные…


                        Ethernet интерфейс с этим справляется.
                        Но вы, зачем-то, решили принимать по Ethernet, а отправлять собственно изобретённым велосипедом.
          +7
          Для скоростной передачи данных есть контроллеры c quad/octo-spi, необходимость которых определяется на этапе проектирования.
          Параллельный порт называется параллельным, потому что его можно использовать, внезапно, как параллельный. Вот только прерываний и флагов, необходимых для работы с данными у него обычно нет, соответственно и контроллер DMA с ним работать не сможет.
          Поэтому для реализации скоростных интерфейсов, например для связи с FPGA, и используются OCTO/QUAD SPI, позволяющие реализовать пропускную способность выше 100 мбит/с.
            0
            Вот может подскажете микроконтроллер stm32 c OCTO/QUAD SPI? Я вот думал использовать stm32H750VB…
              +2
              C quad-spi все просто, линейки stm32f46x/47x и линейки stm32f7/h7. С octo-spi сложнее (линейка на ядре L4+), у ST пока нет чипов с OSPI и ETH на одном кристалле, обещали сделать. QUAD-SPI должно быть достаточно.
              Кстати, в CoubMX есть удобный фильтр для подбора чипов.
                0
                Но как использовать QuadSpi для пересылки между контроллерами? Он ведь предназначен для работы с flash-памятью. Положим, нам надо отправить с mcu1 на mcu2 данные. Мы формируем пакет данных на mcu1 (ну пусть там добавятся адреса и т.д.). А что делать на стороне mcu2? Я вот как-то не соображу, как там быть — туда же придут данные как на flash, а он и не умеет с ними работать?
                  +1
                  Все очень просто, думайте о QSPI как об обычном spi с 4-мя параллельными шинами данных.
                    0
                    Не выходит — вот например в даташите на stm32h750vb написано:
                    The QUADSPI communicates with the Flash memory using commands. Each command
                    can include 5 phases: instruction, address, alternate byte, dummy, data. Any of these
                    phases can be configured to be skipped, but at least one of the instruction, address,
                    alternate byte, or data phase must be present.
                    То есть, я так понимаю, если отключить все ненужные фазы (ну например instruction, address, alternate byte) и ожидать приема данных, то что придет будет dummy+data — в непрерывном режиме данных наверно и можно принять…
                    Попробую (как раз есть stm32h750vb)… Но вот я тут подумал, что если для описанного в статье способа поднять частоту шины в 2 раза и уменьшить таймер до 2, то на 8 линиях данных мы получим… 800 Mbps, причем на том же железе за те же деньги, а если еще найти порт с 16 свободными пинами… И зачем тогда QuadSPI :)
                      0
                      Вы в статье размышляли об использовании eth для решения задачи, неужели отбросить лишний заголовок кадра для вас такая большая проблема?))
                      Конечно, вы можете есть кактус, если хотите.
                        0
                        Я вот ниже написал, ну не понимаю как на стороне slave это использовать? Не отключается же clock — он только на выход! (ну в stm32h750)
                      +1
                      И все равно не понимаю — у QuadSPI нет режима slave. Как он данные-то принимать будет? Он же в режиме чтения сначала пишет на линию, а затем читает… а как это синхронизировать с мастером? Мастер же тоже как-раз пишет на линию…
                      И кто будет тактовый сигнал генерировать?
                      0
                      разве что использовать indirect read/write моды (но не уверен, так как не имел еще опыта с QUAD SPI интерфейсом).
                        0
                        неполучается — смотри мой коммент ниже
                  0
                  В общем, проведенные тесты для stm32h750vb показали, что в режиме чтения QuadSPI гонит на выход тактовый сигнал, посылает адрес и пустой байт и затем читает данные. Никаким способом реализовать режим slave не удалось. Видимо, и остальные stm32 будут вести себя также… печаль…
                    +1
                    Мастером будет приёмный контроллер, слейв получается программный, да. У меня не было проблем со слейвом, так как в качестве него выступала FPGA, для которой было написано соответствующее ip-ядро.
                    Вообще у вас интересная задача. Вы получаете данные по eth, но, похоже, не имеете возможности обработать их на этом же камне. Поэтому пересылаете все в следующий МК. У вас данные требуют специфической обработки? Или просто скорости не хватает? Или одна из железок готова и нужно «расширить» её возможности?
                      0
                      Да, тут такая история — сначала был stm32f107 и он работал с двумя портами eth (по очереди) и реализовывал что-то типа прозрачной сетевой оболочки для конечного устройства (добавляя функционал)… но наступил этап роста и один камень сейчас я заменяю на два (по phy на mac), вот и потребовалась связь между ними (все же там 10/100 Mbps, ну в одну сторону поменьше все же).
                      ну и функционал растет и надо бы на один тип микроконтроллеров перейти (чувствую это все же будет stm32h750 — в одном месте мне надо сильно много вычислять...) для экономии. Ну и цену на все это бы понизить как-то…
                      Не могу пока придумать решение дешевле 2000 рублей — такой вот двухпортовый хаб с возможностью контроля всех пакетов…
                        0

                        Может быть посмотреть в сторону сетевых SoC вроде тех, что используют производители SOHO-роутеров?

                          0
                          Тут ведь какое дело — есть куча чипов 2 порта+ 1 порт на контроллер… и вроде бы недорогие. Но! это уже готовые роутеры vlan и никак не сделаешь фильтрацию и обработку (с подменой и синтезом) пакетов… А все остальное — ну есть вроде микроконтроллеры с ДВУМЯ MAC — но цена… заоблачная…
                          0
                          www.oldi.ru/catalog/element/0519569 не пойдет в качестве железа или сразу с ОС?
                            0
                            вот как раз с ОС и не надо… это устройство еще и много чего должно делать — например по CAN общатся. И стартует оно 100 миллисекунд (ибо промышленное)
                            +1
                            У микроконтроллеров dual ethernet не встречал. Ближайшее подобное есть у nuvoton — NUC980, чипы позиционируются для IoT, стоят в районе 5-7$ в партиях от 1000 шт, контрактная цена должна быть немного ниже.
                            Но это уже MPU, со всеми вытекающими.
                              0
                              ну вот да… так-то переходить без особой причины c Cortex-M не нужно :) Тут много причин…
                                +2
                                NXP такие делает.
                                  0
                                  Да, у меня даже лежат штук 10 50-х… вещь как-бы хорошая, но цена негуманная, и программировать его очень сложно — чего стоит только процедура загрузки… Но два eth — это два eth. В общем — из-за цены непрошло.
                                  0
                                  Можно взять Raspberry Pi, его можно запустить без Ос, как микроконтроллер. Где-то видел примеры.

                                  UPD: сорри, сморозил глупость, вспомнил что там только 1 порт, а у аналогов бывает несколько. Главное, выкинуть Ос, например, OpenWrt и писать на голом железе.
                                    0

                                    Вот только у малины нет двух Ethernet'ов

                          0

                          "Что не нравится при этом — ну нельзя никак запускать DMA от прерывания от входа GPIO, вот и приходится работать с таймерами. Может, кто-нибудь подскажет другой способ?"


                          На Cypress PSoC так получиться. И QSPI тоже есть, но нет ethernet (есть только MDIO (

                            0
                            Как выяснилось — qspi не катит :(
                            Ну и главное — без eth нет смысла…
                            0
                            Может посадить второй контроллер на клок от первого (mc01->BYPASS clock source) — принудительная синхронизация и попробовать читать дату с порта синхронно?
                            И кстати — на 100 Мb сеть я бы не расчитывал. В лучшем случае на 50-70.
                              0
                              ничего не выйдет — нужен именно механизм синхронного таймера — ну вот как в SPI, иначе никак не определить посылку — нужен сдвиг примерно в 0.5 такта.
                              А сеть да — обычно 40-60 Mbps. Ну так это еще и дуплекс, так что 80 должно хватить :)
                              +3
                              Ещё пару вариантов разной степени упоротости:

                              1. У STM32F407, насколько я понял из документации, бортовой USB не умеет HS, только FS. Зато у него есть интерфейс ULPI, который позволяет подключить внешний USB2.0 PHY. Я когда-то работал с ULPI. Конечно на этом камне ULPI интерфейсы воткнуть друг в друга не получится, как бы это красиво не выглядело, т.к. в ULPI именно PHY задаёт flow control, управляя ногами DIR и NEXT. С другой стороны сами эти PHY достаточно простые и дешёвые, они стоят менее 1.5$ (USB3300, например). Взять 2 PHY на каждый камень, соединить их друг с другом по USB и получить что-то около 480mbit/s. Теоретически даже не нужно будет поддерживать целиком интерфейс USB, т.е. дескрипторы и прочие пляски, т.е. сразу сырые данные кидать туда-сюда, но это нужно проверять. Тут и все прелести DMA можно будет использовать из коробки. С разводкой особых проблем быть не должно, ULPI это 12 ног на частоте 60Mhz и PHY друг с другом дифф.парой соединить.

                              2. Использовать staic memory controller. C помощью него STM32F407 умеет цеплять внешнюю память. Тут вариантов много.
                              a). Самый тупой способ. Берём микросхему двухпортовой SRAM памяти и цепляем на два проца. Двухпортовая память дороже обычной, но можно сэкономить на объёме, т.к. передача скорее всего планируется пакетная. Какая-нибудь ущербная 8-битная двухпортовая SRAM с доступом в 55ns даст что-то около 145mbit/s. По деньгам <9$ (71V30S, например), но можно искать ещё.
                              b). Если не хочется иметь дело с dual-port, то чисто теоретически можно одну SRAM память прицепить на 2 контроллера, если есть возможность делать нормальный tristate на управляющем порту проца. Это требует исследования. Зато память можно взять по-шустрее, шину по-больше и компенсировать тем самым все задержки переключения памяти от проца к процу. Единственное, с синхронизацией процесса передачи будет морока.
                              c). Что-то мне подсказывает, что теоретически к этому контроллеру можно подцепить даже аппаратное cmos asynchronous FIFO. Микросхемы малого объёма и скорости достаточно дёшевы <7$ (7201LA15JG, например).
                              d). Совсем обнаглеть и соединить два проца через эту шину напрямую. Это требует досконального понимания работы этого контроллера и его режимов. Но т.к. он умеет работать с NAND, который имеет флаг READY/BUSY, то теоретически возможность для flow control имеется и можно из проца в проц с помощью DMA гнать данные. Но это нужно крайне тщательно проверять.
                                0
                                Ну все варианты, кроме 2d :) — удорожание, так-то провода ведь бесплатны :).
                                А вот над 2d я думал (недолго, правда) — но так и не понял, как делать…
                                Есть и еще ньюансы — скорость будет со всеми фазами и их таймингами немного меньше (примерно до 42 Mbps), а вот пинов сожрет… 24+16+12 — ой-ой, вот столько у меня точно нет.
                                И главное — это всё конфликтует за пины с eth, а те неизменяемы…
                                Вообще у stm-ок очень не хватает мультиплексора линий все-на-все.
                                  0
                                  А что так много пинов для варианта 2d насчитали — адрес ведь там совсем не нужен? Да и шину данных можно попробовать 8-битной сделать, и шина управления — не 12 пин.
                                    0
                                    ну от адреса да — можно избавиться, но управление явно больше 6
                                0
                                1) Можно подцепить устройство, как внешнюю шину и для тактирования передачи использовать соответсвующие сигналы. DMA будет работать. Самый праивльный способ.
                                2) Можно извартиться с таймерами и так же использовать DMA.
                                  0
                                  можно поподробнее — как это как внешнюю шину? У stm32 нет никаких шин, к сожалению — в этом то все и дело!
                                  А с таймерами в статье и описано как…
                                  0
                                  Делал что-то подобное для считывания данных с АЦП. Кстати, заметил, что с некоторыми таймерами не завелось, моё предположение что GPIO и таймер должны сидеть на той же шине.
                                    0
                                    Но ведь таймеры (AHB) и порты (AHB1) всегда на разных шинах? У меня заводиться всегда, но при малых значениях ARR идет пропуск данных DMA — они повторяются сериями…
                                      0
                                      Да, посмотрел, шины разные. Может в чем-то другом косяк был, просто так в памяти отложилось, давно делал.
                                    0
                                    Что не нравится при этом — ну нельзя никак запускать DMA от прерывания от входа GPIO, вот и приходится работать с таймерами. Может, кто-нибудь подскажет другой способ?

                                    Таймер дергать через ETR/Capture, а уже таймер будет запускать DMA.
                                    А еще в H7 видел дополнительный слой управления DMA — DMAMUX2 и там есть триггеры EXTI0 и EXTI1.
                                      0
                                      Именно так и сделано. А вот насчет H7 я уже и сам думаю — по цене не сильно дороже выходит, только вот по току — надо проверить…
                                      0

                                      А MCU 2-ма ядрами не рассматриваете?

                                        0
                                        так мне надо два eth, а не два ядра. А таких очень мало и они очень дорогие…
                                        0
                                        Мне кажется что два слабеньких камня + обвязка — стоят дороже одного, но более шустрого.
                                          0
                                          А редактировать надо и входящие и выходящие из девайса пакеты? Если только одну сторону — то можно одним езернетом обойтись. RX в линию, а TX в девайс.

                                          Или можно вообще разделить контроль: один проц как написано выше, а второй так-же, только в обратную сторону. Тогда возможно траффик между процами можно будет сильно сократить.
                                            0
                                            в одну сторону, конечно, не получится… но что-то в этом есть!
                                            +1
                                            Хм, ну в пределах одного МК фаза не разъезжается и все работает. А дальше? а когда индуктивность земли постучится в дверь?
                                              +1
                                              Проверил на двух платах, соединенных проводками (вообще ужас и лапша) — все нормально. И вообще, я конечно следую всегда высокому искусству черной магии, но перебарщивать тоже не надо — когда у вас 10 Мгц и триггера Шмидта везде где только можно и нельзя — можно немного расслабится и получить удовольствие :)
                                                0
                                                Теоретически, возможен случай, когда фазы МК №1 и №2 разъедутся на 180 градусов? «Оверсемплинга» на реакцию совсем не остается, если тактовая 168МГц, а порты на 100МГц.
                                                А разъехаться она может через несколько часов, или может, дней.
                                                Имхо.
                                                  0
                                                  нет, это невозможно — надеюсь, я смог донести, что фазы отсчитываются каждый раз при новом выходном такте — а это 8 тактов TIM1 — то есть фазы разъедутся на 1/80 мксек максимум (60 градусов), а выборка происходит за 1/10 мксек (180 градусов). Другое дело, если DMA не дадут времени для считывания или записывания порта — тут, конечно, беда будет…
                                                    0
                                                    такты — тактами, но все синхронизируется от кварцев, PLL и далее по тексту. И если тактовые двух МК после делителей разъедутся в противофазу? Механизма состройки — нету, же.
                                                    Понимаю, что притянуто за уши, но палки стреляют, когда не ждешь
                                                      0
                                                      да нет, вы не так поняли систему — такты с выхода первого МК идут на вход таймера второго — так что разница не может превышать одного такта шины второго — а это 82 МГц… при тактах в 10 МГц
                                                        0
                                                        ну вот клок второго будет сдвинут и защелкнется на 1 такт позже (или раньше), т.е. может быть ситуация, что первый МК выдаст 8+8 бит, а второй защелкнет их как 9+7+случайный бит
                                                          +1
                                                          не-не… расстояние между моментами сэмплирования 8 тактов, так что смещение до 3 тактов — ни на что не влияет, а оно не может быть больше 1 такта (даже в противофазе). Гораздо важнее то, что после сэмплирования DMA не сможет взять данные — для этого и есть задержка до 2 тактов.
                                              0

                                              А почему нельзя просто взять внешний аппаратный MAC-контроллер? К примеру LAN9250

                                                0
                                                Можно и так, но:
                                                1. Цена сильно увеличивается — сравните LAN9250 — 500-600 рублей, а ksz8081 — 50-60 рублей, а их два…
                                                2. Та же проблема — как с ним работать? у него SPI & QSPI — в первом случае 42 Mbps, а второй случай — по скорости вроде годится, но у не у всех stm есть.
                                                А так да, хорошее решение… но дорогое
                                                  0

                                                  Не сравнивайте теплое с мягким. LAN9250 избавляет от необходимости ставить второй МК и городить весь этот кошмарный огород, так что сравнение цен некорректное.


                                                  не у всех stm есть.

                                                  Вы микроконтроллеры продвигаете или задачу решаете? МК выбирается под задачу, а не наоборот, выбирайте то, что решит вам задачу, а не создаст еще две.
                                                  Так может оказаться, что проще поставить какой-нибудь AMIC110 и сколотить микропрошивку на базе RTOS

                                                    0
                                                    Вот смотрите — решение на базе даже двух МК стоит мне в производстве 2100 рублей (с корпусом, а уж на базе одного — и вовсе 1700), а то же на базе LAN9250 — уже 2800. Вы понимаете, это как с EROI — если я могу продать по 2500, то даже супер решение но дороже хоть на рубль — не годится от слова совсем.
                                                    И с микроконтроллерами вы не правы — я потому и использую stm (и да, да, ещё и Cube!), что время разработки ПО для меня на новый камень менее дня — как бы требования не изменялись.
                                                    Я уж и не знаю, МК выбирают под задачу видимо в стране розовых пони, а на практике — что есть, то и используем. И важно, чтобы стоимость перехода ПО была минимальна — желательно 0 ;)
                                                      0

                                                      Я что-то не очень улавливаю: сколько в вашей схеме стоит один микроконтроллер? Включая его программирование.
                                                      По вашей арифметике MCU+PHY стоит 400 рублей. Что мало отличается от стоимости LAN9250, где в ход вступают просто договорные отношения, какую скидку под проект вы сможете выбить.


                                                      (и да, да, ещё и Cube!)

                                                      Ничего святого...

                                                        0
                                                        так ведь принятые пакеты надо еще и обрабатывать, так что без MCU никак не обойтись. А устройство таково, что нужен MCU с довольно богатым внутренним миром набором периферии. MCU+2хPHY стоит мне 350 рублей. а MCU+2xLAN — будет 1100 (примерно). Вот эта разница в 750 рублей это порог, отделяющий то что можно сделать от того, что можно продать… Приходится делать то, что можно продать…
                                                          0

                                                          В топике стояла задача "добавить еще один MAC-уровень в существующую систему". Вот вы берете свой STM32F407, и вторым интерфейсом ставите к нему LAN9250. Да, у вас линии получатся разные, но где в тексте написано требование, что они должны быть идентичны? Вы городите что-то вроде пограничного маршрутизатора, изолирующего два сегмента сети, "реальные" 100 мегабит там возможно и не нужны

                                                            0
                                                            Под влиянием нашего обсуждения я подумал, что можно же например KSZ8851M добавить вместо второго phy. Вот это уже даже удешевляет систему. А так у меня уже два MAC есть… система потребовала увеличения производительности (очень много математики) — и я сейчас перебираю решения.
                                                            Вот уже просматривается связка stm32h750+ksz8081+ksz8851M — а это всего 550-600 рублей, что очень здорово, если удастся сохранить 40-50 Mbps пропускной способности — надо проверять…
                                                0
                                                В STM32F750 для передачи данных между микроконтроллерами можно использовать SAI. SAI может работать на частоте выше частоты ядра, к примеру ядро — на 84МГц, а SAI — на 96 или даже 120МГц. Ему нужно всего 4 пина. А если пины заняты, или нужно снизить частоту — в F750 есть ещё и второй SAI. CubeMX не позволяет задать частоту MCLK 84МГц или 120МГц, но регистры вроде бы позволяют, неясно только, будет ли слэйв работать при таком соотношении тактовой частоты SAI и внешнего MCLK.
                                                  0
                                                  SAI — это последовательный интерфейс и он обычно объединен с SPI (с точки зрения сигналов это одно и то же — SCK + DATA). Так что лучше уж SPI — он и проще, можно сразу инициировать DMA и спокойно работать дальше. Но скорость SAI такая же — не выше 42 Mbps
                                                    0
                                                    SAI тактируется от независимого PLL. Поэтому непонятно, откуда ограничение в 42 Mbps. И SAI тоже работает с DMA
                                                      0
                                                      Вы понимаете, затактировать можно и от 256 МГц, но это значит, что у вас на пине будет SCK 256 МГц, что ну никак не может быть… На пине допустимо даже и 100 МГц, но стоимость разводки такой платы… я бы не взялся заставить работать такую шнягу…
                                                      Реально можно допускать 40-50 МГц, с помощью черной магии это можно заставить работать в серии. У меня в статье — всего 10 МГц, и то был справедливый комментарий о сложности с фронтами.
                                                        0
                                                        Для высоких частот всё зависит от длины линии. Если поставить контроллеры на расстоянии 5мм друг от друга, так, чтобы длина высокочастотных дорожек была 5..7 мм, и обеспечить неразрывный слой земли под ними с подключением к ближайшим выводам микроконтроллера — будет работать и на 120МГц. А если использовать 2 SAI — можно обойтись и 50 мегагерцами, тогда можно разнести микроконтроллеры и на 30 мм.
                                                          0
                                                          Но тогда закономерный вопрос — а зачем SAI, если есть SPI (129 Mbps)? Это одно и то же на физическом уровне, но в обработке SPI гораздо лучше.
                                                            0
                                                            Чтобы использовать индивидуальный PLL SAI, и не разгонять ядро и весь периферийный домен. Кроме того, частоту SAI можно выбирать с меньшим шагом.
                                                      0
                                                      Посмотрел — действительно, оба SAI тактируются ещё и от клока домена APB2. Непонятно, где внутри SAI проходит разграничение APB2 и собственной синхронизации.
                                                    0
                                                    -
                                                      0
                                                      P.S. В результате свежих экспериментов выяснилось, что поднятие частоты до 168 МГц закономерно увеличило скорость в 2 раза и данные передались за 14 мксек ( то есть 150 Mbps), а вот при уменьшении границы мастер-таймера ниже 7 начались глюки приемной стороны — не успевает таймер TIM8. При 7 еще работает, но при 6 — уже нет, а ведь это 200 Mbps было бы…

                                                      а надо смотреть на форму сигнала осцилографом, чтобы понятно было что такое искажение сигнала в длинной линии.
                                                      и 200Мгц на монтажке соплями это из области магии.
                                                        0
                                                        Вы видимо невнимательно прочитали — 200 Mbps это 25 Мгц.
                                                          0
                                                          ну да, параллельная шина. кстати в пиках аппаратный паралельный порт есть
                                                            0
                                                            А в стм — fsmc. и что?

                                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                      Самое читаемое