플래시 메모리 또는 SRAM이 부족하면 어떻게해야합니까?


28

Arduino 문서에 따르면 ATmega328에는 부트 로더 + 업로드 스케치 용 32KB 플래시 메모리와 런타임 데이터 용 2KB SRAM 만 있습니다. ATmega2560은 각각 256KB와 8KB로 훨씬 더 많습니다.

두 경우 모두, 특히 스마트 폰과 같은 비슷한 크기의 소비자 장치와 비교할 때 이러한 제한은 다소 작아 보입니다.

부족하면 어떻게 할 수 있습니까? 예를 들어 스케치가 너무 크거나 런타임에 많은 데이터 (예 : 문자열)를 처리해야합니까? 플래시 또는 SRAM을 확장 할 수있는 방법이 있습니까?


변수 최적화를 사용해보십시오. 일부 다른 변수는 논의 여기
TheDoctor

1
변수에 적절한 범위를 사용하지 않으면 변수를 사용하지 않으면 컴파일러에서 RAM 사용을 최적화합니다.
jippie 2012

1
실제로 Arsyino와 비슷한 Teensy 3.2 (Teensyduino 소프트웨어 포함)를 사용할 수 있습니다. RAM / PROGMEM이 부족하다는 것을 감안할 때 Arduino를 밀고있을 가능성이 있음을 의미합니다. Teensy 3.2는 그렇게 비싸지 않습니다. 32 비트, 72MHz (wtf !?) 256KB 플래시 및 64KB RAM 및 3x UART가 있습니다. ATmega2560만큼 더 많은 프로그램 메모리가 아니라 RAM과 속도 증가로 충분합니다.
Paul

답변:


30

최적화
임베디드 시스템의 저수준 프로그래밍은 컴퓨터 및 휴대폰과 같은 범용 장치의 프로그래밍과는 상당히 다릅니다. 자원은 매우 중요하기 때문에 효율성 (속도 및 공간 측면)이 훨씬 중요합니다. 공간이 부족한 경우 가장 먼저해야 할 일은 코드의 어떤 부분을 최적화 할 수 있는지 확인하는 것입니다.

프로그램 공간 (플래시) 사용을 줄이려면 경험이 부족하거나 해당 기술이 필요하지 않은 데스크톱 컴퓨터 프로그래밍에 더 익숙하다면 코드 크기를 최적화하기가 매우 어려울 수 있습니다. 불행히도 모든 상황에서 작동하는 '마법의 탄환'접근법은 없지만 스케치가 실제로 필요한 것을 진지하게 고려하면 도움 이됩니다. 기능이 필요하지 않은 경우 제거하십시오.

때로는 코드의 여러 부분이 동일한 (또는 매우 유사한) 위치를 식별하는 것이 도움이됩니다. 여러 곳에서 호출 할 수있는 재사용 가능한 기능으로 압축 할 수 있습니다. 그러나 때때로 코드를 너무 재사용 할 수있게 만들면 실제로는 더 장황하게됩니다. 연습에 따르는 경향이있는 파업은 까다로운 균형입니다. 코드 변경이 컴파일러 출력에 어떤 영향을 미치는지 살펴 보는 데 약간의 시간이 소요됩니다.

SRAM (런타임 데이터) 최적화는 익숙 할 때 약간 더 쉬운 경향이 있습니다. 초보자 프로그래머에게 가장 흔한 함정은 너무 많은 글로벌 데이터를 사용하는 것입니다. 전체 범위에서 선언 된 것은 스케치의 전체 수명 동안 존재하며 항상 필요한 것은 아닙니다. 변수가 하나의 함수 내에서만 사용되며 호출간에 지속될 필요가없는 경우 로컬 변수로 만듭니다. 함수간에 값을 공유해야하는 경우 전역으로 만드는 대신 매개 변수로 전달할 수 있는지 고려하십시오. 그렇게하면 실제로 필요할 때 해당 변수에 대해서만 SRAM을 사용하게됩니다.

