개발/C와 C++

[c/c++] PSTR(), F() 플래시 메모리에 값 저장

어중E 2022. 10. 30. 21:58

[c/c++] PSTR(), F() 플래시 메모리에 값 저장

아두이노나 다른 보드에서 메모리를 저장하는 부분은 SRAM과 FLASH로 나뉘어 있다고 보시면 됩니다.

 

FLASH는 동작할 코드들이 저장되며, 컴퓨터에서 디스크(HD, SSD)에 해당됩니다. SRAM은 각종 변수가 저장되며, 컴퓨터의 RAM에 해당됩니다. 따라서 FLASH보다 용량이 적습니다.

 

아두이노의 공식사이트(https://www.arduino.cc/en/Tutorial/Foundations/Memory)에 따르면 아두이노의 메모리는 아래와 같이 되어 있습니다.

보시다시피 보통 FLASH에 비해 SRAM은 아주 작은 용량임을 알 수 있습니다.

 

실제로 코딩을 하다가 변수가 많이 사용되거나, 긴 문자열이 사용될 때에는 SRAM이 부족할 경우가 생깁니다. 이런 경우에 FLASH 메모리의 용량을 빌려 쓸 수 있는 방법이 있습니다.

 

먼저 아두이노, C/C++에서 사용되는 것으로는 PROGMEM이 있습니다.

const char str[] PROGMEM = "hellow world";
const PROGMEM char str[] = "hellow world";
const char PROGMEM str[] = "hellow world";

이와 같이 작성해주면 str 변수와 저장되는 문자열은 FLASH 메모리에 저장이 됩니다. 위의 코드 모두 동일한 효과를 냅니다.

 

Serial.println(FV(str));

이를 출력할 때에는 위와 같은 코드로 FV(str)로 사용하면 됩니다. FV는 (const __FlashStringHelper *)를 뜻하는 매크로로 보시면 됩니다. 이는 FLASH 메모리에 저장된 것을 불러올 때 필요한 코드입니다.

 

또 다른 방법으로는 PSRT 매크로를 사용하는 것입니다.

 

Serial.printf_P(PSTR("hellow world"));

문자열 변수를 만들지 않고, 매개변수로 사용되는 곳의 문자열을 FLASH에 저장할 때는 위와 같이 PSTR을 사용합니다. PSTR은 FLASH 메모리에 문자열을 저장하고, 주소 값을 반환합니다. 따라서 주소 값만으로는 print 함수를 사용해서 출력할 수가 없습니다.

 

그렇기 때문에 printf_P라는 함수와 함께 사용해서 FLASH 메모리에 저장된 문자열을 출력합니다.

 

마지막 방법으로는 F매크로가 있습니다.

Serial.print(F("hellow world"));

PSTR은 주소 값을 반환하기 때문에 print에 못쓴다고 했습니다. 다만 매개변수로 문자열만을 입력해야되는 함수에서는 F라는 매크로를 사용할 수 있습니다. 두번째 방법인 printf_P, PSTR을 사용하는 것과 동일한 효과를 가집니다.

 

#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))

F는 PSTR의 주소값을 사용하여, 해당 주소의 값에 저장된 값을 가져오는 매크로로 되어 있습니다.