Хобрук: Ваш путь к мастерству в программировании

Несколько мастеров SPI активны одновременно

Я столкнулся с проблемой при попытке заставить работать 2 мастера SPI одновременно. Оба они имеют разные контакты (mosi, miso, sck, ss), один используется для SD-карты, а другой — для акселерометра. Мое устройство — nRF52832, и я пытался использовать драйверы SPI из nRF52 SDK 15.2.0.

Я не уверен, можно ли их инициализировать и использовать одновременно, но это кажется совершенно неправильным, если программе нужно инициализировать и юнитировать другой экземпляр spi всякий раз, когда ей нужно общаться с другим.

Кажется, что всякий раз, когда один экземпляр инициализируется, второй работает неправильно. Никаких ошибок программа не выдает. Это мое первое знакомство со встроенными системами, и поэтому мой уровень навыков — новичок. Я действительно был бы признателен за помощь.

/**
 * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
/** @file
 * @defgroup fatfs_example_main main.c
 * @{
 * @ingroup fatfs_example
 * @brief FATFS Example Application main file.
 *
 * This file contains the source code for a sample application using FAT filesystem and SD card library.
 *
 */


#include "nrf.h"
#include "bsp.h"
#include "ff.h"
#include "diskio_blkdev.h"
#include "nrf_block_dev_sdc.h"


#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "nrf_drv_spi.h"

#define FILE_NAME   "NORDIC.TXT"
#define TEST_STRING "SD card example."

#define SDC_SCK_PIN     16  ///< SDC serial clock (SCK) pin.
#define SDC_MOSI_PIN    17  ///< SDC serial data in (DI) pin.
#define SDC_MISO_PIN    18  ///< SDC serial data out (DO) pin.
#define SDC_CS_PIN      11  ///< SDC chip select (CS) pin.

#define SDC2_SCK_PIN      5
#define SDC2_MOSI_PIN     4
#define SDC2_MISO_PIN     3
#define SDC2_CS_PIN       12

#define SPI_AC_INSTANCE 1
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_AC_INSTANCE);


/**
 * @brief  SDC block device definition
 * */
NRF_BLOCK_DEV_SDC_DEFINE(
        m_block_dev_sdc,
        NRF_BLOCK_DEV_SDC_CONFIG(
                SDC_SECTOR_SIZE,
                APP_SDCARD_CONFIG(SDC_MOSI_PIN, SDC_MISO_PIN, SDC_SCK_PIN, SDC_CS_PIN)
         ),
         NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00")
);

/**
 * @brief Function for demonstrating FAFTS usage.
 */
static void fatfs_example()
{
    static FATFS fs;
    static DIR dir;
    static FILINFO fno;
    static FIL file;

    uint32_t bytes_written;
    FRESULT ff_result;
    DSTATUS disk_state = STA_NOINIT;

    // Initialize FATFS disk I/O interface by providing the block device.
    static diskio_blkdev_t drives[] =
    {
            DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)
    };

    diskio_blockdev_register(drives, ARRAY_SIZE(drives));

    NRF_LOG_INFO("Initializing disk 0 (SDC)...");
    for (uint32_t retries = 3; retries && disk_state; --retries)
    {
        disk_state = disk_initialize(0);
    }
    if (disk_state)
    {
        NRF_LOG_INFO("Disk initialization failed.");
        return;
    }

    uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size;
    uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb;
    NRF_LOG_INFO("Capacity: %d MB", capacity);

    NRF_LOG_INFO("Mounting volume...");
    ff_result = f_mount(&fs, "", 1);
    if (ff_result)
    {
        NRF_LOG_INFO("Mount failed.");
        return;
    }

    NRF_LOG_INFO("\r\n Listing directory: /");
    ff_result = f_opendir(&dir, "/");
    if (ff_result)
    {
        NRF_LOG_INFO("Directory listing failed!");
        return;
    }

    do
    {
        ff_result = f_readdir(&dir, &fno);
        if (ff_result != FR_OK)
        {
            NRF_LOG_INFO("Directory read failed.");
            return;
        }

        if (fno.fname[0])
        {
            if (fno.fattrib & AM_DIR)
            {
                NRF_LOG_RAW_INFO("   <DIR>   %s",(uint32_t)fno.fname);
            }
            else
            {
                NRF_LOG_RAW_INFO("%9lu  %s", fno.fsize, (uint32_t)fno.fname);
            }
        }
    }
    while (fno.fname[0]);
    NRF_LOG_RAW_INFO("");

    NRF_LOG_INFO("Writing to file " FILE_NAME "...");
    ff_result = f_open(&file, FILE_NAME, FA_READ | FA_WRITE | FA_OPEN_APPEND);
    if (ff_result != FR_OK)
    {
        NRF_LOG_INFO("Unable to open or create file: " FILE_NAME ".");
        return;
    }

    ff_result = f_write(&file, TEST_STRING, sizeof(TEST_STRING) - 1, (UINT *) &bytes_written);
    if (ff_result != FR_OK)
    {
        NRF_LOG_INFO("Write failed\r\n.");
    }
    else
    {
        NRF_LOG_INFO("%d bytes written.", bytes_written);
    }

    (void) f_close(&file);
    return;
}

