Files
VivaMyo-firmware-test/project/ble_peripheral/ble_app_vivaMayo/spi2_bus.c
2026-04-08 16:59:20 +09:00

184 lines
5.3 KiB
C

/*******************************************************************************
* @file spi2_bus.c
* @brief Shared SPI2 Bus - nrfx_spim driver (SoftDevice safe)
* @author Charles KWON <charleskwon@medithings.co.kr>
* @date 2025-02-03
*
* @note Uses nrfx_spim with APP_IRQ_PRIORITY_LOWEST for SoftDevice compatibility
******************************************************************************/
#include "spi2_bus.h"
#include "nrfx_spim.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "app_error.h"
#include "app_util_platform.h" /* For APP_IRQ_PRIORITY_LOWEST */
#include "debug_print.h"
#include <stdio.h>
/* Define instance index if not provided by nrfx (SDK version dependent) */
#ifndef NRFX_SPIM2_INST_IDX
#define NRFX_SPIM2_INST_IDX 0
#endif
/*==============================================================================
* PRIVATE VARIABLES
*============================================================================*/
static bool m_initialized = false;
static nrfx_spim_t m_spi = NRFX_SPIM_INSTANCE(SPI2_BUS_INSTANCE);
/*==============================================================================
* PUBLIC FUNCTIONS
*============================================================================*/
ret_code_t spi2_bus_init(void)
{
if (m_initialized)
{
return NRF_SUCCESS;
}
DBG_PRINTF("[SPI2] nrfx init...\r\n");
nrfx_spim_config_t cfg = NRFX_SPIM_DEFAULT_CONFIG;
cfg.sck_pin = SPI2_SCK_PIN;
cfg.mosi_pin = SPI2_MOSI_PIN;
cfg.miso_pin = SPI2_MISO_PIN;
cfg.ss_pin = NRFX_SPIM_PIN_NOT_USED; /* Manual CS control */
cfg.frequency = NRF_SPIM_FREQ_1M; /* Try slower for debugging */
cfg.mode = NRF_SPIM_MODE_0;
cfg.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST;
cfg.irq_priority = APP_IRQ_PRIORITY_LOWEST; /* SoftDevice safe! */
/* Use NULL handler for blocking mode (no IRQ needed) */
nrfx_err_t err = nrfx_spim_init(&m_spi, &cfg, NULL, NULL);
DBG_PRINTF("[SPI2] init err=%d (blocking)\r\n", err);
if (err != NRFX_SUCCESS && err != NRFX_ERROR_INVALID_STATE) {
DBG_PRINTF("[SPI2] FAIL!\r\n");
return err;
}
/* Configure CS pins as outputs, deasserted (high) */
nrf_gpio_cfg_output(SPI2_CS_ADA2200);
nrf_gpio_cfg_output(SPI2_CS_FLASH);
nrf_gpio_pin_set(SPI2_CS_ADA2200);
nrf_gpio_pin_set(SPI2_CS_FLASH);
m_initialized = true;
DBG_PRINTF("[SPI2] OK\r\n");
return NRF_SUCCESS;
}
void spi2_bus_uninit(void)
{
if (!m_initialized) return;
nrfx_spim_uninit(&m_spi);
nrf_gpio_cfg_default(SPI2_SCK_PIN);
nrf_gpio_cfg_default(SPI2_MISO_PIN);
nrf_gpio_cfg_default(SPI2_MOSI_PIN);
nrf_gpio_cfg_default(SPI2_CS_ADA2200);
nrf_gpio_cfg_default(SPI2_CS_FLASH);
m_initialized = false;
}
bool spi2_bus_is_initialized(void)
{
return m_initialized;
}
const nrf_drv_spi_t* spi2_bus_get_instance(void)
{
/* Using nrfx_spim now - return NULL for legacy compatibility */
return NULL;
}
/* Debug: count transfers for selective logging */
static uint32_t s_xfer_count = 0;
ret_code_t spi2_bus_transfer(const uint8_t *tx_buf, uint8_t tx_len,
uint8_t *rx_buf, uint8_t rx_len)
{
if (!m_initialized)
{
DBG_PRINTF("[SPI2] ERROR: not init!\r\n");
return NRF_ERROR_INVALID_STATE;
}
s_xfer_count++;
bool debug = (s_xfer_count <= 10);
nrfx_spim_xfer_desc_t xfer;
nrfx_err_t err;
/* Blocking mode: nrfx_spim_xfer() waits for completion internally */
/* Full-duplex mode: TX and RX simultaneously */
if (tx_len > 0 && rx_len > 0) {
DBG_PRINTF("[SPI2] FD TX[%d] RX[%d]\r\n", tx_len, rx_len);
xfer.p_tx_buffer = tx_buf;
xfer.tx_length = tx_len;
xfer.p_rx_buffer = rx_buf;
xfer.rx_length = rx_len;
DBG_PRINTF("[SPI2] xfer...\r\n");
err = nrfx_spim_xfer(&m_spi, &xfer, 0);
DBG_PRINTF("[SPI2] xfer done err=%d\r\n", err);
if (err != NRFX_SUCCESS) {
DBG_PRINTF("[SPI2] FD err=%d\r\n", err);
return err;
}
DBG_PRINTF("[SPI2] RX: %02X %02X %02X %02X\r\n",
rx_buf[0],
rx_len > 1 ? rx_buf[1] : 0,
rx_len > 2 ? rx_buf[2] : 0,
rx_len > 3 ? rx_buf[3] : 0);
}
/* TX only mode */
else if (tx_len > 0) {
if (debug) {
DBG_PRINTF("[SPI2] TX[%d]: %02X\r\n", tx_len, tx_buf[0]);
}
xfer.p_tx_buffer = tx_buf;
xfer.tx_length = tx_len;
xfer.p_rx_buffer = NULL;
xfer.rx_length = 0;
err = nrfx_spim_xfer(&m_spi, &xfer, 0);
if (err != NRFX_SUCCESS) {
DBG_PRINTF("[SPI2] TX err=%d\r\n", err);
return err;
}
}
/* RX only mode */
else if (rx_len > 0) {
xfer.p_tx_buffer = NULL;
xfer.tx_length = 0;
xfer.p_rx_buffer = rx_buf;
xfer.rx_length = rx_len;
err = nrfx_spim_xfer(&m_spi, &xfer, 0);
if (err != NRFX_SUCCESS) {
DBG_PRINTF("[SPI2] RX err=%d\r\n", err);
return err;
}
if (debug) {
DBG_PRINTF("[SPI2] RX[%d]: %02X %02X %02X\r\n",
rx_len, rx_buf[0],
rx_len > 1 ? rx_buf[1] : 0,
rx_len > 2 ? rx_buf[2] : 0);
}
}
return NRF_SUCCESS;
}