SRAM 사용의 또 다른 킬러는 텍스트 처리 (예 : String클래스 사용)입니다. 일반적으로 가능하면 문자열 작업을 수행하지 않아야합니다. 그들은 거대한 메모리 호그입니다. 예를 들어 많은 텍스트를 직렬로 출력하는 경우 Serial.print()문자열 연결 대신 여러 번의 호출을 사용하십시오. 또한 가능한 경우 코드에서 문자열 리터럴 수를 줄이십시오.

가능하면 재귀를 피하십시오. 재귀 호출이 이루어질 때마다 스택의 레벨이 더 깊어집니다. 재귀 함수를 반복적으로 리팩토링하십시오.

EEPROM 사용 EEPROM
은 가끔 변경되는 것의 장기 저장에 사용됩니다. 큰 목록 또는 고정 데이터의 룩업 테이블을 사용해야하는 경우 사전에 EEPROM에 저장하고 필요한 경우 필요한 항목 만 꺼내십시오.

분명히 EEPROM은 크기와 속도가 상당히 제한되어 있으며 쓰기주기가 제한되어 있습니다. 데이터 제한에 대한 훌륭한 솔루션은 아니지만 플래시 또는 SRAM의 부담을 덜어주기에 충분할 수 있습니다. SD 카드와 같은 유사한 외부 저장소와 인터페이스하는 것도 가능합니다.

확장
다른 모든 옵션을 다 사용한 경우 확장이 가능할 수 있습니다. 불행히도 프로그램 공간을 늘리기 위해 플래시 메모리를 확장하는 것은 불가능합니다. 그러나, 이다 SRAM을 확장 할 수. 즉, 데이터 크기를 늘리는 대신 코드 크기를 줄이기 위해 스케치를 리팩터링 할 수 있습니다.

더 많은 SRAM을 얻는 것은 실제로 매우 간단합니다. 하나의 옵션은 하나 이상의 23K256 칩 을 사용하는 것 입니다. SPI를 통해 액세스되며 SpiRAM 라이브러리 가있어이를 사용하도록 도와줍니다. 5V가 아닌 3.3V에서 작동한다는 점에 유의하십시오 !

Mega를 사용하는 경우 Lagrangian Point 또는 Rugged Circuits 에서 SRAM 확장 쉴드를 얻을 수도 있습니다.


1
SRAM 공간 문제가 있고 사용 가능한 프로그램 메모리가있는 경우 SRAM 대신 프로그램 메모리에 상수 데이터를 저장할 수도 있습니다. 여기 또는 여기
코너 울프

1
EEPROM의 또 다른 훌륭한 대안은 SD 카드입니다. 몇 개의 IO 포트를 차지하지만 맵 데이터 또는 이와 유사한 공간이 필요하면 PC의 사용자 정의 프로그램으로 쉽게 교체하고 편집 할 수 있습니다.
Anonymous Penguin

1
메모리가 부족한 경우 SPI SRAM 또는 RAM 확장을 사용하도록 권장해서는 안됩니다. 그것은 단지 돈 낭비입니다. 더 큰 MCU를 선택하는 것이 더 저렴합니다. 게다가 성능이 매우 떨어질 수 있습니다. 예상되는 RAM 사용량이 한계에 너무 근접하면 잘못된 보드 / 마이크로 컨트롤러 / 개발 플랫폼을 선택하는 것입니다. 물론, 좋은 사용법 (문자열을 플래시에 저장)과 최적화 (일부 라이브러리 사용을 피하는 것)는 진정한 게임 체인저가 될 수 있습니다. 그러나이 시점에서 Arduino Software 플랫폼을 사용하면 이점이 없습니다.
next-hack

24

예를 들어 Uno와 같이 Arduino에 코드를 업로드하면 사용 가능한 32K 중 얼마나 많은 바이트를 사용하는지 알려줍니다. 그것은 당신이 가지고있는 플래시 메모리의 양입니다 (컴퓨터 하드 디스크를 생각하십시오). 프로그램이 실행되는 동안 SRAM이라는 것을 사용하고 있으며 사용 가능한 프로그램이 훨씬 적습니다.

