STM32F10x SPI - Sin reloj

Estoy tratando de hacer que la operación SPI básica funcione en un chip STM32F107VC usando la placa de desarrollo WaveShare Port107. Estoy tratando de inicializar SPI1 que reside en PA4-PA7.
Estoy intentando una prueba de bucle invertido simple, por lo que MISO está conectado directamente a MOSI. También he adjuntado un osciloscopio a NSS y SCK.

A continuación se muestra mi código:

// Clock configuration
RCC->APB2ENR |= 1;              // Alternate Function Clock Enable
RCC->APB2ENR |= 1<<2;           // Enable clock to Port A.
RCC->APB2ENR |= 1<<12;          // Enable clock for SPI1.

// Pin configuration (no remapping)
// Output = AF PushPull 50MHz. 
// Input = Active Pullup/Pulldown
// I have tried NSS as AFPuP, Active Pullup/Pulldown, GPIO output etc...
// NSS (PA4) = input, CLK (PA5) = output, MISO (PA6) = input, MOSI (PA7) = output
GPIOA->CRL = 0xB8B80000;

// General SPI configuration
SPI1->CR1 = 0;
SPI1->CR1 |= 7<<3;                  // Lowest frequency.    
SPI1->CR1 &= ~(1<<0);               // Clock phase. 1st clock transition starts data capture
SPI1->CR1 |= 1<<1;                  // Clock polarity. High when idle.
SPI1->CR1 &= ~(1<<11);              // Use 8 bit data
SPI1->CR1 |= 1<<7;                  // LSB transmitted first.
//SPI1->CR1 |= 1<<9;                // Software slave management
//SPI1->CR1 |= 1<<8                 // Software NSS bit high
SPI1->CR1 |= 1<<2;                  // Master device.
SPI1->CR1 &= ~(1<<10);              // Use both RX and TX
SPI1->CR1 &= ~(3<<12);              // No CRC
SPI1->CR1 &= ~(1<<15);              // 2-line unidirectional mode
SPI1->CR2 = 0;                      // Polling mode (no interrupts)
SPI1->CR1 |= 1<<6;                  // Enable SPI1.

Ahora, para realizar la prueba de loopback, envío un byte, luego leo el byte (lo configuré para usar un registro de desplazamiento de 8 bits).

void loopback(unsigned char byte)
{
    GPIOA->BSRR &= ~(1<<4); // !NSS line set to low (active) state. I have
                            // also attempted to use GPIOA->ODR and
                            // also attempted software NSS mode.
    //  while ((SPI1->SR & (1 << 7)) != 0 );    // Wait for BUSY to clear. not using.
    while (!(SPI1->SR & (1 << 1))); // Wait TXE (Transmit buffer empty)
    SPI1->DR = byte;

    // read it back
    unsigned char readByte = ReadByte();

    if (byte == readByte)
    {
         // ... Test passed!
    }
    GPIOA->BSRR |= 1<<4;     //!NSS set high. (unactive state).
}

unsigned char ReadByte(void)
{
    while (!(SPI1->SR & (1 << 0))); // Wait RXNE (Receive not empty (we have data))
    unsigned char readByte = SPI1->DR;
    return readByte;
}

Monitoreando CLK y NSS (y MISO/MOSI) con un osciloscopio, cuando NSS pasa a su estado bajo activo, no oscila ninguna línea de reloj. Incluso si hay una transmisión que intenta ocurrir, los bits se establecen en el registro de datos, pero no creo que estén siendo expulsados ​​​​de DR porque RXNE nunca sube (lo que tiene sentido porque no hay una línea de reloj activa).

¿Alguien podría indicarme por qué la línea clk nunca oscila? ¿Está mal mi configuración?

Saludos

Sus configuraciones son muy difíciles de leer. ¿ Por qué no utiliza la biblioteca de periféricos estándar ? Debería haber algunas buenas descripciones en los archivos fuente sobre cómo configurar las cosas.
Sus configuraciones son fáciles de leer porque no oscurecen las cosas como lo hacen las funciones de la biblioteca. Pero el uso de alias para números de bits mejoraría la legibilidad y la portabilidad.
¿Por qué se configura NSS como entrada?
@venny Configuré NSS como entrada y también como salida push-pull AF, ambas configuraciones no funcionaron.
También usaré alias para los números pin, gracias por el consejo.

Respuestas (1)

Quite el comentario de las líneas que permiten que SSM (CR1 bit 9) use la selección manual de esclavos.

SPI1->CR1 |= SPI_CR1_SSM; //disable automatic SS
Si no escribo nada en el búfer y mantengo NSS bajo, ¿oscilará el CLK?
No, cuando no se usa el modo automático, NSS es completamente independiente y solo es útil para el esclavo receptor. El CLK oscilará solo para desplazar un número predefinido de bits después de escribir un valor en el registro de transmisión de datos.