코드 정리
- 주석 영문으로 변경 - Allman 스타일로 통일
This commit is contained in:
@@ -1,29 +1,18 @@
|
||||
/*******************************************************************************
|
||||
* @file i2c_manager.c
|
||||
* @brief Reliable HW↔SW I2C Switching Logic (with Mode Set Logging)
|
||||
*******************************************************************************
|
||||
/*==============================================================================
|
||||
* i2c_manager.c - HW / SW I2C mutex switching logic
|
||||
*
|
||||
* [모듈 개요]
|
||||
* I2C 버스의 HW(하드웨어 TWI) / SW(소프트웨어 비트뱅) 모드 전환을 관리하는 모듈.
|
||||
* Manages mutually-exclusive HW (TWI peripheral) and SW (bit-bang) I2C modes.
|
||||
*
|
||||
* - HW I2C: nRF52840 내장 TWI 하드웨어 주변장치를 사용 (ICM42670P IMU 센서 통신용, 400kHz)
|
||||
* - SW I2C: GPIO 비트뱅 방식의 소프트웨어 I2C (현재 사용하지 않는 레거시 코드)
|
||||
* HW I2C : nRF52840 TWI hardware, 400 kHz Fast Mode (ICM42670P IMU)
|
||||
* SW I2C : GPIO bit-bang (legacy, currently unused)
|
||||
*
|
||||
* [핀 설정]
|
||||
* Pins:
|
||||
* SCL = P1.14 (ICM42670_I2C_SCL_PIN)
|
||||
* SDA = P1.15 (ICM42670_I2C_SDA_PIN)
|
||||
*
|
||||
* [주요 함수]
|
||||
* hw_i2c_init_once() : SW→HW 전환 또는 HW 초기화 (이미 HW 모드면 중복 초기화 방지)
|
||||
* sw_i2c_init_once() : HW→SW 전환 (TWI 해제 후 SW 모드 진입, 레거시)
|
||||
* i2c_reset_state() : 모든 I2C 모드 플래그를 초기화 (HW/SW 모두 false)
|
||||
*
|
||||
* [동작 원리]
|
||||
* HW_I2C_FRQ, SW_I2C_FRQ 두 개의 bool 플래그로 현재 모드를 추적하며,
|
||||
* 한 번에 하나의 모드만 활성화되도록 상호 배제(mutex) 방식으로 관리한다.
|
||||
* 모드 전환 시 기존 모드의 리소스를 먼저 해제한 후 새 모드를 초기화한다.
|
||||
*
|
||||
******************************************************************************/
|
||||
* The two bool flags HW_I2C_FRQ and SW_I2C_FRQ track the current mode.
|
||||
* Switching releases the old mode's resources before initialising the new one.
|
||||
*============================================================================*/
|
||||
|
||||
#include "i2c_manager.h"
|
||||
#include "debug_print.h"
|
||||
@@ -34,137 +23,101 @@
|
||||
#include "boards.h"
|
||||
#include "system_interface.h"
|
||||
|
||||
/* 현재 I2C 모드 상태 플래그 (true = 해당 모드 활성화) */
|
||||
bool HW_I2C_FRQ = true; /* HW TWI 모드 활성 여부 (기본값: true, 초기 상태는 HW) */
|
||||
bool SW_I2C_FRQ = false; /* SW 비트뱅 모드 활성 여부 */
|
||||
/* Current I2C mode flags */
|
||||
bool HW_I2C_FRQ = true;
|
||||
bool SW_I2C_FRQ = false;
|
||||
|
||||
/* TWI 인스턴스 번호 (nRF52840은 TWI0, TWI1 두 개 지원) */
|
||||
/* TWI instance (nRF52840 supports TWI0 and TWI1) */
|
||||
#define TWI_INSTANCE 0
|
||||
|
||||
/* TWI (I2C) 하드웨어 인스턴스 : IMU 드라이버에서 사용 - jhChun 26.03.16 */
|
||||
const nrfx_twi_t m_twi = NRFX_TWI_INSTANCE(TWI_INSTANCE);
|
||||
|
||||
/* TWI (I2C) 해제 - jhChun 26.03.16 */
|
||||
/* TWI 하드웨어를 비활성화하고 초기화 해제하여 GPIO 핀을 반환한다 */
|
||||
static void twi_uninitialize(void){
|
||||
nrfx_twi_disable(&m_twi); /* TWI 주변장치 비활성화 */
|
||||
nrfx_twi_uninit(&m_twi); /* TWI 초기화 해제 (핀 리소스 반환) */
|
||||
/* Disable and uninitialise the TWI peripheral, releasing GPIO pins. */
|
||||
static void twi_uninitialize(void)
|
||||
{
|
||||
nrfx_twi_disable(&m_twi);
|
||||
nrfx_twi_uninit(&m_twi);
|
||||
}
|
||||
|
||||
/* TWI (I2C) 하드웨어 초기화 (SCL/SDA핀, 400kHz) - jhChun 26.03.16 */
|
||||
/* SCL, SDA 핀을 설정하고 400kHz Fast Mode로 TWI를 초기화 및 활성화한다 */
|
||||
/* Initialise the TWI peripheral (SCL/SDA pins, 400 kHz, blocking mode). */
|
||||
static void twi_initialize(void){
|
||||
ret_code_t err_code;
|
||||
|
||||
/* TWI 설정 구조체: 핀 번호, 클럭 속도, 인터럽트 우선순위 지정 */
|
||||
const nrfx_twi_config_t twi_config = {
|
||||
.scl = ICM42670_I2C_SCL_PIN, /* SCL 핀 (P1.14) */
|
||||
.sda = ICM42670_I2C_SDA_PIN, /* SDA 핀 (P1.15) */
|
||||
.frequency = NRF_TWI_FREQ_400K, /* 400kHz Fast Mode */
|
||||
.interrupt_priority = APP_IRQ_PRIORITY_HIGH, /* 높은 인터럽트 우선순위 */
|
||||
.scl = ICM42670_I2C_SCL_PIN,
|
||||
.sda = ICM42670_I2C_SDA_PIN,
|
||||
.frequency = NRF_TWI_FREQ_400K,
|
||||
.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
|
||||
};
|
||||
|
||||
/* TWI 초기화 (이벤트 핸들러 NULL = 블로킹 모드) */
|
||||
err_code = nrfx_twi_init(&m_twi, &twi_config, NULL, NULL);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
nrfx_twi_enable(&m_twi); /* TWI 주변장치 활성화 → I2C 통신 가능 */
|
||||
nrfx_twi_enable(&m_twi);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* HW (TWI) 초기화 */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/*
|
||||
* HW I2C 모드로 전환하거나 초기화하는 함수.
|
||||
* - SW 모드가 활성화되어 있으면 SW 플래그를 해제하고 HW로 전환
|
||||
* - 이미 HW 모드이면 중복 초기화를 방지하여 바로 리턴
|
||||
* - 최초 HW 초기화 시 twi_initialize()를 호출하여 TWI 하드웨어 설정
|
||||
*/
|
||||
/*==============================================================================
|
||||
* hw_i2c_init_once - Switch to or initialise HW TWI mode
|
||||
*
|
||||
* If SW mode is active, its flag is cleared first.
|
||||
* If HW mode is already active, returns immediately (no re-init).
|
||||
*============================================================================*/
|
||||
void hw_i2c_init_once(void)
|
||||
{
|
||||
// SW 모드일 경우 강제 해제 후 HW 전환
|
||||
if (SW_I2C_FRQ)
|
||||
{
|
||||
//DBG_PRINTF("[I2C]SW→HW\r\n");
|
||||
|
||||
// SW 리소스 해제 (필요 시 추가)
|
||||
SW_I2C_FRQ = false;
|
||||
nrf_delay_ms(2); /* 모드 전환 안정화 대기 (2ms) */
|
||||
nrf_delay_ms(2); /* mode-switch settling */
|
||||
}
|
||||
|
||||
/* 이미 HW 모드가 활성화되어 있으면 중복 초기화 방지를 위해 즉시 리턴 */
|
||||
// 이미 HW면 스킵
|
||||
if (HW_I2C_FRQ)
|
||||
{
|
||||
// DBG_PRINTF("[I2C] HW I2C set\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* HW TWI 하드웨어 초기화 수행 (SCL/SDA 핀 설정, 400kHz, 활성화) */
|
||||
// 실제 HW 초기화
|
||||
twi_initialize();
|
||||
nrf_delay_ms(2); /* 초기화 후 안정화 대기 (2ms) */
|
||||
nrf_delay_ms(2);
|
||||
|
||||
/* 모드 플래그 갱신: HW 활성, SW 비활성 */
|
||||
HW_I2C_FRQ = true;
|
||||
SW_I2C_FRQ = false;
|
||||
|
||||
// DBG_PRINTF("[I2C] HW I2C Mode set!\r\n");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* SW (Port Bang-Bang) 초기화 */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/*
|
||||
* SW I2C(비트뱅) 모드로 전환하는 함수. (현재 레거시, 사용하지 않음)
|
||||
* - HW 모드가 활성화되어 있으면 TWI를 해제하고 SW로 전환
|
||||
* - 이미 SW 모드이면 중복 초기화를 방지하여 바로 리턴
|
||||
* - power_control.c의 power_loop()에서 Step 0에서 호출됨
|
||||
*/
|
||||
/*==============================================================================
|
||||
* sw_i2c_init_once - Switch to SW bit-bang mode (legacy, unused)
|
||||
*
|
||||
* If HW mode is active, TWI is released first.
|
||||
* If SW mode is already active, returns immediately.
|
||||
*============================================================================*/
|
||||
void sw_i2c_init_once(void)
|
||||
{
|
||||
// HW 모드일 경우 강제 해제 후 SW 전환
|
||||
if (HW_I2C_FRQ)
|
||||
{
|
||||
//DBG_PRINTF("[I2C]HW→SW\r\n");
|
||||
|
||||
nrfx_twi_disable(&m_twi); /* TWI 비활성화 */
|
||||
nrfx_twi_uninit(&m_twi); /* TWI 초기화 해제 */
|
||||
nrf_delay_ms(2); /* 모드 전환 안정화 대기 (2ms) */
|
||||
|
||||
nrfx_twi_disable(&m_twi);
|
||||
nrfx_twi_uninit(&m_twi);
|
||||
nrf_delay_ms(2);
|
||||
HW_I2C_FRQ = false;
|
||||
}
|
||||
|
||||
// 이미 SW 모드면 재실행 금지
|
||||
if (SW_I2C_FRQ)
|
||||
{
|
||||
// DBG_PRINTF("[I2C] SWI2C already initialized\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* TWI 라인 완전 해제 후 SW 비트뱅 모드 진입 */
|
||||
// 실제 SW 초기화
|
||||
twi_uninitialize(); // TWI 라인 해제
|
||||
nrf_delay_ms(1); /* 해제 후 안정화 대기 (1ms) */
|
||||
twi_uninitialize();
|
||||
nrf_delay_ms(1);
|
||||
|
||||
/* 모드 플래그 갱신: SW 활성, HW 비활성 */
|
||||
SW_I2C_FRQ = true;
|
||||
HW_I2C_FRQ = false;
|
||||
|
||||
// DBG_PRINTF("[I2C] SW I2C Mode set!\r\n");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 전체 리셋 */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/*
|
||||
* 모든 I2C 모드 플래그를 초기화하는 함수.
|
||||
* HW/SW 모두 비활성 상태로 만들어, 다음 init 호출 시 강제로 재초기화되도록 한다.
|
||||
* 주로 시스템 리셋이나 에러 복구 시 사용.
|
||||
*/
|
||||
/*==============================================================================
|
||||
* i2c_reset_state - Clear all mode flags
|
||||
*
|
||||
* Forces re-initialisation on the next init call. Used for system reset
|
||||
* or error recovery.
|
||||
*============================================================================*/
|
||||
void i2c_reset_state(void)
|
||||
{
|
||||
HW_I2C_FRQ = false; /* HW 모드 플래그 초기화 */
|
||||
SW_I2C_FRQ = false; /* SW 모드 플래그 초기화 */
|
||||
HW_I2C_FRQ = false;
|
||||
SW_I2C_FRQ = false;
|
||||
DBG_PRINTF("Flags reset\r\n");
|
||||
}
|
||||
|
||||
@@ -1,50 +1,31 @@
|
||||
/*******************************************************************************
|
||||
* @file i2c_manager.h
|
||||
* @brief Common header for HW/SW I2C mutex control
|
||||
*******************************************************************************
|
||||
/*==============================================================================
|
||||
* i2c_manager.h - HW / SW I2C mutex control
|
||||
*
|
||||
* [헤더 개요]
|
||||
* I2C 버스 HW/SW 모드 전환 관리자의 공용 인터페이스 헤더.
|
||||
* Manages the mutually-exclusive HW TWI and SW bit-bang I2C modes.
|
||||
* Only one mode may be active at a time.
|
||||
*
|
||||
* - HW_I2C_FRQ: HW TWI 모드 활성 여부 (true = HW I2C 사용 중)
|
||||
* - SW_I2C_FRQ: SW 비트뱅 모드 활성 여부 (true = SW I2C 사용 중)
|
||||
*
|
||||
* 두 플래그는 상호 배제적으로 동작하며, 동시에 true가 되지 않도록 관리된다.
|
||||
*
|
||||
******************************************************************************/
|
||||
* Flags:
|
||||
* HW_I2C_FRQ : true when HW TWI mode is active
|
||||
* SW_I2C_FRQ : true when SW bit-bang mode is active
|
||||
*============================================================================*/
|
||||
#ifndef __I2C_MANAGER_H__
|
||||
#define __I2C_MANAGER_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "app_error.h"
|
||||
|
||||
/* I2C 모드 상태 플래그 (외부 참조용) */
|
||||
extern bool HW_I2C_FRQ; /* HW TWI 모드 활성 여부 */
|
||||
extern bool SW_I2C_FRQ; /* SW 비트뱅 모드 활성 여부 */
|
||||
extern bool HW_I2C_FRQ;
|
||||
extern bool SW_I2C_FRQ;
|
||||
|
||||
/**
|
||||
* @brief HW I2C(TWI) 모드 초기화 (중복 초기화 방지)
|
||||
*
|
||||
* SW 모드가 활성화되어 있으면 해제 후 HW로 전환한다.
|
||||
* 이미 HW 모드이면 아무 동작 없이 리턴한다.
|
||||
* ICM42670P IMU 센서 통신 전에 호출하여 HW I2C를 준비한다.
|
||||
*/
|
||||
/* Initialise HW I2C (TWI) mode. If SW mode is active it is released first.
|
||||
* No-op if HW mode is already active. Call before ICM42670P IMU access. */
|
||||
void hw_i2c_init_once(void);
|
||||
|
||||
/**
|
||||
* @brief SW I2C(비트뱅) 모드 초기화 (레거시, 현재 미사용)
|
||||
*
|
||||
* HW 모드가 활성화되어 있으면 TWI를 해제한 후 SW로 전환한다.
|
||||
* 이미 SW 모드이면 아무 동작 없이 리턴한다.
|
||||
*/
|
||||
/* Initialise SW I2C (bit-bang) mode (legacy, currently unused).
|
||||
* If HW mode is active it is released first. */
|
||||
void sw_i2c_init_once(void);
|
||||
|
||||
/**
|
||||
* @brief I2C 모드 플래그 전체 초기화
|
||||
*
|
||||
* HW_I2C_FRQ, SW_I2C_FRQ를 모두 false로 리셋한다.
|
||||
* 다음 init 호출 시 강제로 재초기화가 수행된다.
|
||||
*/
|
||||
/* Reset both mode flags to false, forcing re-initialisation on next call. */
|
||||
void i2c_reset_state(void);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user