때로는 한동안 만지지 않은 지점에서 프로그램이 이상하게 작동하는 것을 볼 수 있습니다. 최근 변경으로 인해 메모리 부족 (SRAM)이 발생할 수 있습니다. 다음은 일부 SRAM을 해제하는 방법에 대한 몇 가지 팁입니다.

SRAM 대신 Flash에 문자열 저장

내가 본 가장 일반적인 것 중 하나는 긴 문자열이 너무 많기 때문에 메모리가 부족한 칩입니다.

사용 가능한 F()문자열이 훨씬 많으므로 문자열을 사용할 때이 함수를 사용하여 SRAM 대신 Flash에 저장하십시오.

Serial.println(F("This string will be stored in flash memory"));

올바른 데이터 유형을 사용하십시오.

int(2 바이트)에서 byte(1 바이트) 로 전환하여 바이트를 저장할 수 있습니다 . 부호없는 바이트는 0-255를 제공하므로 255보다 크지 않은 숫자가 있으면 바이트를 저장하십시오!

메모리가 부족하다는 것을 어떻게 알 수 있습니까?

일반적으로 프로그램이 이상하게 작동하는 것을 관찰하고 무엇이 잘못되었는지 궁금해합니다. 코드가 엉망인 지점 근처에서 아무것도 변경하지 않았으므로 무엇이 제공됩니까? 메모리가 부족합니다.

사용 가능한 메모리 양을 알려주는 몇 가지 기능이 있습니다.

사용 가능한 메모리


F()아두 이노 전용 기능인지 아니면 AVR 라이브러리에 있는지 알고 있습니까? 당신 PROGMEM const ...도 언급을 고려할 수 있습니다.
jippie

또한 비트 구조를 사용하여 변수가 사용하는 공간을 더 줄일 수 있습니다 (예 : 부울을 많이 처리하는 경우).
jfpoilpret

17

다른 사람들이 말한 것 외에도 (나는 완전히 동의 한 것), 나는 기억에 관한 이 adafruit 기사 를 읽는 것이 좋습니다 ; 잘 작성되고 메모리에 대해 많은 것을 설명하고 메모리를 최적화하는 방법에 대한 힌트를 제공합니다.

읽기가 끝나면 귀하의 질문에 대한 완전한 답변을 얻을 것이라고 생각합니다.

요약하면 메모리 문제가있는 위치에 따라 두 가지 가능한 최적화 대상이 있습니다.

  • 플래시 (즉, 프로그램 메모리); 이를 위해 다음을 수행 할 수 있습니다.
    • 데드 코드 (예 : 포함되었지만 사용되지 않은 코드) 및 사용되지 않은 변수 (SRAM에도 도움이되는 변수)를 제거합니다.
    • 중복 된 코드를 제거
    • 부트 로더를 완전히 제거하십시오 (UNO의 경우 0.5K, 다른 Arduino 모델의 경우 2 또는 4K를 얻을 수 있음). 이것은 몇 가지 단점이 있지만
  • SRAM (즉, 스택, 힙 및 정적 데이터); 이를 위해 당신은 할 수 있습니다 :
    • 사용하지 않는 변수 제거
    • 각 변수의 크기를 최적화하십시오 (예를 들어 int -2 바이트 만 필요한 경우 긴 -4 바이트를 사용하지 마십시오)
    • 변수에 올바른 범위를 사용하고 가능한 경우 정적 데이터보다 스택을 선호하십시오.
    • 버퍼 크기를 최소로 줄입니다.
    • 상수 데이터를 PROGMEM으로 옮깁니다 (즉, 정적 데이터는 플래시 메모리에 유지되며 프로그램 시작시 SRAM으로 복사되지 않습니다). F()매크로 를 사용할 수있는 상수 문자열에도 적용됩니다 )
    • 절대적으로 필요하지 않은 경우 동적 할당을 피하십시오. 메모리를 비운 후에도 축소되지 않는 조각난 힙 을 피할 수 있습니다.

