Dữ liệu bạn mô tả (sử dụng toàn bộ bộ nhớ chương trình 24 bit để lưu trữ dữ liệu) không thể được xác định và khởi tạo trong C và không thể đọc trực tiếp qua C; cách duy nhất để truy cập nó là bằng cách gói gọn trong một hàm lắp ráp có thể gọi được bằng C hoặc nội tại.
Thực sự có hai câu hỏi ở đây:
Làm thế nào để chơi độc đáo với trình biên dịch, trình biên dịch và trình liên kết, để khi bạn xác định dữ liệu 24 bit của mình trong tệp lắp ráp là dữ liệu có thể định vị lại bằng một tên tượng trưng D1
, thay vì dữ liệu không tên ở một địa chỉ cố định, trình biên dịch có thể thấy biến này để xác định địa chỉ của nó
làm thế nào để truy cập dữ liệu
Câu hỏi thứ 2 (cách truy cập dữ liệu) được trả lời cho các phần 33EP trong DS70613C và phải được trả lời cho các phần 33FJ trong DS70204C (nhưng các ví dụ trong hướng dẫn 33FJ chỉ sử dụng 16 bit thấp). Dưới đây là đoạn mã ví dụ từ tài liệu tham khảo 33EP hoạt động cho các bộ phận 33EP + nên cho 33FJ (Tôi không có sẵn thiết bị 33FJ):
(lưu ý: sử dụng mã int
, trong khi đó sẽ tốt hơn khi sử dụng uint16_t
và #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)
;
}
Bạn sẽ lưu ý rằng các hàm dựng sẵn __builtin_tblrdl()
và __builtin_tblrdh()
được sử dụng để đọc các từ dữ liệu 16 bit thấp và cao từ một vị trí bộ nhớ chương trình và __builtin_tblpage() and __builtin_tbloffset()
có thể được sử dụng để trích xuất trang và phần bù của địa chỉ. Trong ví dụ cụ thể này, mảng highWord luôn là 0 và mảng lowWord khớp với prog_data được xác định và khởi tạo trong C.
Xin lưu ý không có con trỏ được sử dụng ở đây! Mặc dù có thể sử dụng các biến thông thường được gắn thẻ const
, để chúng được đặt bởi trình liên kết trong không gian chương trình chỉ đọc và để bạn có thể đọc bộ nhớ bằng các kỹ thuật con trỏ C tiêu chuẩn, với trình biên dịch tự động quản lý các thanh ghi phân trang đối với bạn, bạn chỉ có thể lưu trữ dữ liệu 16 bit. Bạn cần truy cập các hàm dựng sẵn TBLRDL và TBLRDH để có được tất cả 24 bit dữ liệu.
Về cách chơi độc đáo với trình biên dịch / linker / etc, bạn phải đánh lừa trình biên dịch và nói với nó rằng nó chỉ nhìn thấy dữ liệu 16 bit. Đây là một ví dụ hoạt động để lấy biến D1 được khai báo ở nơi khác:
#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);
Điều này không đọc chính xác các giá trị 24 bit và lưu trữ chúng trong 24 bit dưới cùng của uint32_t. Biến D1 bên ngoài được khai báo trong C là biến giả chỉ được sử dụng để lấy tại địa chỉ bắt đầu bằng cách tận dụng cách trình biên dịch / trình biên dịch / trình liên kết làm việc cùng nhau. Các hàm dựng sẵn xử lý phần còn lại của công việc.
Những gì tôi không biết là làm thế nào để tự động lấy kích thước của dữ liệu, vì nó được xác định + khởi tạo trong lắp ráp.