Hi,
I'm trying to connect a nordic nrf52832 as an SPI master to an external Flash, and for that I'm using SDK 16.0.0.
Since I wanted to already use the transaction mechanism as I use for TWI, I tried to adapt the example from ..\examples/peripheral/spi_master_using_nrf_spi_mngr, which - unfortunately for me at least - does not perform a read, only writes.
However, I cannot really communicate with the device, at least I'm not even able to obtain the external_flash properties (3x bytes whoamI like data) to assure that I'm connected and if so to the correct device (I have a single slave SPI device and single master manager). It seems to me that I may have an issue with my SW code since I cannot even get the end_callback running. I.e., it seems to me that I'm really missing any configuration instead of having an HW issue (which I cannot currently test).
So, I'm sending part of the code, that I hope can already help in spotting the problem(s).
/* SDK */
#include "nrf_spi_mngr.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
/* C standard library */
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
/********************************** Private ***********************************/
/* SPI Specific definitions */
#define SPI_INSTANCE_ID 1 ///< SPI ID. Cannot be instance 0 due to TWI_mngr instance 0 presence.
#define SPI_QUEUE_SIZE 50 ///< SPI maximum pending transactions.
#define SPI_SCK_PIN (25) ///< SCK (Serial Clock) signal pin.
#define SPI_MOSI_PIN (24) ///< MOSI (Master Out Slave In) signal pin.
#define SPI_MISO_PIN (23) ///< MISO (Master In Slave Out) signal pin.
#define SPI_SS_PIN (26) ///< SS (Slave Select) signal pin. Optional
#define SPI_OVER_READ_CHARACTER (0xFF) ///< Over Read Character default
#define SPI_FREQUENCY (NRF_DRV_SPI_FREQ_8M) ///< Frequency 8MHz
#define SPI_MODE (1) ///< CPOL=0 (Leading), CPHA=0 (Active High)
#define SPI_BIT_ORDER (NRF_SPI_BIT_ORDER_MSB_FIRST) ///< Bit Order default
/* used together with OpCodes (Operation Commands) */
#define DUMMY_BYTE (0x00)
/* SPI manager definition. */
NRF_SPI_MNGR_DEF(m_nrf_spi_mngr, SPI_QUEUE_SIZE, SPI_INSTANCE_ID);
/* SPI manager configuration utility. */
static ret_code_t spi_manager_init(void) {
nrf_drv_spi_config_t const m_nrf_drv_spi_config = {
.sck_pin = SPI_SCK_PIN,
.mosi_pin = SPI_MOSI_PIN,
.miso_pin = SPI_MISO_PIN,
.ss_pin = SPI_SS_PIN,
.irq_priority = APP_IRQ_PRIORITY_LOW, // changed from APP_IRQ_PRIORITY_LOWEST without success
.orc = SPI_OVER_READ_CHARACTER,
.frequency = SPI_FREQUENCY,
.mode = SPI_MODE,
.bit_order = SPI_BIT_ORDER
};
/* Inits SPI Manager Driver */
return nrf_spi_mngr_init(&m_nrf_spi_mngr, &m_nrf_drv_spi_config);
}
/* SPI manager uninit. */
static void spi_manager_uninit(void) {
/* Make sure SPI is disabled */
nrf_spi_mngr_uninit(&m_nrf_spi_mngr);
}
/* Flash chip state */
static struct _external_flash_x {
uint8_t device_id[2]; /* Holds the device ID (Parts 1 and 2) */
uint8_t manufacturer_id; /* Holds the manufacturer ID */
uint8_t status_register[2]; /* Holds the manufacturer ID */
} external_flash_x = { .device_id = { 0 }, .manufacturer_id = 0, .status_register = { 0 } };
static bool finished_cb = false;
// Internal Buffer 256 bytes experience.
static uint8_t m_auxiliar_buffer[256];
/* Chip Select enabling (active low) */
__STATIC_INLINE void _start_chip_select(void) {
nrf_gpio_pin_clear(SPI_SS_PIN);
nrf_delay_us(10);
};
/* Chip Select disabling (disable high) */
__STATIC_INLINE void _end_chip_select(void) {
nrf_gpio_pin_set(SPI_SS_PIN);
};
static void getManufactureAndDevice_begin_callback(void * p_user_data) {
_start_chip_select();
};
/* This never get called. I.e., finished_cb never gets true.*/
static void getManufactureAndDevices_end_callback(ret_code_t result, void * p_user_data) {
finished_cb = true;
external_flash_x.manufacturer_id = m_auxiliar_buffer[0];
external_flash_x.device_id[0] = m_auxiliar_buffer[1];
external_flash_x.device_id[1] = m_auxiliar_buffer[2];
_end_chip_select();
};
/* Obtains the integrity of the expected manufacturer and family code */
static bool _external_flash_x_get_integrity_data(void) {
// NRF SPI buffer for the commands to get the Manufacture and Devices' Ids
static NRF_SPI_MNGR_BUFFER_LOC_IND uint8_t integrity_op_cmds[] = {
READ_MAN_DEVICE_ID_OP,
DUMMY_BYTE,
DUMMY_BYTE,
DUMMY_BYTE
}; // Note: external flash manufacture states only 3x bytes of DUMMY_BYTE (0x00)
static nrf_spi_mngr_transfer_t NRF_SPI_MNGR_BUFFER_LOC_IND integrity_transfer_cmds[] = {
NRF_SPI_MNGR_TRANSFER(&integrity_op_cmds[0], sizeof(integrity_op_cmds), m_auxiliar_buffer, 4)
// Note: Already changed "4" by many other values without success. Manufactor states 4 commands (i.e., 1 + 3x dummies)
};
static nrf_spi_mngr_transaction_t const integrity_transaction_cmd = {
.begin_callback = getManufactureAndDevice_begin_callback,
.end_callback = getManufactureAndDevices_end_callback,
.p_user_data = NULL,
.p_transfers = integrity_transfer_cmds,
.number_of_transfers = 1,
.p_required_spi_cfg = NULL
};
if (nrf_spi_mngr_schedule(&m_nrf_spi_mngr, &integrity_transaction_cmd) == NRF_SUCCESS) {
return true;
} else {
return false;
}
}
/********************************** Public ************************************/
/* Initializes the External_Flash_X device. */
bool external_flash_x_init(void) {
/* Initialize SPI manager and interface */
if ( spi_manager_init() != NRF_SUCCESS) {
return false;
}
/* Configure GPIO pins */
/* Initialize chip-select/ slave select but disable it (disable high) */
nrf_gpio_cfg_output(SPI_SS_PIN);
nrf_gpio_pin_set(SPI_SS_PIN);
nrf_delay_us(20); // Documentation states 10 us, but I even already changed to 20.
/* configure SCK, MOSI and MISO */
nrf_gpio_cfg_output(SPI_SCK_PIN);
nrf_gpio_cfg_output(SPI_MOSI_PIN);
nrf_gpio_cfg_input(SPI_MISO_PIN,NRF_GPIO_PIN_PULLUP);
/* Clear MOSI value */
nrf_gpio_pin_clear(SPI_MOSI_PIN);
nrf_delay_us(20);
/* Clear SCK value; Since we're going to use SPI Mode 0, CPOL=0 */
nrf_gpio_pin_clear(SPI_SCK_PIN);
nrf_delay_us(20);
/* Erase auxiliar buffer */
memset(m_auxiliar_buffer, 0x00, sizeof(m_auxiliar_buffer));
/* Read "Manufacturer and Device ID" */
if (!_external_flash_x_get_integrity_data()) {
return false;
}
/* Here I do the integrity check that is always failing since it seems that I cannot read from External Flash via SPI
...
*/
}
#"#"#
/* main.c */
/* some #includes */
/* Clock setup */
lfclock_init();
/* RTC2 setup including its enabling */
rtc_init();
/* Macro for initializing the application timer module */
app_timer_init();
/* calls external_flash_x_init() */
external_flash_x_init();
/* ... */
Thanks in advance for you support.
Luis Silva