anhy0923
HY's Embedded LAB
anhy0923
전체 방문자
오늘
어제
  • 분류 전체보기 (67)
    • UDS 진단통신 (1)
    • FreeRTOS (2)
    • ROS2 (5)
    • [EH전공] CAN 통신 (1)
    • C언어 튜터링: C로 로봇을 파헤쳐보자! (4)
    • [졸업작품] 외벽 균열 검사 로봇 (8)
      • 2021-2 <종합설계기획> (7)
      • 2022-1 <종합설계1> (1)
      • 2022-2 <종합설계2> (0)
    • TCP 기반 제어시스템 (7)
      • Robot Arm Control (5)
      • RPi CCTV Server (2)
    • Embedded System (6)
      • Linux (3)
      • Linux - Ubuntu (2)
      • RPi (1)
    • Drone FW using STM32CubeIDE (25)
      • 0. Intro (2)
      • 1. Debug (3)
      • 2. Sensor Interface (4)
      • 3. GPS (4)
      • 4. Transmitter_Receiver (3)
      • 5. Drone Body Asb (1)
      • 6. ESC Protocol (4)
      • 7. EEPROM (2)
      • 8. GCS (1)
      • PID Control (1)
    • Elec Academy (3)
    • HAL & LL Driver (1)
    • OpenCV - Lane Detection (1)

블로그 메뉴

  • 홈
  • 방명록

티스토리

hELLO · Designed By 정상우.
anhy0923

HY's Embedded LAB

[Drone Firmware using STM32CubeIDE] 7-1. EEPROM: AT24C08
Drone FW using STM32CubeIDE/7. EEPROM

[Drone Firmware using STM32CubeIDE] 7-1. EEPROM: AT24C08

2021. 8. 15. 21:48

 PID 제어 시에 드론의 게인값을 저장하기 위하여 메모리 공간이 필요한데, FC에는 비휘발성 메모리인 EEPROM이 내장되어 있다. 내장되어 있는 EEPROM은 AT24Cxx 시리즈 중 'AT24C08'으로 1Kbytes의 용량을 가진다. AT24Cxx 데이터시트를 참고하여 AT24C08의 스펙을 살펴보자.

 

EEPROM: AT24C08

 

 

  • 비휘발성 메모리
  • AT24Cxx 이 뒤의 숫자가 용량을 의미 (kbits) 
  • AT24C08 -> 8kbits -> 1Kbytes
  • 내부적으로 64개의 pages로 영역을 구분
  • 1page당 16bytes의 크기를 가짐.
  • I2C Interface (MAX 400kHz @ 3.3V)
  • 쓰기금지 (WP) 핀 제공 (데이터 보호)
  • AT24C04 이상부터는 Page Write Mode로 Write할 때 16bytes단위로 쓰기 해야함!
  • 100만번 쓰고지울 수 있고, 100년동안 저장 가능 -> 반 영구적

 

 

 


Memory Organization

 AT24C08의 메모리 구조는 16Bytes로 이루어진 하나의 페이지가 총 64페이지로 구성되어 있다. 즉 메모리의 총 용량은 16 x 64 = 1024 = 1KBytes 이다. 또한 1바이트당 메모리 주소 1번지를 차지하므로 0~1023번지의 메모리 주소를 표현하기 위해, 즉 1024가지의 주소를 표현하기 위해서는 10bit(2^10 = 1024) 가 필요하다.

 

 


Pin Description

 AT24C08은 I2C로 인터페이스 한다. I2C로 인터페이스 하는 장치는 장치 주소(Device Address)와 내부 메모리 주소(Register Address / Word Address)를 가진다. 장치 주소는 I2C 통신을 하는 많은 슬레이브 장치들을 구분하기 위한 주소이고 내부 메모리 주소는 통신할 대상 장치에서 어떤 메모리 영역과 통신을 할건지 구분하는 주소이다. 

  AT24Cxx는 Device Adress Pin으로 A0, A1, A2 핀이 있다. 그 중 AT24C08의 경우 A2 핀만 쓰고 나머지 A0와 A1는 사용하지 않는다. 따라서 이 핀들은 내부적으로 GND에 연결한다. 이 EEPROM은 FC와 I2C로 통신하므로 I2C 통신 핀인 SDA, SCL핀이 있다. 그리고 쓰기 금지 모드를 설정하는 Write Protect (WP) Pin이 있다. 이 핀에 HIGH를 넣어주면 쓰기 금지 모드가 설정되고 LOW를 넣어주면 쓰기 금지 모드가 해제된다. 

 


