Es muy posible que la razón para usar DMA se encuentre en STM32 errata (el enlace es para la subfamilia stm32f101 / 103 de «alta densidad»), un documento tan fascinante como el propio manual de referencia. Básicamente, el periférico I2C está roto de muchas maneras interesantes. Uno de los elementos de errata (2.11.1) indica que ciertos eventos de hardware deben ser atendidos inmediatamente, o puede ocurrir algún tipo de condición de carrera de hardware:
Cuando los eventos EV7, EV7_1, EV6_1, EV6_3, EV2, EV8 y EV3 no son
administrado antes de que se transfiera el byte actual, los problemas pueden ser
encontrado como recibir un byte extra, leer los mismos datos
Dos veces o datos faltantes.
Básicamente, el funcionamiento correcto no está garantizado en todos los casos, a menos que I2C reciba el servicio de las interrupciones de mayor prioridad (Solución 2) o DMA (Solución 1). Ahora, si lo estoy leyendo correctamente, una simple transferencia encuestada con todas las interrupciones deshabilitadas también funcionaría, pero eso va en contra de toda la filosofía de diseño de Cortex-M (la concurrencia sale por la ventana). Si se usa un RTOS preventivo, es aún peor.
Dicho esto, varias personas tienen a I2C trabajando en los modos de encuesta e interrupción sin seguir estrictamente las recomendaciones de errata y sin problemas aparentes. Sin embargo, esto no puede tomarse como una indicación de que un problema nunca ocurrirá, por supuesto. Si va a implementar su propio controlador I2C, le recomiendo que maneje no solo todas las posibles condiciones de error indicadas por el periférico, sino también los tiempos de espera. Si ocurre un error o se agota el tiempo de espera, asegúrese de enviar una PARADA (para reiniciar los esclavos) y reiniciar el controlador tal como se documenta en el manual. Recibir datos erróneos de esclavos también es una posibilidad en la que deberías pensar. Puede encontrar muchas discusiones sobre este problema en los foros de ST y en otros lugares.