Из незадействованной периферии есть разве что 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 было бы…
Комментарии (83)
Griboks
21.07.2019 10:11«Можно было бы использовать Ethernet (MAC-to-MAC), но вот беда — он занят, именно из него и берутся эти данные…»
А он разве симплексный? Сетевой адаптер разве не может одновременно передавать и получать данные? А данные не могут идти сразу на нужное устройство?oam2oam Автор
21.07.2019 10:26+1Ethernet конечно, дуплекс. Но тут требуется получить пакет из Phy и его обработать, а затем передать на другой контроллер (идет борьба за стоимость :)
nevzorofff
21.07.2019 22:38А при вашем способе передачи его «обработать» не надо?
oam2oam Автор
22.07.2019 07:32не понял ваш вопрос. Я и написал, что надо обработать, а сетевой адаптер просто передаст данные.
nevzorofff
22.07.2019 21:27Ну на FD интерфейсе ничто не мешает данные принять, обработать и отдать, лишь бы проц «обработку» потянул.
oam2oam Автор
23.07.2019 08:33а что это — FD интерфейс и где он?
nevzorofff
23.07.2019 17:54-1Режим Full Duplex у Ethernet, позволяет одновременно данные и принимать и отправлять.
oam2oam Автор
23.07.2019 18:01У микроконтроллера нет никакого FD, а есть MAC, все пляски тут и происходят — MAC принимает данные, использует выделенный DMA, записывает их в цепочку блоков данных и затем устанавливает прерывание. То же и для отправки (в обратном порядке) надо сделать. Ну а в промежутке обработать пакет (собрать из кусков, проанализировать...). В статье же решалась проблема, когда пакет принят на одном MAC, а передать его надо на другом MAC — одно из решений использовать второй MCU (так как MAC один на контроллер, два очень редко и дорого). Есть еще другие решения — использовать внешний MAC (тут много способов).
Ну вот, а ниже MAC лежит PHY, вот у него-то и есть FD — но это совершенно все равно и не интересует, поскольку никак не сказывается на задаче…nevzorofff
23.07.2019 20:02-1Задача стояла другая принять и отправить данные на скорости 100мбит/с:
Встала передо мной такая вот проблема — надо передавать данные между двумя микроконтроллерами STM32F407 хотя бы на скорости 100 Mbps. Можно было бы использовать Ethernet (MAC-to-MAC), но вот беда — он занят, именно из него и берутся эти данные…
Ethernet интерфейс с этим справляется.
Но вы, зачем-то, решили принимать по Ethernet, а отправлять собственно изобретённым велосипедом.
evgeniy1294
21.07.2019 10:27+6Для скоростной передачи данных есть контроллеры c quad/octo-spi, необходимость которых определяется на этапе проектирования.
Параллельный порт называется параллельным, потому что его можно использовать, внезапно, как параллельный. Вот только прерываний и флагов, необходимых для работы с данными у него обычно нет, соответственно и контроллер DMA с ним работать не сможет.
Поэтому для реализации скоростных интерфейсов, например для связи с FPGA, и используются OCTO/QUAD SPI, позволяющие реализовать пропускную способность выше 100 мбит/с.oam2oam Автор
21.07.2019 10:28Вот может подскажете микроконтроллер stm32 c OCTO/QUAD SPI? Я вот думал использовать stm32H750VB…
evgeniy1294
21.07.2019 10:35+2C quad-spi все просто, линейки stm32f46x/47x и линейки stm32f7/h7. С octo-spi сложнее (линейка на ядре L4+), у ST пока нет чипов с OSPI и ETH на одном кристалле, обещали сделать. QUAD-SPI должно быть достаточно.
Кстати, в CoubMX есть удобный фильтр для подбора чипов.oam2oam Автор
21.07.2019 10:41Но как использовать QuadSpi для пересылки между контроллерами? Он ведь предназначен для работы с flash-памятью. Положим, нам надо отправить с mcu1 на mcu2 данные. Мы формируем пакет данных на mcu1 (ну пусть там добавятся адреса и т.д.). А что делать на стороне mcu2? Я вот как-то не соображу, как там быть — туда же придут данные как на flash, а он и не умеет с ними работать?
evgeniy1294
21.07.2019 10:47+1Все очень просто, думайте о QSPI как об обычном spi с 4-мя параллельными шинами данных.
oam2oam Автор
21.07.2019 10:53Не выходит — вот например в даташите на 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 :)evgeniy1294
21.07.2019 11:02Вы в статье размышляли об использовании eth для решения задачи, неужели отбросить лишний заголовок кадра для вас такая большая проблема?))
Конечно, вы можете есть кактус, если хотите.oam2oam Автор
21.07.2019 11:04Я вот ниже написал, ну не понимаю как на стороне slave это использовать? Не отключается же clock — он только на выход! (ну в stm32h750)
oam2oam Автор
21.07.2019 10:57+1И все равно не понимаю — у QuadSPI нет режима slave. Как он данные-то принимать будет? Он же в режиме чтения сначала пишет на линию, а затем читает… а как это синхронизировать с мастером? Мастер же тоже как-раз пишет на линию…
И кто будет тактовый сигнал генерировать?
besitzeruf
21.07.2019 12:22разве что использовать indirect read/write моды (но не уверен, так как не имел еще опыта с QUAD SPI интерфейсом).
oam2oam Автор
21.07.2019 11:10В общем, проведенные тесты для stm32h750vb показали, что в режиме чтения QuadSPI гонит на выход тактовый сигнал, посылает адрес и пустой байт и затем читает данные. Никаким способом реализовать режим slave не удалось. Видимо, и остальные stm32 будут вести себя также… печаль…
evgeniy1294
21.07.2019 11:30+1Мастером будет приёмный контроллер, слейв получается программный, да. У меня не было проблем со слейвом, так как в качестве него выступала FPGA, для которой было написано соответствующее ip-ядро.
Вообще у вас интересная задача. Вы получаете данные по eth, но, похоже, не имеете возможности обработать их на этом же камне. Поэтому пересылаете все в следующий МК. У вас данные требуют специфической обработки? Или просто скорости не хватает? Или одна из железок готова и нужно «расширить» её возможности?oam2oam Автор
21.07.2019 11:52Да, тут такая история — сначала был stm32f107 и он работал с двумя портами eth (по очереди) и реализовывал что-то типа прозрачной сетевой оболочки для конечного устройства (добавляя функционал)… но наступил этап роста и один камень сейчас я заменяю на два (по phy на mac), вот и потребовалась связь между ними (все же там 10/100 Mbps, ну в одну сторону поменьше все же).
ну и функционал растет и надо бы на один тип микроконтроллеров перейти (чувствую это все же будет stm32h750 — в одном месте мне надо сильно много вычислять...) для экономии. Ну и цену на все это бы понизить как-то…
Не могу пока придумать решение дешевле 2000 рублей — такой вот двухпортовый хаб с возможностью контроля всех пакетов…Kitsok
21.07.2019 12:55Может быть посмотреть в сторону сетевых SoC вроде тех, что используют производители SOHO-роутеров?
oam2oam Автор
21.07.2019 13:00Тут ведь какое дело — есть куча чипов 2 порта+ 1 порт на контроллер… и вроде бы недорогие. Но! это уже готовые роутеры vlan и никак не сделаешь фильтрацию и обработку (с подменой и синтезом) пакетов… А все остальное — ну есть вроде микроконтроллеры с ДВУМЯ MAC — но цена… заоблачная…
Ivanii
21.07.2019 12:57www.oldi.ru/catalog/element/0519569 не пойдет в качестве железа или сразу с ОС?
oam2oam Автор
21.07.2019 13:01вот как раз с ОС и не надо… это устройство еще и много чего должно делать — например по CAN общатся. И стартует оно 100 миллисекунд (ибо промышленное)
evgeniy1294
21.07.2019 12:59+1У микроконтроллеров dual ethernet не встречал. Ближайшее подобное есть у nuvoton — NUC980, чипы позиционируются для IoT, стоят в районе 5-7$ в партиях от 1000 шт, контрактная цена должна быть немного ниже.
Но это уже MPU, со всеми вытекающими.oam2oam Автор
21.07.2019 13:02ну вот да… так-то переходить без особой причины c Cortex-M не нужно :) Тут много причин…
predator86
21.07.2019 17:20+2NXP такие делает.
oam2oam Автор
21.07.2019 17:22Да, у меня даже лежат штук 10 50-х… вещь как-бы хорошая, но цена негуманная, и программировать его очень сложно — чего стоит только процедура загрузки… Но два eth — это два eth. В общем — из-за цены непрошло.
semen-pro
22.07.2019 16:34Можно взять Raspberry Pi, его можно запустить без Ос, как микроконтроллер. Где-то видел примеры.
UPD: сорри, сморозил глупость, вспомнил что там только 1 порт, а у аналогов бывает несколько. Главное, выкинуть Ос, например, OpenWrt и писать на голом железе.
SadAngel
21.07.2019 13:20"Что не нравится при этом — ну нельзя никак запускать DMA от прерывания от входа GPIO, вот и приходится работать с таймерами. Может, кто-нибудь подскажет другой способ?"
На Cypress PSoC так получиться. И QSPI тоже есть, но нет ethernet (есть только MDIO (
Sdima1357
21.07.2019 13:51Может посадить второй контроллер на клок от первого (mc01->BYPASS clock source) — принудительная синхронизация и попробовать читать дату с порта синхронно?
И кстати — на 100 Мb сеть я бы не расчитывал. В лучшем случае на 50-70.oam2oam Автор
21.07.2019 14:26ничего не выйдет — нужен именно механизм синхронного таймера — ну вот как в SPI, иначе никак не определить посылку — нужен сдвиг примерно в 0.5 такта.
А сеть да — обычно 40-60 Mbps. Ну так это еще и дуплекс, так что 80 должно хватить :)
Inanity
21.07.2019 14:39+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 гнать данные. Но это нужно крайне тщательно проверять.oam2oam Автор
21.07.2019 14:49Ну все варианты, кроме 2d :) — удорожание, так-то провода ведь бесплатны :).
А вот над 2d я думал (недолго, правда) — но так и не понял, как делать…
Есть и еще ньюансы — скорость будет со всеми фазами и их таймингами немного меньше (примерно до 42 Mbps), а вот пинов сожрет… 24+16+12 — ой-ой, вот столько у меня точно нет.
И главное — это всё конфликтует за пины с eth, а те неизменяемы…
Вообще у stm-ок очень не хватает мультиплексора линий все-на-все.
Sap_ru
21.07.2019 16:151) Можно подцепить устройство, как внешнюю шину и для тактирования передачи использовать соответсвующие сигналы. DMA будет работать. Самый праивльный способ.
2) Можно извартиться с таймерами и так же использовать DMA.oam2oam Автор
21.07.2019 16:18можно поподробнее — как это как внешнюю шину? У stm32 нет никаких шин, к сожалению — в этом то все и дело!
А с таймерами в статье и описано как…
Firelander
21.07.2019 16:18Делал что-то подобное для считывания данных с АЦП. Кстати, заметил, что с некоторыми таймерами не завелось, моё предположение что GPIO и таймер должны сидеть на той же шине.
oam2oam Автор
21.07.2019 16:28Но ведь таймеры (AHB) и порты (AHB1) всегда на разных шинах? У меня заводиться всегда, но при малых значениях ARR идет пропуск данных DMA — они повторяются сериями…
Firelander
21.07.2019 16:39Да, посмотрел, шины разные. Может в чем-то другом косяк был, просто так в памяти отложилось, давно делал.
hardegor
21.07.2019 19:48Что не нравится при этом — ну нельзя никак запускать DMA от прерывания от входа GPIO, вот и приходится работать с таймерами. Может, кто-нибудь подскажет другой способ?
Таймер дергать через ETR/Capture, а уже таймер будет запускать DMA.
А еще в H7 видел дополнительный слой управления DMA — DMAMUX2 и там есть триггеры EXTI0 и EXTI1.oam2oam Автор
21.07.2019 21:15Именно так и сделано. А вот насчет H7 я уже и сам думаю — по цене не сильно дороже выходит, только вот по току — надо проверить…
AVI-crak
21.07.2019 21:23Мне кажется что два слабеньких камня + обвязка — стоят дороже одного, но более шустрого.
Fox_Alex
21.07.2019 22:30А редактировать надо и входящие и выходящие из девайса пакеты? Если только одну сторону — то можно одним езернетом обойтись. RX в линию, а TX в девайс.
Или можно вообще разделить контроль: один проц как написано выше, а второй так-же, только в обратную сторону. Тогда возможно траффик между процами можно будет сильно сократить.
IgorPie
22.07.2019 00:05+1Хм, ну в пределах одного МК фаза не разъезжается и все работает. А дальше? а когда индуктивность земли постучится в дверь?
oam2oam Автор
22.07.2019 07:35+1Проверил на двух платах, соединенных проводками (вообще ужас и лапша) — все нормально. И вообще, я конечно следую всегда высокому искусству черной магии, но перебарщивать тоже не надо — когда у вас 10 Мгц и триггера Шмидта везде где только можно и нельзя — можно немного расслабится и получить удовольствие :)
IgorPie
22.07.2019 17:16Теоретически, возможен случай, когда фазы МК №1 и №2 разъедутся на 180 градусов? «Оверсемплинга» на реакцию совсем не остается, если тактовая 168МГц, а порты на 100МГц.
А разъехаться она может через несколько часов, или может, дней.
Имхо.oam2oam Автор
22.07.2019 17:22нет, это невозможно — надеюсь, я смог донести, что фазы отсчитываются каждый раз при новом выходном такте — а это 8 тактов TIM1 — то есть фазы разъедутся на 1/80 мксек максимум (60 градусов), а выборка происходит за 1/10 мксек (180 градусов). Другое дело, если DMA не дадут времени для считывания или записывания порта — тут, конечно, беда будет…
IgorPie
22.07.2019 19:55такты — тактами, но все синхронизируется от кварцев, PLL и далее по тексту. И если тактовые двух МК после делителей разъедутся в противофазу? Механизма состройки — нету, же.
Понимаю, что притянуто за уши, но палки стреляют, когда не ждешьoam2oam Автор
22.07.2019 20:33да нет, вы не так поняли систему — такты с выхода первого МК идут на вход таймера второго — так что разница не может превышать одного такта шины второго — а это 82 МГц… при тактах в 10 МГц
IgorPie
22.07.2019 21:07ну вот клок второго будет сдвинут и защелкнется на 1 такт позже (или раньше), т.е. может быть ситуация, что первый МК выдаст 8+8 бит, а второй защелкнет их как 9+7+случайный бит
oam2oam Автор
22.07.2019 21:11+1не-не… расстояние между моментами сэмплирования 8 тактов, так что смещение до 3 тактов — ни на что не влияет, а оно не может быть больше 1 такта (даже в противофазе). Гораздо важнее то, что после сэмплирования DMA не сможет взять данные — для этого и есть задержка до 2 тактов.
Dima_Sharihin
22.07.2019 11:47А почему нельзя просто взять внешний аппаратный MAC-контроллер? К примеру LAN9250
oam2oam Автор
22.07.2019 12:57Можно и так, но:
1. Цена сильно увеличивается — сравните LAN9250 — 500-600 рублей, а ksz8081 — 50-60 рублей, а их два…
2. Та же проблема — как с ним работать? у него SPI & QSPI — в первом случае 42 Mbps, а второй случай — по скорости вроде годится, но у не у всех stm есть.
А так да, хорошее решение… но дорогоеDima_Sharihin
22.07.2019 13:05Не сравнивайте теплое с мягким. LAN9250 избавляет от необходимости ставить второй МК и городить весь этот кошмарный огород, так что сравнение цен некорректное.
не у всех stm есть.
Вы микроконтроллеры продвигаете или задачу решаете? МК выбирается под задачу, а не наоборот, выбирайте то, что решит вам задачу, а не создаст еще две.
Так может оказаться, что проще поставить какой-нибудь AMIC110 и сколотить микропрошивку на базе RTOSoam2oam Автор
22.07.2019 13:12Вот смотрите — решение на базе даже двух МК стоит мне в производстве 2100 рублей (с корпусом, а уж на базе одного — и вовсе 1700), а то же на базе LAN9250 — уже 2800. Вы понимаете, это как с EROI — если я могу продать по 2500, то даже супер решение но дороже хоть на рубль — не годится от слова совсем.
И с микроконтроллерами вы не правы — я потому и использую stm (и да, да, ещё и Cube!), что время разработки ПО для меня на новый камень менее дня — как бы требования не изменялись.
Я уж и не знаю, МК выбирают под задачу видимо в стране розовых пони, а на практике — что есть, то и используем. И важно, чтобы стоимость перехода ПО была минимальна — желательно 0 ;)Dima_Sharihin
22.07.2019 13:22Я что-то не очень улавливаю: сколько в вашей схеме стоит один микроконтроллер? Включая его программирование.
По вашей арифметике MCU+PHY стоит 400 рублей. Что мало отличается от стоимости LAN9250, где в ход вступают просто договорные отношения, какую скидку под проект вы сможете выбить.
(и да, да, ещё и Cube!)
Ничего святого...
oam2oam Автор
22.07.2019 13:26так ведь принятые пакеты надо еще и обрабатывать, так что без MCU никак не обойтись. А устройство таково, что нужен MCU с довольно богатым
внутренним миромнабором периферии. MCU+2хPHY стоит мне 350 рублей. а MCU+2xLAN — будет 1100 (примерно). Вот эта разница в 750 рублей это порог, отделяющий то что можно сделать от того, что можно продать… Приходится делать то, что можно продать…Dima_Sharihin
22.07.2019 13:33В топике стояла задача "добавить еще один MAC-уровень в существующую систему". Вот вы берете свой STM32F407, и вторым интерфейсом ставите к нему LAN9250. Да, у вас линии получатся разные, но где в тексте написано требование, что они должны быть идентичны? Вы городите что-то вроде пограничного маршрутизатора, изолирующего два сегмента сети, "реальные" 100 мегабит там возможно и не нужны
oam2oam Автор
22.07.2019 13:38Под влиянием нашего обсуждения я подумал, что можно же например KSZ8851M добавить вместо второго phy. Вот это уже даже удешевляет систему. А так у меня уже два MAC есть… система потребовала увеличения производительности (очень много математики) — и я сейчас перебираю решения.
Вот уже просматривается связка stm32h750+ksz8081+ksz8851M — а это всего 550-600 рублей, что очень здорово, если удастся сохранить 40-50 Mbps пропускной способности — надо проверять…
Sun-ami
22.07.2019 12:14В STM32F750 для передачи данных между микроконтроллерами можно использовать SAI. SAI может работать на частоте выше частоты ядра, к примеру ядро — на 84МГц, а SAI — на 96 или даже 120МГц. Ему нужно всего 4 пина. А если пины заняты, или нужно снизить частоту — в F750 есть ещё и второй SAI. CubeMX не позволяет задать частоту MCLK 84МГц или 120МГц, но регистры вроде бы позволяют, неясно только, будет ли слэйв работать при таком соотношении тактовой частоты SAI и внешнего MCLK.
oam2oam Автор
22.07.2019 12:59SAI — это последовательный интерфейс и он обычно объединен с SPI (с точки зрения сигналов это одно и то же — SCK + DATA). Так что лучше уж SPI — он и проще, можно сразу инициировать DMA и спокойно работать дальше. Но скорость SAI такая же — не выше 42 Mbps
Sun-ami
22.07.2019 13:34SAI тактируется от независимого PLL. Поэтому непонятно, откуда ограничение в 42 Mbps. И SAI тоже работает с DMA
oam2oam Автор
22.07.2019 13:45Вы понимаете, затактировать можно и от 256 МГц, но это значит, что у вас на пине будет SCK 256 МГц, что ну никак не может быть… На пине допустимо даже и 100 МГц, но стоимость разводки такой платы… я бы не взялся заставить работать такую шнягу…
Реально можно допускать 40-50 МГц, с помощью черной магии это можно заставить работать в серии. У меня в статье — всего 10 МГц, и то был справедливый комментарий о сложности с фронтами.Sun-ami
22.07.2019 13:51Для высоких частот всё зависит от длины линии. Если поставить контроллеры на расстоянии 5мм друг от друга, так, чтобы длина высокочастотных дорожек была 5..7 мм, и обеспечить неразрывный слой земли под ними с подключением к ближайшим выводам микроконтроллера — будет работать и на 120МГц. А если использовать 2 SAI — можно обойтись и 50 мегагерцами, тогда можно разнести микроконтроллеры и на 30 мм.
oam2oam Автор
22.07.2019 13:53Но тогда закономерный вопрос — а зачем SAI, если есть SPI (129 Mbps)? Это одно и то же на физическом уровне, но в обработке SPI гораздо лучше.
Sun-ami
22.07.2019 13:59Чтобы использовать индивидуальный PLL SAI, и не разгонять ядро и весь периферийный домен. Кроме того, частоту SAI можно выбирать с меньшим шагом.
Sun-ami
22.07.2019 13:55Посмотрел — действительно, оба SAI тактируются ещё и от клока домена APB2. Непонятно, где внутри SAI проходит разграничение APB2 и собственной синхронизации.
siargy
24.07.2019 13:24P.S. В результате свежих экспериментов выяснилось, что поднятие частоты до 168 МГц закономерно увеличило скорость в 2 раза и данные передались за 14 мксек ( то есть 150 Mbps), а вот при уменьшении границы мастер-таймера ниже 7 начались глюки приемной стороны — не успевает таймер TIM8. При 7 еще работает, но при 6 — уже нет, а ведь это 200 Mbps было бы…
а надо смотреть на форму сигнала осцилографом, чтобы понятно было что такое искажение сигнала в длинной линии.
и 200Мгц на монтажке соплями это из области магии.
besitzeruf
Нк раз такой велосипед изобрелся, то спрошу: не проще ли будет использовать 2+ SPI на максимальной скорости (один для первой половины, второй для второй половины данных)? Пинов отнимите в идеале 6 и еще прием организовать сможете.
oam2oam Автор
Я так и попробовал вначале — но вот незадача, я могу только SPI1 и SPI3 использовать, тут, во-первых SPI3 только 24 Mbps дает, да и то при 168 МГц, ну и во-вторых, разводка все-же усложняется. А вот пинов хватает, аж остается… Так что такой подход вполне себе жизнеспособен, я думаю. К тому же остается запас по скорости — тут можно и поднять ее хотя бы в 2 раза…