Device Addressing

 I2C로 통신하는 각각의 장치는 통신할 대상 장치를 구분하는데에 장치 주소(7bit)를 사용한다. AT24C08의 경우는 장치 주소와 내부 메모리 주소의 개념이 섞여있다. 먼저 장치 주소 Device Address의 구조는 아래와 같다.

 8Kbits EEPROM인 AT24C08 기준으로 Device Address는 총 8비트지만, 실질적인 장치 주소의 역활은 A2 비트까지인 5비트이다. 그 뒤로 오는 P1, P0 비트는 SDA Line에서 Device Address 다음으로 올 Word Address(혹은 Page Address)의 상위 2비트를 의미한다. 앞서 0부터 1023번지까지의 주소를 표현하기 위해서는 총 10비트 (2^10 = 1024가지) 가 필요하다고 언급하였다. 8bit, 즉 한 바이트 씩 끊어서 통신을 하므로 이 한 바이트 안에 10bit를 모두 넣을 수 없기 때문에 Device Address의 두 비트를 빌려온 셈이다. 또한 Device Address의 마지막 비트인 R/W 비트는 I2C 통신의 읽기 혹은 쓰기를 결정하는 비트이다. 0이면 읽기, 1이면 쓰기가 된다. Device Address와 Word Address의 구조는 다음과 같다.

8Kbits EEPROM's Device Address Structure (AT24C08)


Write Operations

 AT24C08 EEPROM에 데이터를 쓰는 방식에는 두 가지가 있는데, Byte 단위로 쓰는 Byte Write 모드와 Page 단위로 쓰는 Page Write 방식이 있다. 그 중 Page Write 방식으로 데이터를 EEPROM에 쓰기할 것이다. Page 단위로 데이터를 쓸 시, 주의해야할 사항이 있다!

 Page Write 모드로 데이터를 연속적을 쓸 때, 페이지의 경계를 넘어가면 다음페이지의 첫 바이트부터 기록하는 것이 아닌 같은 페이지의 시작 바이트부터 덮어써진다. 즉, 쓰고자 하는 페이지의 첫 바이트부터 덮어써진다는 것(overwritten)이다!! 예를 들면, 20바이트의 데이터를 쓰고자 할때, Page Write 모드로 데이터를 쓰기하면 첫 16바이트를 해당 페이지에 기록하고 나머지 4바이트는 방금 기록한 페이지의 첫 4바이트 위에 덮어써진다는 의미이다. 이를 Roll over 현상이라 하는데, 이를 방지하기 위해 16바이트 단위, 즉 Page 단위로 메모리에 접근하고 데이터를 써야한다. 

 

다음은 Page Write 모드로 쓰기 동작을 할 때, SDA 핀의 전기적인 Sequence를 나타낸 그림이다. 

 

 I2C 통신은 START 비트, 장치 주소, 메모리 주소, R//W비트, 바이트 단위마다 ACK 신호, STOP 비트 등등, 통신 구조가 다소 복잡하다. 원래 이 모든 과정을 한 비트씩 코드로 다 구현을 해야한다. 하지만 CubeIDE의 HAL 드라이버는 이를 구현한 시퀀스 함수를 제공한다. 따라서 I2C 통신은 HAL 드라이버를 이용하여 코드를 작성한다. LL 드라이버는 I2C 통신의 기본적인 함수를 제공하지 않아, 모든 통신 시퀀스를 직접 다 작성해줘야 한다.

 

 HAL 드라이버를 사용하여 I2C 통신 시, 메모리 영역에 바이트 단위로 접근하기 때문에 short, int, float, double 등과 같은 여러 바이트로 이루어진 데이터 형태는 반드시 바이트 단위로 쪼개서 저장해야 한다. 특히 실수 형태의 경우 비트연산이 불가하므로 주의가 필요하다.

 


 Read Operations

 읽기 모드 역시 Roll over 현상이 있긴 하지만, 이는 Page 단위가 아닌 메모리의 끝에서 처음으로 넘어가서 읽어지는 것이므로 쓰기 동작 보다는 Roll over 현상을 크게 고려할 여지가 적다. 

SDA Line's Electrical Sequence in Random Read Mode 

 

 이상으로 Atmel사의 EEPROM인 AT24C08 에 대해 알아보았다. 더 자세한 스펙은 데이터시트에서 찾을 수 있다.

AT24Cxx.PDF
0.43MB

 


Connecting AT24C08 to I2C

 AT24C08은 FC에 내장되어 있다. A0, A1, A2는 모두 GND에 연결되어 있고, I2C 통신에 필요한 SDA, SCL 핀과 쓰기 금지 모드 설정 핀인 WP 핀만 FC와 연결해주면 된다. 핀 연결은 다음과 같다.

AT24C08   STM32F405 Port
SCL  ↔  SCL1 PB8
SDA  ↔  SDA1 PB9
WP  ↔  GPIO - Output PC13

 WP핀은 FC의 회로도 상에서 3.3V 전원에 풀업으로 연결되어 있다. 따라서 외부에서 신호가 들어오지 않으면 기본적으로 쓰기 금지 모드가 활성화 된다는 것을 의미한다. 

 I2C 1번채널을 사용하며 I2C 1번 채널은 APB1 버스에 연결되어 있다. 또한 STM32F405가 Master로 동작하므로 Slave Features는 설정 안해도 무관하다. 

 


