임베디드에는 가상 메모리가 없나?
·
Embedded
지난번에 STM32F103C8T6 칩으로 고추건조기를 만든 임베디드 프로젝트를 진행했다. STM32F103C8T6 칩은 Cortex-M3 코어에 Flash 64KB, SRAM 20KB짜리 칩이다. 그때 프로젝트를 진행하면서 가졌던 의문이 하나 있었다. "얘는 가상 메모리가 없는 것 같은데?" 데스크톱에서 돌아가는 프로그램은 가상 주소 공간 위에서 동작한다. 프로세스마다 같은 가상 주소가 서로 다른 물리 주소로 매핑되고, 그 변환을 하드웨어가 처리한다. 그런데 이 칩의 펌웨어에서는 그런 변환 계층이 보이지 않았다. 데이터시트의 메모리 맵에 적힌 주소가 코드에서 쓰는 주소와 그대로 같았다. 찾아보니 이 칩에 가상 메모리가 없는 것은 맞았다. 다만 "임베디드에는 가상 메모리가 없다"로 일반화하면 틀린다는 것도..
[오제이 튜브 임베디드 강의] 외전. 최신 DS18B20 라이브러리로 고추건조기 리팩토링하기
·
Embedded
동기 — 왜 리팩토링을 시도하는가이 강의 시리즈에서 가장 고생했던 문제 중 하나가 FND와 온도 센서의 통신 충돌이었다. "쓰레드 흉내내기"부터 "드디어 해결된 크리티컬 문제"까지 세 글에 걸쳐 다뤘던 이 문제를 요약하면:TIM3 인터럽트(100μs 주기)에서 FND를 갱신하고, main 루프에서 DS18B20 온도 센서를 읽는 구조main에서 1-Wire 통신 중에 TIM3 인터럽트가 발생하면, FND의 SPI GPIO가 끼어들어 1-Wire 타이밍이 깨짐FND에 온도가 0으로만 표시되거나, 깜빡이는 현상 발생강의에서는 이전 버전 라이브러리의 소스를 직접 수정하여 해결했다. is_busy 플래그를 수동으로 추가하고, write_bit 단위까지 내려가서 실제 통신 구간에만 락을 걸었다. 동작은 했지만, ..
[오제이 튜브 임베디드 강의] 40. 클라스가 다른 ADC 강의
·
Embedded
가변 저항 회로 연결이전 글("너무나도 중요한 ADC")에서 ADC의 이론을 다뤘다. 이번에는 가변 저항을 이용하여 실제로 ADC를 사용한다.가변 저항은 돌리면 저항값이 변하고, 이에 따라 출력 전압이 변하는 부품이다. 3개의 핀이 있다.핀연결역할1번3.3V입력 전압2번PA2 (ADC 입력)가변 저항에 따라 0~3.3V 변화3번GND접지테스터기로 확인하면, 1번-3번 사이에 약 3.29V가 측정되고, 2번 핀의 전압은 가변 저항을 조절함에 따라 0V ~ 3.29V까지 변화한다. 이 가변 저항 대신 온도 센서, 습도 센서 등 다른 아날로그 센서를 연결하면 다양한 측정이 가능하다.ADC 설정.ioc 설정STM32CubeIDE에서 PA2를 ADC1 채널 2로 설정하고, 다음과 같이 옵션을 구성한다.설정 항목값..
[오제이 튜브 임베디드 강의] 39. 너무나도 중요한 ADC
·
Embedded
아날로그와 디지털ADC를 이해하려면 먼저 아날로그와 디지털의 차이를 알아야 한다.아날로그(Analog)는 물질이나 시스템의 상태를 연속적으로 변하는 물리량으로 나타낸 것이다. 예를 들어 온도를 그래프로 표현하면, 아무리 확대해도 그 사이에 모든 값이 연속적으로 존재하며 끊어지지 않는다. 디지털(Digital)은 연속적인 값을 0과 1로 표현하고 처리하는 방법이다. 아날로그처럼 모든 값을 저장하는 것은 불가능하므로, 중간 값들을 생략하여 저장한다. 이미지를 확대했을 때 픽셀이 깨지는 것이 대표적인 예다. 사람 눈에는 연결된 것처럼 보이지만, 사실은 빈 공간을 생략하고 촘촘하게 연결하여 아날로그를 흉내 내는 것이다. MP3, AVI, JPG 같은 파일들이 모두 아날로그 신호를 디지털로 변환한 결과물이다.AD..
[오제이 튜브 임베디드 강의] 38. 고추건조기 보드완성
·
Embedded
버튼 더블클릭 해결이전 글("보드 완성까지 두번 남았다")에서 버튼으로 온도를 설정하고 릴레이를 제어하는 기본 골격을 완성했다. 이번에는 디테일을 다듬어 실제 사용 가능한 수준으로 마무리한다. 첫 번째 문제는 버튼을 한 번 눌렀는데 여러 번 입력되는 현상(더블클릭/채터링)이다. 스위치 접점이 물리적으로 튀면서 인터럽트가 여러 번 발생하기 때문이다.소프트웨어적 해결HAL_GetTick()으로 이전 버튼 입력 시간을 저장하고, 현재 시간과의 차이가 200ms 미만이면 무시하도록 구현한다.// stm32f1xx_it.cstatic uint32_t m_button_before_time = 0;void EXTI0_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_..
[오제이 튜브 임베디드 강의] 37. 보드 완성까지 두번 남았다
·
Embedded
GPIO SPI → HW SPI 전환이전 글("드디어 완성되는 완전체 보드")에서 모든 모듈의 하드웨어 점검을 마쳤다. 이번에는 본격적인 코딩에 들어간다.첫 번째로 해결할 문제는 FND가 올바로 켜지지 않는 현상이다. 장치가 늘어나면서 MCU의 작업량이 증가했고, GPIO로 직접 SPI 신호를 만드는 방식으로는 FND 갱신에 필요한 타이밍을 안정적으로 유지하기 어려워졌다. 이전 글("STM32에서는 SPI 기능을 제공한다구")에서 다뤘듯이, GPIO SPI를 칩에서 제공하는 HW SPI(HAL_SPI_Transmit)로 전환하면 MCU의 부담이 줄어든다. FND 제어 코드의 send 함수를 HAL_SPI_Transmit 한 줄로 교체하고, init_fnd에 SPI 핸들러를 인자로 넘기도록 수정한다.// ..
[오제이 튜브 임베디드 강의] 36. 드디어 완성되는 완전체 보드
·
Embedded
완전체 보드의 목표지금까지 각 모듈을 개별적으로 다뤄왔다. 이번 강의에서는 모든 모듈을 하나의 보드에 통합하고, 각각이 정상 동작하는지 점검한다. 회로도 v4 기준으로 진행하며, 이전 버전과 핀 배치가 일부 변경되었으므로 주의가 필요하다.전체 핀 배치 요약모듈핀이전 글스위치 (Up/Fix/Down)PB0 / PB1 / PB2"내 힘으로 LED 회로 만들어서 제어하기"스위치 (Start)PB12-UART TXPA9"printf도 쉽지 않다구"LED × 2PB6 / PB7"내 힘으로 LED 회로 만들어서 제어하기"OLED (I2C)PB10(SCL) / PB11(SDA)"배운 I2C로 OLED를 제어해보자"온도 센서 (1-Wire)PA2 (v4에서 변경)"1-Wire 통신"FND (SPI)PB15(SCLK) ..
[오제이 튜브 임베디드 강의] 35. 내 로고는 내가 만든다
·
Embedded
OLED 로고 출력의 목표이전 글("배운 I2C로 OLED를 제어해보자")에서 SSD1306 라이브러리를 포팅하고, Fast Mode(400kHz)로 변경하여 OLED를 성공적으로 제어했다. 샘플 코드에 포함된 말 애니메이션과 Hello World가 출력되는 것을 확인했는데, 이번에는 샘플 이미지를 자신만의 로고로 교체한다.로고 이미지 제작OLED의 해상도가 128×64이므로, 로고 이미지도 128×64 픽셀로 만들어야 한다.그림판 등 이미지 편집 도구를 열고, 캔버스 크기를 128×64로 설정텍스트, 도형 등을 추가하여 원하는 로고를 디자인흑백(모노크롬)으로 저장 — OLED가 흑백이므로 색상은 의미 없음애니메이션 효과를 원한다면 여러 버전의 로고 이미지를 만들어둔다.비트맵 변환 — image2cpp만..
[오제이 튜브 임베디드 강의] 34. 배운 I2C로 OLED를 제어해보자!
·
Embedded
I2C 옵션 보충이전 글("이제는 쉬워진 I2C 통신")에서 I2C의 기본 개념을 다뤘다. 이번에는 실제 설정에서 만나는 옵션들을 보충한다.Fast Mode Duty Cycle이전 글에서 I2C는 Standard Mode(100kHz)와 Fast Mode(400kHz)가 있다고 다뤘다. Fast Mode에서는 Duty Cycle이 1:1이 아닌 1:2 또는 1:1.77로 설정된다. 400kHz는 1사이클이 2.5μs다. 이를 상승(High)과 하강(Low)으로 나누면 각각 1.25μs가 되어야 한다. 그런데 I2C를 정의한 NXP(구 필립스)의 사양에 따르면 Low 구간의 최소 유지 시간이 1.3μs 이상이어야 한다. 1.25μs로는 이 스펙을 충족하지 못하므로, Low 구간을 더 길게 잡아 1:2(Hi..