SRAM 사용을 줄이는 추가 접근 방법도 설명되어 있지만 (코딩시 약간 무겁고 효율적이지 않기 때문에 거의 사용되지 않음) EEPROM을 사용하여 프로그램에서 작성된 데이터를 저장하지만 나중에는 일부 조건에서 사용되지 않습니다. EEPROM에서 데이터를 다시로드 할 수있을 때 발생합니다.


1
죽은 코드 제거-컴파일러는 이것을 처리하는 데 정말 좋습니다. 호출되지 않은 코드가 많더라도 아무런 차이가 없습니다. 실수로 필요하지 않은 코드를 호출하면 물론 다릅니다.
dethSwatch

9

스토리지가 부족한 경우 두 가지 조치가 있습니다.

  • 어떻게 든 코드를 "최적화"하여 저장 공간이 적게 필요합니다. 또는 최소한 부족한 특정 종류의 스토리지를 적게 사용합니다 (여전히 많은 종류의 스토리지를 사용합니다). 또는,
  • 저장 용량을 추가하십시오.

온라인으로 첫 번째 작업을 수행하는 방법에 대한 많은 팁이 있습니다 (그리고 사람들이 Arduino를 사용하는 대부분의 경우 내장 스토리지는 "최적화"후에 충분합니다). 그래서 두 번째에 중점을 둘 것입니다.

플래시 또는 SRAM을 사용하는 세 가지가 있습니다. 각각 스토리지를 추가하는 데 약간 다른 접근 방식이 필요합니다.

  • 가변 스토리지 : Sachleen이 이미 지적했듯이 SRAM을 확장 할 수 있습니다. SRAM, FRAM 및 NVSRAM 은 모두 빠르게 변하는 변수에 적합합니다. 원칙적으로 플래시를 사용하여 변수를 저장할 수 있지만 플래시 마모에 대해 걱정해야합니다. SPI (직렬 프로토콜)는 Arduino에 연결하는 가장 쉬운 방법입니다. SpiRAM 라이브러리는 마이크로 칩과 함께 작동 23K256 시리얼 SRAM 칩. Ramtron FM25W256 직렬 FRAM 칩 (현재 Cypress 소유)도 SPI를 사용합니다. Cypress CY14B101 NVSRAM 도 SPI를 사용합니다. 기타.

  • 다음에 전원을 켤 때 계속 있어야하는 일정한 데이터 : SRAM을 확장하는 것만큼이나 간단합니다. 사용 가능한 외부 EEPROM, FRAM, NVSRAM 및 FLASH 저장 장치가 많이 있습니다. 현재 MB 당 최저 비용은 SD 플래시 카드 (SPI를 통해 액세스 할 수 있음)입니다. Ramtron FM25W256 (위 참조), Cypress CY14B101 (위 참조) 등도 상수 데이터를 저장할 수 있습니다. 많은 확장 쉴드에는 SD 카드 슬롯이 포함되어 있으며 여러 라이브러리자습서 는 SD 카드 읽기 및 쓰기를 지원합니다. (SRAM은 전원이 꺼지면 모든 것을 잊기 때문에 SRAM을 사용할 수 없습니다).

  • 실행 코드 : 불행히도 Arduino의 플래시 메모리를 확장하여 프로그램 공간을 늘릴 수는 없습니다. 그러나 프로그래머는 항상 데이터 크기를 늘리고 약간 느리게 실행하여 코드 크기를 줄이기 위해 스케치를 리팩터링 할 수 있습니다. 이론적으로 전체 스케치를 해석 가능한 언어로 번역하고 해당 스케치 버전을 SD 카드에 저장 한 다음 Arduino에서 실행되는 해당 언어의 인터프리터를 작성하여 SD 카드 -Arduino , BASIC 통역사, Tom Napier Picaro 통역사, 응용 프로그램 별 언어 등).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.