Intentaré simplificar mi proyecto tanto como sea posible para que esto sea comprensible. Estoy conectando una placa nRF52 PCA10040 a un FPGA iCE5LP (Lattice).
Tengo un problema con los bytes que ingresan a la MCU (línea MISO), este es el curso de acción:
Los datos se cargan correctamente, según la simulación. Lo que recibo en todas las demás transferencias es el byte que espero pero que se desplazó un bit. Vea las siguientes capturas de pantalla;
Esta es la simulación: Esta es la salida del analizador lógico: Lo que espero: (es un procedimiento de inicialización de eMMC)
Lo que obtengo al azar:
0xE07FC040 que es 0xC0FF8080 >> 1 o 0x007F8040 que es 0x00FF0080 >> 1
static uint8_t m_rx_buf[4]; /**< RX buffer. */
static uint8_t m_rx_buf_ext[6]; /**< RX buffer. */
static uint8_t m_tx_buf[] = {0x00, 0xaa, 0xbb, 0xcc}; /**< TX buffer. */
/**
* @brief SPI user event handler.
* @param event
*/
void spi_event_handler(nrf_drv_spi_evt_t const * p_event) {
spi_xfer_done = true;
NRF_LOG_PRINTF("Received: %x %x %x %x\n", m_rx_buf[0], m_rx_buf[1], m_rx_buf[2], m_rx_buf[3]);
}
/**
* Function to send a command to a specific module.
* @param module : Module to communicate with
* @param command : Command to send
*/
ret_code_t sendCommand(uint8_t module, uint8_t command, uint8_t mmc_command, uint32_t mmc_arg) {
ret_code_t err_code;
uint8_t firstByte = module + command;
if (command > 31 || module > 7) {
return APP_ERROR_INVALID_CMD;
}
uint8_t msg_a[] = {firstByte, mmc_command, mmc_arg >> 24, mmc_arg >> 16, mmc_arg >> 8, mmc_arg & 0xFF};
uint8_t msg_length = sizeof(msg_a);
memset(m_rx_buf_ext, 0, msg_length);
spi_xfer_done = false;
err_code = nrf_drv_spi_transfer(&spi, msg_a, msg_length, m_rx_buf_ext, msg_length);
while (!spi_xfer_done) {
__WFE();
}
if (err_code != NRF_SUCCESS) {
NRF_LOG_PRINTF("Error during transfer : %d\n", err_code);
}
return err_code;
}
ret_code_t initMMC() {
ret_code_t err_code;
bool mmc_initialized = false;
nrf_delay_us(200); /**< Wait for more than 74 clock cycles before issuing a command. */
err_code = sendCommand(MODULE_CMD_SEND, CMD_SEND_CMD_TO_MMC, CMD0, 0);
while (!mmc_initialized) {
nrf_delay_us(300);
err_code = sendCommand(MODULE_CMD_SEND, CMD_SEND_CMD_TO_MMC, CMD1, ARG_BUS_INIT);
nrf_delay_us(600);
memset(m_rx_buf, 0, 4);
spi_xfer_done = false;
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, 4, m_rx_buf, 4));
while (!spi_xfer_done)
{
__WFE();
}
if (m_rx_buf[0] == 0xC0 || m_rx_buf[0] == 0x80 || m_rx_buf[0] == 0xE0) {
NRF_LOG_PRINTF("eMMC Initialized.\n");
mmc_initialized = true;
}
nrf_delay_ms(1000);
}
return err_code;
}
void init_clock() {
NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
NRF_CLOCK->TASKS_LFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0); // Wait for clock to start
}
int main(void) {
APP_ERROR_CHECK(NRF_LOG_INIT());
init_clock();
LEDS_CONFIGURE(LEDS_MASK);
LEDS_OFF(LEDS_MASK);
APP_TIMER_INIT(APP_TIMER_PRESCALER,APP_TIMER_OP_QUEUE_SIZE,NULL);
APP_ERROR_CHECK(nrf_drv_gpiote_init());
buttons_init();
NRF_LOG_PRINTF(NRF_LOG_COLOR_RED"\nSTARTING.\r\n"NRF_LOG_COLOR_DEFAULT);
nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG(SPI_INSTANCE);
spi_config.ss_pin = SPI_CS_PIN;
spi_config.frequency = NRF_SPI_FREQ_4M;
spi_config.mode = NRF_DRV_SPI_MODE_0;
APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler));
resetFPGA(RST_PIN); //Pulls up fpga's reset pin for 5ms then down
nrf_delay_ms(1000);
APP_ERROR_CHECK(initMMC());
while(1) {
__WFE();
}
}
¿Tienes una idea de lo que estoy haciendo mal? ¡Muchas gracias!
La diferencia entre su velocidad de adquisición y la velocidad de datos no es suficiente. Aumentar la velocidad del FPGA o disminuir la velocidad del SPI soluciona el problema de alineación.
Su reloj SPI y su reloj FPGA no están sincronizados. Esto significa que su reloj FPGA debe funcionar como mínimo dos veces más rápido que el reloj SPI. Sin embargo, dado que SPI es una señal externa, es posible que no esté del todo limpia. Es probable que haya fluctuaciones en su reloj y/o datos. Un factor de 2 como diferencia es simplemente cortarlo demasiado cerca.
Tiene un factor de 3. Cuando tenga dudas sobre la validez de sus señales, tenga en cuenta que esto está cerca del mínimo indispensable. Aumenta el factor. Como indicaste, el factor 12 funciona. Es probable que su umbral esté en 8 (12/8 = 1,5 MHz).
Además, lo más probable es que no necesites una velocidad tan alta. Es probable que la integridad de los datos sea mucho más importante. Constrúyalo de forma segura primero, preocúpese por la optimización de la velocidad después.
La trama de su analizador lógico no tiene la resolución necesaria. Pero el MISO y el MOSI parecen estar desfasados por medio ciclo.
Normalmente hay 4 modos en los que operan los buses SPI . En uno, se espera que los datos cambien en el flanco descendente y se muestreen en el flanco ascendente del reloj. En otro ocurre lo contrario. Si el maestro y el esclavo no se configuraron de la misma manera, el resultado es impredecible. Sin embargo, un cambio de bit de 1 es un resultado razonable de tal desajuste.
Mástil
Esponjoso
Mástil
Mástil
Esponjoso
Mástil
Esponjoso