외부 RAM에서 실행할 코드 컴파일


13

PIC18F85J5 기반의 미니멀리스트 게임 시스템을위한 디자인을 고려하고 있습니다 . 내 디자인의 일부는 칩을 다시 프로그래밍하거나 프로그램 메모리를 플래시하지 않고 SD 카드에서 게임을로드 할 수 있다는 것입니다. 외부 SRAM에서 코드를 실행할 수있는 외부 메모리 인터페이스가 있기 때문에 해당 칩을 선택했습니다.

기본 아이디어는 내부 프로그램 메모리에 sd 카드를 찾아보기위한 인터페이스가 포함되어 있고 사용자가 프로그램을 선택하면 16 진수 파일을 sd 카드에서 외부 램으로 복사 한 다음 실행을 외부 램 공간으로 옮깁니다. .

내부 프로그램 메모리에는 그래픽, 컨트롤러 입력 및 기타 다양한 유틸리티를위한 다양한 라이브러리가 있습니다.

내부 펌웨어 부품을 올바르게 작동시키는 방법을 알고 있다고 확신합니다. 문제는 외부 RAM에서 실행할 프로그램을 만드는 것입니다. 일반 사진을 대상으로하는 것과 같은 느낌이 들지 않으며 내부 메모리에서 사용 가능한 라이브러리 기능을 알고 있어야하지만 다시 컴파일하지 말고 링크 만하면됩니다. 또한 0이 아닌 32k 내부 플래시 직후 주소를 사용해야합니다. 이러한 유형의 제약 조건을 사용하여 프로그램을 컴파일하는 좋은 방법이 있습니까?

MPLab IDE를 사용하고 있지만 익숙하지 않거나 이러한 종류의 사용자 지정을 수행하는 방법에 익숙하지 않습니다.


내가 여기서 본 최고의 질문 중 하나는 ... 아이디어와 답변을 기다리겠습니다.
Jon L

흥미로운 대안이 몇 가지 더 있습니다. electronics.stackexchange.com/questions/5386/…
Toby Jaffey

나는 그것을 보았지만 대부분 플래시로 쓰는 것을 권장합니다. 피하고 ​​싶습니다. 내 하드웨어 디자인은 승인 된 답변의 애플리케이션 노트에있는 그림 6과 비슷합니다.
captncraig

답변:


8

두 가지 별도의 문제가 있습니다.

  1. 외부 RAM 주소 범위에 대한 코드 작성

    이것은 실제로 매우 쉽습니다. 코드가 차지할 주소 범위 만 포함하는 링커 파일을 만들면됩니다. 이러한 외부 앱을 위해 특정 프로그램 메모리 주소 범위를 예약 할뿐만 아니라 일부 RAM 공간을 예약해야합니다. 이 RAM 공간은 프로그램 메모리 주소와 같이 고정되어 있어야합니다. 링커 파일에서 사용할 수있는 고정 및 알려진 주소 범위 만 사용하십시오. 기본 코드 링커 파일에서 사용할 수 없도록하는 것을 잊지 마십시오.

    기본 코드는 새 앱을 외부 메모리에로드 한 후 실행 방법을 알아야합니다. 가장 쉬운 방법은 아마도 첫 번째 외부 RAM 위치에서 실행을 시작하는 것입니다. 즉, 코드에는 해당 절대 시작 주소에 하나의 CODE 섹션이 필요합니다. 여기에는 나머지 코드의 오른쪽 레이블에 대한 GOTO가 포함되어 있으며 모두 재배치 가능합니다.

  2. 기본 코드에서 앱을 라이브러리 루틴에 연결

    기존 Microchip 도구를 사용하여이를 수행 할 수있는 간단한 방법은 없지만 그렇게 나쁘지는 않습니다.

    훨씬 더 큰 문제는 기본 코드 변경을 처리하는 방법입니다. 간단한 전략은 기본 코드를 작성하고 결과 맵 파일에서 프로그램을 실행하여 전역 주소를 수집 한 다음 전역 적으로 정의 된 모든 기호에 대해 EQU 문이 포함 된 가져 오기 파일을 작성하는 것입니다. 이 가져 오기 파일은 모든 앱 코드에 포함됩니다. 앱 소스 코드에는 기본적으로 기본 코드 진입 점에 대한 고정 주소 참조가 포함되어 있으므로 연결할 것이 없습니다.

    그렇게하기 쉽고 작동하지만 기본 코드를 변경할 때 어떤 일이 발생하는지 고려하십시오. 사소한 버그 수정으로도 모든 주소가 움직일 수 있으며 기존의 모든 앱 코드가 좋지 않아 다시 작성해야합니다. 모든 앱을 업데이트하지 않고 기본 코드 업데이트를 제공하지 않으려는 경우이 문제를 해결할 수는 있지만 좋지 않은 생각입니다.

    더 좋은 방법은 기본 코드에서 선택된 고정 알려진 주소에 정의 된 인터페이스 영역을 갖는 것입니다. 앱 코드가 호출 할 수있는 모든 서브 루틴마다 하나의 GOTO가 있습니다. 이러한 GOTO는 고정 된 알려진 주소에 배치되며 외부 앱은 해당 위치 만 호출하여 서브 루틴이 해당 기본 코드 빌드에서 실제로 종료 된 위치로 이동합니다. 이것은 익스포트 된 서브 루틴 당 2 개의 프로그램 메모리 워드와 런타임에 2 개의 추가 사이클 비용이 들지만 가치가 있다고 생각합니다.

    이를 위해서는 GOTO 생성 프로세스와 외부 앱이 서브 루틴 (실제로 GOTO 리디렉터) 주소를 가져 오기 위해 가져올 내보내기 파일을 자동화해야합니다. MPASM 매크로의 영리한 사용법으로 할 수는 있지만 전처리 과정에서 외부 파일에 쓸 수 있기 때문에 전처리기를 사용해야합니다. 전 처리기 매크로를 작성하여 각 리디렉터를 한 줄의 소스 코드로 정의 할 수 있습니다. 매크로는 실제 대상 루틴에 대한 외부 참조 인 GOTO를 생성하고 해당 루틴의 알려진 상수 주소와 함께 적절한 이름을 가진 내보내기 파일에 적절한 행을 추가하는 모든 불쾌한 작업을 수행합니다. 아마도 매크로는 정규 이름 (런타임 확장 가능 배열과 같은)을 가진 많은 전 처리기 변수를 만든 다음 모든 매크로 호출 후에 내보내기 파일을 한 번 작성합니다. 전처리 기가 MPASM 매크로로 할 수없는 많은 작업 중 하나는 문자열 조작을 수행하여 다른 이름에서 새 심볼 이름을 작성하는 것입니다.

    내 전 처리기 및 기타 여러 관련 자료는 www.embedinc.com/pic/dload.htm 에서 무료로 제공 됩니다.


