This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nrf52832, sd card and accelerometer.

Hello!

I have both SD Card and accelerometer in same SPI bus. Both of them working like charm if another is not present. I'am using app_sdcard from 52 sdk.

Can i use spi manager for my accelerometer or does that effect to sd card drivers?

I have found that SD Card drivers are using gpio to enable and disable CS but problem is that its uses handler. When i try to use same SPI master the sd card:s handler doesn't like data from accelerometer.

I have tried to add NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER to modified nrf_drv_spi_transfer, but then i don't get any data out and it still gives me

<error> app: ERROR 3 [NRF_ERROR_INTERNAL] at C:\nrf\components\libraries\sdcard\app_sdcard.c:987
PC at: 0x0002D26B

And error is from app_sdcard spi_handler.

As i did have few pins to spare. I seperated SD Card and accelerometer to own busses and it still does not work.

SD Card setup:

CS: pin 11

SCK: 16

MOSI: 17

MISO: 18

Using SPI 2 instance

Accelerometer:

CS: 12

SCK: 5

MOSI: 4

MISO: 3

Using SPI 1 instance

The one which initializes first works and other is not doing anything.

I have another sensor which uses i2c and it uses TWI instance 0

  • Schematics: 

    gleapper.pdf

    Code:

    /**
     * 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();
        }
    }
    
    /** @} */
    
    What have i missed? In main fatfs_example() works if it is called first and same does initAcc()

  • Hi, what happens if you do not initialize the TWI sensor? The TWI peripheral is shared with the SPI peripheral, so you can't have both SPI0 and TWI0 enabled at the same time. SPI1 and TWI1 etc.

  • And regarding using the same SPI bus with two slaves,  I need to setup a project here to see what happens with the SD-card driver.

    What you could try is to use two different SPI instances for the two slaves, but use the same GPIO configuration. Then you will have to uninitialize and re-initialize the SPI instance every time you want to start a new transfer, but at least the handlers are separate for the different instances.

    First we would have to figure out why you can only enable one SPI instance at a time though. So please try to disable the TWI instance.

  • Hi Stian, I moved my code to "test" enviroment so i'm now only using spi instance 1 and spi instance 2. TWI is not enabled. It's quite frustrating that they are working, but not as together.

  • So it seems I can't have 2 spi masters initialized at the same time.

    Program works if i uninitialize sd card before executing initAcc.

    What would be the best solution to use both at "same" time? Is constantly initializing and unitializing the spi master heavy duty? 

Related