static uint8_t       tx_buf[3];
static uint8_t       rx_buf[10];    /**< RX buffer. */

uint8_t accReadByte(uint8_t RegisterAddress)
{ 
  tx_buf[0] = 0x7F & RegisterAddress;
  tx_buf[1] = 0x80 & RegisterAddress;

  APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, tx_buf, 2, rx_buf, 1+2));
  return rx_buf[2];
}

void initAcc()
{
  //nrf_gpio_set_cfg_output(SDC2_CS_PIN);

  nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;

  spi_config.ss_pin = SDC2_CS_PIN;
  spi_config.miso_pin = SDC2_MISO_PIN;
  spi_config.mosi_pin = SDC2_MOSI_PIN;
  spi_config.sck_pin = SDC2_SCK_PIN;
  spi_config.frequency = NRF_SPI_FREQ_250K;

  APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL));



}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    bsp_board_init(BSP_INIT_LEDS);

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("FATFS example started.");

    fatfs_example();
    initAcc();

    if ( accReadByte(0x0D) == 0x6A )
    {
      NRF_LOG_INFO("Got right whoami!");
    }


    while (true)
    {
        __WFE();
    }
}

/** @} */
04.12.2018

  • Похоже, вы говорите о каком-то коде, который вы написали, но у нас нет кода, на который мы могли бы посмотреть. 04.12.2018
  • Обычно на шине чипов есть контакт выбора чипа, который вам нужно переключить, чтобы сказать, с кем вы разговариваете. Аппаратное обеспечение должно подключаться к GPIO, или некоторые контроллеры имеют выделенную логику. В противном случае вам нужен гейт на управляющих сигналах. Часто достаточно sck, чтобы эффективно включить/выключить связь с устройством. 04.12.2018
  • из таблицы данных представляется возможным иметь две отдельные шины spi, для каждой из которых необходимо иметь отдельный gpios для вывода выбора. вы пытаетесь сделать dma (еще не смотрел, поддерживается ли это), но если да, то может ли часть / периферийное устройство делать более одного за раз? вы используете прерывания, есть ли отдельные прерывания? у вас есть графики масштаба для исходного кода, если / когда вы это предоставите? 05.12.2018
  • Я думаю, что эта проблема вызвана чем-то, чего я не понимаю в EasyDMA. Когда я просматриваю код в отладчике, кажется, что с памятью правильно манипулируют, и я просто не могу заставить dma сохранить ответ в моем буфере. 05.12.2018

Ответы:


1

Проблема решена. SD-карта и акселерометр по умолчанию имеют разные последовательные шины. Когда сначала инициализировался другой, второй не смог инициализировать шину, и это привело к тому, что nRF52832 не получил правильного ответа.

02.01.2019
  • @ligori Можете ли вы включить / выделить, как вы решили проблему в своем коде? 04.06.2021
  • Новые материалы

    Почему шаблоны проектирования и почему нет?
    Сложность — мать всех проблем в программировании. Программное обеспечение должно быть разработано с точки зрения того, кто его поддерживает, а не того, кто его пишет, потому что программное..

    Создание дизайна обуви с помощью машинного обучения
    Обувь. Что подождать? Я думал, что речь пойдет о машинном обучении! Ну это так. Если бы вы пошли на Amazon, сколько обуви вы бы нашли? Наверное, много, не так ли? Но много ли в них..

    GraalVM в 2022 году: итоги года
    2022 год был очень продуктивным для проекта и сообщества GraalVM. Вместе мы разработали множество новых функций, выпустили GraalVM для последних версий Java и новых платформ и увидели несколько..

    Быстрая разработка: волшебный мир больших языковых моделей
    РУКОВОДСТВО Быстрая разработка: волшебный мир больших языковых моделей Подход, основанный на данных, для получения наилучшего ответа Искусство и наука Можно ли совместить машинное..

    Ускоренный курс по Node Redis
    Сегодня мы будем учиться использовать Redis в Node.js, однако я не собираюсь вываливать сюда всю документацию и утомлять вас до смерти. Это руководство для начинающих? — спросите вы. Ну..

    Обзор Python для науки о данных и машинного обучения
    Python стал наиболее предпочтительным языком программирования среди разработчиков, которые в основном занимаются наукой о данных и машинным обучением. Интуитивно понятные и уникальные функции..

    Принудительный сброс состояния компонента React с помощью ключевого свойства
    Принудительный сброс состояния компонента React с помощью ключевого свойства Знаете ли вы, что вы можете использовать опору key для принудительного сброса состояния компонента? В..