나는 고정 된 점프 테이블의 아이디어를 정말로 좋아한다. 플래시 메모리의 끝에서 시작하여 각 시스템 호출에 대한 위치를 고정 할 수있었습니다. 내가 설명하는 모든 전 처리기 부두를 알아낼 수 없다면 모든 서브 루틴의 주소를 가진 수동으로 유지 관리되는 헤더 파일을 피할 수도 있습니다.
captncraig

5

옵션 1 : 통역 언어

이것은 직접 하지 않습니다 질문에 대답 (BTW이며, 직접 해결하는 답변에서 배우고 싶습니다) 외부 프로그램을로드하기 위해 외부 프로그램을로드 할 수있는 프로젝트를 수행 할 때 매우 일반적입니다. 통역 언어. 리소스가 부족한 경우 (이 프로세서에서 PIC32 또는 소형 ARM 프로세서 사용에 대해 생각해 보셨습니까?) 언어를 전체 사양의 하위 집합으로 제한하는 것이 일반적입니다. 더 나아가 체인은 몇 가지 작업 만 수행하는 도메인 별 언어입니다.

예를 들어, elua 프로젝트 는 리소스 부족 (64kB RAM) 해석 언어의 예입니다. 일부 기능을 제거하면 32k RAM까지 줄일 수 있습니다 (참고 : 8 비트 아키텍처 인 현재 프로세서에서는 작동하지 않습니다. 외부 RAM을 사용하면 그래픽이 너무 느릴 수 있습니다). 최소한의 API를 제공하면 새로운 사용자가 게임을 쉽게 프로그래밍 할 수있는 빠르고 유연한 언어를 제공합니다. 온라인 언어에 대한 많은 문서가 있습니다. 비슷한 방식으로 사용할 수있는 다른 언어 (Forth 및 Basic과 같은)가 있지만 현재 Lua가 최선의 선택이라고 생각합니다.

비슷한 맥락에서 고유 한 도메인 별 언어를 만들 수 있습니다. 보다 완전한 API와 외부 문서를 제공해야하지만 게임이 모두 비슷하다면 그리 어렵지 않을 것입니다.

어쨌든 PIC18은 아마도 사용자 정의 프로그래밍 / 스크립팅 및 그래픽과 관련된 것에 사용하는 프로세서가 아닐 수도 있습니다. 이 클래스의 프로세서에 익숙 할 수도 있지만, 디스플레이 드라이버와 더 많은 메모리를 사용하는 것이 좋습니다.

옵션 2 : 모든 것을 다시 프로그래밍하십시오

