initial commit
This commit is contained in:
183
project/ble_peripheral/ble_app_vivaMayo/spi2_bus.c
Normal file
183
project/ble_peripheral/ble_app_vivaMayo/spi2_bus.c
Normal file
@@ -0,0 +1,183 @@
|
||||
/*******************************************************************************
|
||||
* @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;
|
||||
}
|
||||
Reference in New Issue
Block a user