【问题标题】:Multiple SPI masters active at once多个 SPI 主机同时处于活动状态
【发布时间】:2019-05-05 22:14:01
【问题描述】:

我在尝试让 2 个 SPI 主机同时工作时遇到了问题。它们都有不同的引脚(mosi、miso、sck、ss),一个用于 SD 卡,另一个用于加速度计。我的设备是 nRF52832,我一直在尝试使用 nRF52 SDK 15.2.0 中的 SPI 驱动程序。

我不确定它们是否可以同时被初始化和使用,但是如果程序在需要与另一个 spi 实例通信时需要初始化和 uninit 另一个 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();
    }
}

/** @} */

【问题讨论】:

  • 您似乎在谈论您编写的一些代码,但没有代码可供我们查看。
  • 芯片总线上通常有一个芯片选择引脚,您需要切换它才能说出您正在与谁交谈。硬件应将此连接到 GPIO 或某些控制器具有专用逻辑。否则,您需要控制信号的门。通常,只需对sck 进行门控即可有效地打开/关闭与设备的通信。
  • 从数据表看来,可能有两个独立的 spi 总线,需要为每个选择引脚设置单独的 gpios。您是否正在尝试进行 dma(尚未查看是否支持),但如果支持,该部分/外围设备一次可以做多个吗?你使用中断有单独的中断吗?如果/当你提供源代码时,你有范围图吗?
  • 我认为这个问题是由我在 EasyDMA 上不理解的东西引起的。当我在调试器中单步执行代码时,内存似乎被正确操作,我无法让 dma 保存对我缓冲区的回复。

标签: arm spi m4


【解决方案1】:

问题解决了。 SD卡和加速度计默认都有不同的串行总线。当第一次初始化另一个时,第二个在总线初始化失败,导致 nRF52832 没有得到正确的答案。

【讨论】:

  • @ligori 你能在代码中包含/强调你是如何解决这个问题的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
  • 2019-09-16
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
相关资源
最近更新 更多