Программный I2C - это минус один таймер и один канал DMA (да еще и
приличный буфер в ОЗУ надо выделять). Либо придется делать
блокирующий, что для пересылки больше, чем одного байта, на малых
скоростях как-то не очень. Но, в принципе, согласен: мелкие посылки
можно и блокирующими делать, ничего страшного не произойдет, если
на 100кбод десяток байт перешлешь. У "монстра" плата - изначально четырехслойка. У меня - тоже четырехслойка: https://github.com/eddyem/stm32samples/tree/master/F3%3AF303/Multistepper
Оригинальный "MKS monster" в нашем случае использовать было бы невозможно в виду специфики (крутить-то не двигатели станка, а независимые шаговики, причем, нужно в любой момент быть готовым узнать текущее положение, сколько шагов до концевика и т.п.), так что, прошивку по-любому бы пришлось писать. Вот, заодно и плату развел, чтобы вменяемо все подключалось. Если STEP генерить таймерами, намного лучше получается, т.к. микрошаги на постоянной скорости расположены строго через равные промежутки времени, а не как в случае с программным управлением, когда на осциллограмму смотришь, а там черт знает что творится (особенно при активном параллельном обмене по USB и т.п. с более высокими приоритетами прерываний). Скорости, понятное дело, маленькие (5000 шагов в секунду соответствует примерно 150кГц), но когда у тебя этих движков аж восемь, лучше всего по-максимуму ограничить все эти программные штучки.
Кстати, а что там за "забаженные варианты у STM"? Если руководствоваться эрратой, все ОК. Понятно, что у 103 очень много ограничений, но работает же...