Я постараюсь максимально упростить свой проект, чтобы сделать это понятным. Я подключаю плату nRF52 PCA10040 к FPGA iCE5LP (Lattice).
У меня проблема с байтами, поступающими на MCU (линия MISO), вот порядок действий:
Данные правильно загружены, в соответствии с симуляцией. При каждой второй передаче я получаю ожидаемый байт, но сдвинутый на один бит. См. следующие скриншоты;
Это симуляция: Это вывод логического анализатора:
Что я ожидаю: (это процедура инициализации eMMC)
Что я получаю случайно:
0xE07FC040 (0xC0FF8080 >> 1) или 0x007F8040 (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();
}
}
У вас есть идея, что я делаю неправильно? Большое спасибо!
Разницы между вашей скоростью захвата и скоростью передачи данных недостаточно. Увеличение скорости FPGA или уменьшение скорости SPI решает проблему выравнивания.
Ваши часы SPI и часы FPGA не синхронизированы. Это означает, что часы FPGA должны работать как минимум в два раза быстрее, чем часы SPI. Однако, поскольку SPI является внешним сигналом, он может быть не совсем чистым. Вероятно, есть джиттер на ваших часах и/или данных. Фактор 2 в качестве разницы просто сокращает его слишком близко.
У вас есть коэффициент 3. Если вы сомневаетесь в достоверности ваших сигналов, имейте в виду, что он близок к абсолютному минимуму. Увеличьте коэффициент. Как вы указали, фактор 12 работает. Ваш порог, вероятно, равен 8 (12/8 = 1,5 МГц).
Кроме того, вам, скорее всего, не нужна такая высокая скорость. Целостность данных, вероятно, гораздо важнее. Сначала сделайте его безопасным, а потом позаботьтесь об оптимизации скорости.
График вашего логического анализатора не имеет необходимого разрешения. Но MISO и MOSI, похоже, не совпадают по фазе на половину цикла.
Обычно есть 4 режима, в которых работают шины SPI . В одном ожидается, что данные изменятся по заднему фронту, а выборка будет производиться по переднему фронту тактового сигнала. В другом все наоборот. Если ведущий и ведомый не были установлены одинаково, результат непредсказуем. Однако битовый сдвиг на 1 является разумным результатом такого несоответствия.
Мачта
Пушистый
Мачта
Мачта
Пушистый
Мачта
Пушистый