Las lecturas de SPI son cambiadas, inconsistentes (nRF Master, FPGA Slave)

1

Intentaré simplificar mi proyecto tanto como sea posible para que esto sea comprensible. Estoy conectando una placa nRF52 PCA10040 a una FPGA iCE5LP (Lattice).

Tengo un problema con los bytes que llegan a la MCU (línea MISO), aquí está el curso de acción:

  1. El maestro envía el comando a través de SPI
  2. Slave ejecuta el comando, y preparar los datos para la transferencia
  3. Después de esperar el tiempo suficiente para el comando ser procesados y los datos a ser Preparado, el Maestro envía dummy. bytes para recibir el registro tx de la FPGA.
  4. Los datos parecen modificados y son inconsistentes.

Los datos están correctamente cargados, de acuerdo con la simulación. Lo que recibo de todas las demás transferencias es el byte que estoy esperando, pero cambiado en un bit. Vea las siguientes capturas de pantalla;

Esta es la simulación: Estaeslasalidadelanalizadorlógico:  Loqueespero:(esunprocedimientodeinicializacióndeeMMC)

  • 0xC0FF8080o0x40FF8080dependiendodelresultadoinicial

Loqueobtengoalazar:

0xE07FC040quees0xC0FF8080>>1 o0x007F8040quees0x00FF0080>>1

staticuint8_tm_rx_buf[4];/**<RXbuffer.*/staticuint8_tm_rx_buf_ext[6];/**<RXbuffer.*/staticuint8_tm_tx_buf[]={0x00,0xaa,0xbb,0xcc};/**<TXbuffer.*//***@briefSPIusereventhandler.*@paramevent*/voidspi_event_handler(nrf_drv_spi_evt_tconst*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!

    
pregunta Fluffy

2 respuestas

2

La diferencia entre la velocidad de adquisición y la velocidad de datos no es suficiente. Aumentar la velocidad del FPGA o disminuir la velocidad del SPI sí 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, puede que no esté completamente limpia. Es probable que haya jitter en su reloj y / o datos. Un factor de 2 como diferencia es simplemente cortarlo demasiado cerca.

Usted tiene un factor de 3. Cuando tenga dudas sobre la validez de sus señales, tenga en cuenta que esto es casi mínimo. Aumenta el factor. Como indicaste, el factor 12 funciona. Su umbral es probable en 8 (12/8 = 1.5 MHz).

Además, probablemente no necesite una velocidad tan alta. La integridad de los datos es probablemente mucho más importante. Primero constrúyalo de forma segura, y luego preocupe la optimización de la velocidad.

    
respondido por el Mast
0

Su gráfica del analizador lógico no tiene la resolución necesaria. Pero el MISO y el MOSI parecen estar fuera de fase en 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 lo contrario es cierto. Si el maestro y el esclavo no se configuraron igual, el resultado es impredecible. Sin embargo, un cambio de bit de 1 es un resultado razonable de tal desajuste.

    
respondido por el st2000

Lea otras preguntas en las etiquetas