Endianess en la salida STM32F4 FSMC

Actualmente estoy configurando un STM32F407 para evaluar un módulo de pantalla que utiliza un controlador de pantalla Renesas R61526A.

Pude configurar el proyecto usando CubeMX sin problemas, y el FSMC parece estar funcionando.

Sin embargo, noté que la palabra de datos de salida era big endian, pero estoy bastante seguro de que todos los STM32 son little endian (uint16_t 0x51ab como variable se convierte en 0xab51 cuando se monitorea la salida D0-16 con el osciloscopio). No esperaba que la FSMC cambiara el orden de los bytes en la salida.

#define LCDADDRESS 0x63FFF00F
const LCDmemorymapping LCDRWregisteraccess = (uint16_t*) LCDADDRESS;
static void writetoLCD(uint16_t dataword)
{
    *LCDRWregisteraccess= (uint16_t) dataword;
}

static uint16_t readfromLCD(uint16_t unused)
{
    return  (uint16_t) *LCDRWregisteraccess;
}


/* FSMC initialization function */
static void MX_FSMC_Init(void)
{
  FSMC_NORSRAM_TimingTypeDef Timing;

  /** Perform the SRAM1 memory initialization sequence
  */
  hsram1.Instance = FSMC_NORSRAM_DEVICE;
  hsram1.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
  /* hsram1.Init */
  hsram1.Init.NSBank = FSMC_NORSRAM_BANK1;
  hsram1.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
  hsram1.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
  hsram1.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
  hsram1.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
  hsram1.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
  hsram1.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
  hsram1.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
  hsram1.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
  hsram1.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
  hsram1.Init.ExtendedMode = FSMC_EXTENDED_MODE_DISABLE;
  hsram1.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
  hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
  hsram1.Init.PageSize = FSMC_PAGE_SIZE_NONE;
  /* Timing */
  Timing.AddressSetupTime = 3;
  Timing.AddressHoldTime = 15;
  Timing.DataSetupTime = 8;
  Timing.BusTurnAroundDuration = 3;
  Timing.CLKDivision = 16;
  Timing.DataLatency = 17;
  Timing.AccessMode = FSMC_ACCESS_MODE_A;
  /* ExtTiming */

  if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

Me gustaría que la salida también fuera little-endian, entonces, ¿estoy haciendo algo obviamente mal? La solución obvia sería leer/escribir los datos como

*LCDRWregisteraccess= (uint16_t)((0xff00&dataword)>>8)|(0x00ff&dataword<<8));

o simplemente usar la instrucción REV16, pero me preguntaba si hay una configuración dentro del FSMC que me falta o si estoy haciendo algo mal.

Además, esta es mi primera pregunta de intercambio de pila, por lo que si no formulé la pregunta correctamente, no dude en señalarlo :)

¡Muchas gracias de antemano!

No está claro lo que está preguntando aquí. ¿Qué esperaba que sucediera y cómo se desvía el comportamiento real de esa expectativa? Por ejemplo, ¿apareció el MSB de los datos en la línea D15 o en la línea D0?
Esperaba que la salida tuviera el mismo nivel de bits y bytes que la variable (debido a que STM32 es little-endian, esperaba que la salida fuera la misma). Con respecto a su pregunta, el MSB estaba representado en la línea D7. El LSB en el D8 y así sucesivamente. La solución simple sería usar la instrucción REV16, pero tenía curiosidad por saber por qué el sistema se comporta de esa manera. Voy a tratar de aclarar la pregunta, Gracias.
Entonces, para que quede perfectamente claro, está viendo el MSB en la línea D0.
No, el MSB se puede ver en la línea D7. Si los datos que se sacarán del bus serían 0xC000, serán visibles como 0x00C0 en el bus. Se conmutan el byte superior y el inferior. El orden de bits dentro de los bytes reales no se ve afectado.
Está escribiendo en una dirección impar (0x63FFF00F) usando 16 bits. Eso podría explicar el sorprendente resultado.
Supongo que vale la pena verificar dos veces para ver cuál es realmente el orden de bytes en la memoria; está definida por la implementación. Puede leerlo desde 0xE000ED0C bit 15. 0 es LE, 1 es BE

Respuestas (1)

Está escribiendo en una dirección impar (0x63FFF00F) usando 16 bits. Eso podría explicar el sorprendente resultado. – Code

Codo estaba en lo cierto. Acceder a bytes impares mientras la FSMC estaba configurada para palabras de datos de 16 bits hizo que hiciera un doble acceso (2 operaciones de escritura) con los bytes exactamente en el orden incorrecto.

Mis direcciones ahora son:

#define LCD_CMD 0x60030000
#define LCD_DATA 0x60000000