키보드를 만듭시다. 어때요~ 참 쉽죠? (12)

나빌레라의 이미지

FAT16 데이터를 펌웨어에서 만들어서 운영체제에 보내면 드라이브로 마운트 된다. 그러면 사용자는 키맵 바이너리나 펌웨어 바이너리를 직관적이고 단순하게 그냥 복사하면 된다. 펌웨어는 파일 데이터만 내장 플래시 메모리에 저장하고 그 데이터를 잘 쓰는 것이다. 이 과정에서 펌웨어는 사용자가 보낸 데이터가 키맵인지 펌웨어인지 구분해야 한다. 우선 키맵을 어떻게 구분할지 방법을 궁리해 보자.

키맵 바이너리 위치 지정

STM32F103은 내장 플래시 메모리로 64KB 혹은 128KB를 갖고 있다. 왜 '혹은' 이라고 썼나면, 구입하는 보드마다 용량이 달랐기 때문이다. 분명 세부 모델 별로 내장 플래시 메모리 용량차이가 있을텐데 데이터 시트를 봐도, 64KB, 128KB 라고 숫자 두 개를 같이 표기해 놓고 어떤 모델이 64KB인지 128KB인지 설명을 찾을 수 없었다. 내가 못 찾는 거겠지. 아무튼 내장 플래시 메모리 용량이 두 배나 차이남에도 가격 차이는 별로 없는지 STM32F103 칩을 사용한 보드를 세 장 샀는데 두 장은 128KB였고 한 장은 64KB였다. 중국에서 만든거라 대중없이 아무렇게 쓰는 것 같다.

그래서 그냥 64KB 용량에 맞춰서 디자인하기로 결정했다. 그럼 다 될테니까. 내장 플래시 메모리는 NOR 타입으로 플래시 메모리에서 바로 명령어 실행이 가능하다. 그래서 내장 플래시 메모리의 주 용도는 펌웨어 저장 및 실행이다. 나는 펌웨어를 저장하고 남는 공간 중 일부에 키맵을 저장해서 쓰기로 했다.

이 시점에서 펌웨어 바이너리 크기는 17KB 였다. 그래서 아래처럼 메모리 맵을 구성했다.

  • 전체 64KB
    • 펌웨어: ~ 63KB
    • 키맵 : 63KB ~ 64KB

즉, 큰 고민 없이 플래시 메모리 제일 마지막 한 페이지만 키맵용으로 쓰기로 한 것이다. 내장 플래시 메모리 페이지 사이즈는 1KB이고 키맵 파일은 몇 백 바이트 수준으로 크기가 작기 때문에 1KB면 충분한 크기다.

키맵 파일은 어떻게 구분해야 할까

운영체제에서 파일을 던지면 파일 내용을 디바이스로 전송한다. 그 내용은 파일의 메타 정보도 포함한다. 메타 정보란 별게 아니라 파일 이름, 생성 날짜, 수정 날짜 이런 것들이다. 중요한건 디바이스 펌웨어는 파일 이름도 알 수 있다는 것이다. 그래서 가장 단순하게 파일 이름이 예를 들어 keymap.dat 이런식이면 키맵 파일로 간주하고 데이터를 키맵 영역에 저장하는 식으로 만들 수 있다. 나쁘지 않은 방식이다.

방법을 조금 달리하면 펌웨어가 하는 일을 두 개(파일 이름 확인, 데이터 확인)에서 한 개로 줄일 수 있다. 어떻게 하냐면, 파일 데이터 특정 위치에 정해 놓은 데이터 시퀀스를 적어 놓는 것이다. 보통 이 정해 놓은 데이터 시퀀스를 매직 스트링(magic string) 혹은 매직 택스트(magic text) 혹은 매직 시그니처(magic signature)라고 한다. 아무튼 매직 어쩌구다. 그리고 또 보통은 이 매직 문자를 파일 시작 부분에 놓는다. 그래야 찾기 편하고 실제 데이터와 섞이지 않으니까.

매직 문자를 쓰면 펌웨어는 파일 이름은 신경 쓰지 않아도 된다. 데이터 시작이 매직 문자인 파일이 들어오면 그냥 키맵 데이로 간주하면 된다. 매직 문자는 아무거라도 상관 없다. 000000이라든가 FFFFFFF 같은 것만 피하면 된다. 되도록이면 대충 랜덤하게 고르면 된다.

그래서 최종적으로 키맵 데이터를 추상화하는 자료 구조는 아래 코드와 같다.

typedef struct KeymapFile
{
    uint32_t    magic_high;
    uint32_t    magic_low;
    uint32_t    crc;
    uint8_t     keymap[NUM_LAYERS][TOTAL_KEY_MAP_SIZE];
} KeymapFile_t;

키맵 데이터 시작 부분에 매직 문자를 넣기로 했으므로 CRC32 값 위에 매직 문자로 4바이트를 넣었다.

키맵 다운로드 절차

FAT16 제어 코드에서 파일 쓰기(write)하는 코드에 키맵을 판별하는 코드를 추가하면 된다. 먼저 코드를 보자

         KeymapFile_t* checkKeymap = (KeymapFile_t*)data;
            uint32_t* checkMainFw = (uint32_t*)data;
            if ((checkKeymap->magic_high == KEYMAP_MAGIC_H_WORD) && (checkKeymap->magic_low == KEYMAP_MAGIC_L_WORD))
            {
                debug_printf("Keymap download\n");
                WriteKeyMapToFlash((uint8_t*)checkKeymap, FLASH_PAGE_SIZE);
                FATSetStatusFileName("SUCCESS ");
                debug_printf(">>> Done\n");
                return len;
            }
            else if (*checkMainFw == firstWordOfMainFw)
            {
                debug_printf("MainFW download\n");
                tempflashStartPage = MAIN_FW_PAGENUM;
                startCopy = true;
            }
            else
            {
                FATSetStatusFileName("UNKOWN  ");
                return len;
            }

호스트에서 데이터가 들어올 때 첫 번째 섹터인 경우에 검사를 한다. 현재 들어온 데이터가 첫 번째 섹터라면 데이터의 첫 4바이트를 매직 문자와 비교한다. 매직 문자는 키맵 에디터와 펌웨어가 서로 같은 값을 써야한다. 키맵 에디터에서 키맵 데이터 파일을 만들 때 미리 넣어 놔야 한다.

첫 번째 섹터 데이터의 첫 4바이트 데이터가 키맵 매직 문자와 같다면, 펌웨어는 이 데이터를 키맵으로 간주한다. 그래서 데이터의 목적지 섹터 주소를 63으로 지정한다. 계속 반복하지만 STM32F103의 내장 플래시 메모리 섹터 사이즈는 1KB기 때문에 섹터 주소를 63으로 지정하면 내장 플래시 메모리에 63KB위치에 데이터가 저장된다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.