그러나, 이미 C에서 자신을 모든 게임 프로그래밍에 계획하는 경우, 다음로드와 귀찮게하지 않습니다 단지 SD 카드에서 게임 로직을. 32kB의 플래시 만 있으면 다시 프로그래밍 할 수 있으며이를 위해 4GB microSD 카드를 쉽게 얻을 수 있습니다. (참고 : 더 큰 카드는 종종 SDHC이므로 인터페이스하기가 더 어렵습니다). 32kB의 모든 마지막 바이트를 사용한다고 가정하면, 필요한 게임 로직에 관계없이 펌웨어의 131,072 개 사본을 SD 카드에 남겨 둘 수 있습니다.

AN851 과 같이 PIC 용 부트 로더를 작성하기위한 많은 노트가 있습니다. 특정 메모리 영역 (아마도 메모리 영역의 상단, 링커에서 지정)을 차지하도록 부트 로더를 설계하고 전체 펌웨어 프로젝트가이 영역에 도달하지 않도록 지정해야합니다. Appnote는이를 자세히 설명합니다. "PIC18F452의 부팅 섹션"을 "링커에서 지정한 부팅 섹션"으로 바꾸면됩니다.

그런 다음 부트 로더는 사용자가 SD 카드에서 실행할 프로그램을 선택하고 전체를 복사하도록 허용하면됩니다. UI는 사용자가 선택 버튼을 눌러 선택 모드로 들어가야한다는 것일 수 있습니다. 일반적으로 부트 로더는 재설정시이 버튼의 상태를 확인하기 만하고, 누르고 있지 않으면 게임으로 부팅합니다. 이 버튼을 누르고 있으면 사용자가 SD 카드에서 파일을 선택하고 프로그램을 복사 한 다음 [새로운] 게임으로 계속 부팅 할 수 있어야합니다.

이것이 나의 현재 추천입니다.

옵션 3 : 16 진 파일의 일부만 저장하는 깊은 마법

계획된 메커니즘의 문제점은 프로세서가 API 및 함수 호출을 처리하지 않고 숫자 -명령 포인터가 점프 할 수있는 주소를 처리하고 API 사양에 따라 함수 호출을 실행하는 코드가있을 것으로 예상한다는 점입니다. 이 프로그램의 단지 일부를 컴파일하려고하면 링커는 호출 할 때 무엇을해야할지 알 수 없습니다 check_button_status()toggle_led(). 이러한 기능은 프로세서의 16 진 파일에 존재하지만 어떤 주소에 있는지 정확히 알아야합니다.

링커는 이미 코드를 여러 섹션으로 나눕니다. 이론적으로 이것을 일부 -section#pragma주문 으로 추가 섹션으로 나눌 수 있습니다 . 나는 이것을 한 적이 없으며 방법을 모른다. 위의 두 가지 방법이 실패하거나 누군가가 여기에 멋진 답변을 게시 할 때 까지이 메커니즘을 배우지 못할 것이므로 가르쳐 줄 수 없습니다.


번호 2에 대한 반대 의견은 플래시 메모리의 칩 수명 기간 동안 소거주기 수가 제한되어 있다는 것입니다. 8 비트 미니멀리즘을 사용하기 때문에 더 강력한 MCU를 사용하고 싶지 않습니다.
captncraig 2013

@CMP-10,000 회 이상의 삭제주기가 있습니다. 누군가가 매일 다른 게임을한다면, 2039 년까지 지속될 것입니다. 플래시는 회로의 나머지 부분보다 거의 확실히 지속될 것입니다. 아케이드에서 매일 수십 번 연주하지 않는 한 걱정할 필요는 없다고 생각합니다.
Kevin Vermeer

1
둘째, 8 비트 미니멀리즘은 근사해 보일 수 있지만 프로그래밍에는 어려움이 있습니다. 프로세서의 한계를 뛰어 넘기 때문에 견고한 마이크로 컨트롤러를 얻는 것이 훨씬 더 복고풍처럼 보이도록 만드는 것이 훨씬 쉽습니다.
Kevin Vermeer

1
매우 공정한 포인트. 부품 수를 줄이더라도 pic32는 비용이나 외부 구성 요소가 이와 다르지 않으며 512K의 내부 플래시가 있으면 승리합니다.
captncraig

실용적인 해결책은 pic32를 사용하고 부트 로더를 작성하여 sd 카드에서 다시 플래시하는 것 같습니다. 부트 로더와 사용자 코드 모두가 필요한 기능을 재사용하는 데 어려움을 겪을 것입니다.하지만 12k 부트 플래시에 유지하는 한 사용자에게 전체 칩을 제공해야하며 소스에서 원하는 라이브러리를 포함 할 수 있습니다 수평.
captncraig
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.