Data yang Anda gambarkan (penggunaan 24-bit penuh dari memori program untuk menyimpan data) tidak dapat didefinisikan dan diinisialisasi dalam C, dan tidak dapat membaca langsung melalui C; satu-satunya cara untuk mengaksesnya adalah dengan merangkum dalam fungsi perakitan C-callable atau intrinsik.
Sebenarnya ada dua pertanyaan di sini:
cara bermain apik dengan kompiler, assembler, dan tautan, sehingga ketika Anda mendefinisikan data 24-bit dalam file rakitan sebagai data yang dapat dipindahkan dengan nama simbolis D1
, daripada data yang tidak disebutkan namanya di alamat tetap, kompiler dapat melihat variabel ini untuk menentukan alamatnya
cara mengakses data
Pertanyaan ke-2 (bagaimana mengakses data) dijawab untuk bagian 33EP di DS70613C dan harus dijawab untuk bagian 33FJ di DS70204C (tetapi contoh dalam manual 33FJ hanya menggunakan bit 16 rendah). Berikut ini cuplikan contoh kode dari manual referensi 33EP yang berfungsi untuk 33EP bagian + seharusnya untuk 33FJ (Saya tidak punya perangkat 33FJ yang mudah tersedia):
(catatan: penggunaan kode int
, sedangkan akan lebih baik digunakan uint16_t
dan #include <stdint.h>
)
int prog_data[10] __attribute__((space(prog))) =
{0x0000, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, 0x9999};
unsigned int lowWord[10], highWord[10];
unsigned int tableOffset, loopCount;
int main(void){
TBLPAG = __builtin_tblpage (prog_data);
tableOffset = __builtin_tbloffset (prog_data);
/* Read all 10 constants into the lowWord and highWord arrays */
for (loopCount = 0; loopCount < 10; loopCount ++)
{
lowWord[loopCount] = __builtin_tblrdl (tableOffset);
highWord[loopCount] = __builtin_tblrdh (tableOffset);
tableOffset +=2;
}
while(1)
;
}
Anda akan mencatat bahwa fungsi builtin __builtin_tblrdl()
dan __builtin_tblrdh()
digunakan untuk membaca kata-kata data 16-bit yang rendah dan tinggi dari lokasi memori program, dan __builtin_tblpage() and __builtin_tbloffset()
dapat digunakan untuk mengekstrak halaman dan mengimbangi alamat. Dalam contoh khusus ini, array highWord selalu 0, dan array lowWord cocok dengan prog_data yang didefinisikan dan diinisialisasi dalam C.
Harap dicatat tidak ada petunjuk yang digunakan di sini! Meskipun dimungkinkan untuk menggunakan variabel normal yang ditandai const
, sehingga mereka ditempatkan oleh linker di ruang program read-only, dan agar Anda dapat membaca memori menggunakan teknik pointer C standar, dengan kompiler secara otomatis mengelola register paging. untuk Anda, Anda hanya dapat menyimpan data 16-bit. Anda perlu mengakses fungsi built-in TBLRDL dan TBLRDH untuk mendapatkan semua 24 bit data.
Adapun cara bermain dengan kompiler / linker / etc, Anda harus menipu kompiler dan mengatakan itu hanya melihat data 16-bit. Berikut adalah contoh yang berfungsi untuk mendapatkan pada variabel D1 yang dideklarasikan di tempat lain:
#define D1_SIZE 18
extern uint16_t __attribute__((space(prog))) D1[D1_SIZE];
#define READ_DATA(dst, v, len) readData(dst, __builtin_tblpage(v), __builtin_tbloffset(v), len)
void readData(uint32_t *pdst, uint16_t page, uint16_t offset, uint16_t len)
{
TBLPAG = page;
while (len-- > 0)
{
uint16_t lo = __builtin_tblrdl (offset);
uint16_t hi = __builtin_tblrdh (offset);
*pdst++ = (((uint32_t)(hi)) << 16) | ((uint32_t)(lo));
offset += 2;
}
}
...
uint32_t d1copy[D1_SIZE];
READ_DATA(d1copy, D1, D1_SIZE);
Ini benar membaca nilai 24-bit dan menyimpannya di bagian bawah 24 bit dari uint32_t. Variabel D1 extern yang dideklarasikan dalam C adalah variabel dummy yang hanya digunakan untuk mendapatkan alamat awal dengan memanfaatkan cara kompiler / assembler / penghubung bekerja bersama. Fungsi builtin menangani sisa pekerjaan.
Yang saya tidak tahu adalah bagaimana cara secara otomatis mendapatkan ukuran data, karena itu ditentukan + diinisialisasi dalam perakitan.