CubeMX Code Generation

 이제 CubeIDE에서 코드를 생성해보자.

 

 먼저 I2C 1번채널에 대한 설정이다. I2C 1번채널을 설정하면 Pinout view에서 기본적으로 PB8이 SCL, PB9가 SDA로 활성화 된다. 이를 그대로 사용한다. 파라미터 설정에선 스피드 모드를 Fast Mode로 설정한다. Fast Mode로 설정하면 Clock speed가 400kHz로 설정된다.

 

 앞서 I2C 통신은 HAL 드라이버로 구현한다고 하였다. Project Manager Tab의 Advanced Settings에서 I2C1을 HAL 드라이버로 설정한다.

 

 다음은 WP(Write Protection)핀으로 설정할 PC13 에 대한 설정이다. GPIO_Output 모드로 설정하고 기본 출력 레벨을 High로 설정한다. 

 

 CubeMX 설정이 끝났다. 다음으로 HAL 드라이버로 생성된 i2c.c 파일을 확인하여 앞서 설정한 파라미터들로 잘 설정되었는지 확인해보자.

 

i2c.c

 CubeMX의 HAL 드라이버로 생성된 i2c.c 파일은 다음과 같다.

 앞서 설정한 파라미터 대로 잘 설정된 것을 확인할 수 있다.

 30번째 줄에서 시작하는 MX_I2C1_Init() 함수에서 49번째 줄에 HAL_I2C_Init(&hi2c1) 함수가 있는데, 이 함수 내부에서 내부적으로 오른쪽 사진에 있는 HAL_I2C_MspInit() 함수가 호출된다.

 


Write Data to EEPROM & Read Data from EEPROM

 이제 EEPROM에 데이터를 써보고 EEPROM으로부터 데이터를 읽어와보겠다. 먼저 EEPROM에 아무 데이터도 쓰지 않은 상태에서 EEPROM에서 데이터를 읽어오면 다음과 같이 255가 읽어와진다. 

 

 이번엔 EEPROM에 데이터를 쓰고 쓴 데이터를 읽어와 볼 것이다. 먼저 WP 핀을 고려해야한다. 초기 설정에서 WP핀은 High로 설정하였다. 즉, 쓰기 금지 모드로 초기화 되어있다. 이 상태에서 EEPROM 데이터를 쓰면 EEPROM에 데이터가 기록되지 않는다. 따라서 먼저 WP을 Low로 설정하고 데이터를 EEPROM에 써야한다.

unsigned char buf_write[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
unsigned char buf_read[16] = {0};

LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_13); // WP - LOW
HAL_I2C_Mem_Write(&hi2c1, 0xA0, 0x00, I2C_MEMADD_SIZE_8BIT, &buf_write[0], sizeof(buf_write), 1);
HAL_Delay(1);
LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_13); // WP - HIGH

HAL_I2C_Mem_Read(&hi2c1, 0xA0, 0x00, I2C_MEMADD_SIZE_8BIT, &buf_read[0], sizeof(buf_read), 1);

for (int i=0; i<16; i++) printf("%d ", buf_read[i]);

 앞으로 EEPROM의 쓰기와 읽기는 Page 단위로 할 것이다. 한 Page는 16Bytes로 구성되어 있다. 즉, 한 Page에 기록할 수 있는 용량은 16바이트로 이는 char형 변수 16개 기록이 가능하다. EEPROM에 쓰고 읽을 변수를 unsigned char 형태로 선언한다.

 Write 함수와 Read 함수의 두번째, 세번째 파라미터는 각각 Device Address, Page Address로 0xA0, 0x00으로 설정하였다. 이렇게 설정하면 0번지에 데이터를 쓰고 읽게 된다. 앞서 Page Address는 총 10bit로 표현되는데 상위 2bit는 Device Address의 2bit를 사용한다고 하였다. 이를 잘 고려하여 정확한 번지수를 비트단위로 분석한 후 16진수로 표현하여 파라미터를 넣어줘야 한다. (꼭 16진수로 파라미터 입력할 필요는 없지만 16진수 표현이 간결하다.)

 

 위와 같이 소스코드를 작성한 후 실행을 시키면 다음과 같이 출력된다. 

 

 

 

'Drone FW using STM32CubeIDE > 7. EEPROM' 카테고리의 다른 글

[Drone Firmware using STM32CubeIDE] 7-2. EEPROM Protocol Definition  (0) 2021.08.17
    'Drone FW using STM32CubeIDE/7. EEPROM' 카테고리의 다른 글
    • [Drone Firmware using STM32CubeIDE] 7-2. EEPROM Protocol Definition
    anhy0923
    anhy0923

    티스토리툴바