Mảng lớn trong C18 gây ra thiết lập lại thiết bị


7

Tôi đang sử dụng PIC18F13K22 và Microchip của trình biên dịch C18 trong MPLABX. PIC tiếp tục thiết lập lại, khi nó chuẩn bị nhảy vào thói quen dịch vụ ngắt (ISR). Tôi đã có thể theo dõi vấn đề xuống khai báo của một mảng:

UINT16 rom periods[] = {64000,59412,55438,51962, ...} // 1024 Values

Nếu tôi thu nhỏ kích thước của mảng xuống một vài mục, PIC sẽ chạy mà không cần thiết lập lại liên tục.

Bây giờ tôi tự hỏi tại sao các mảng lớn gây ra một thiết lập lại. Và thậm chí thú vị hơn đối với tôi: tôi có thể khai báo bằng cách nào đó một tập dữ liệu có chứa 1024 giá trị này không?


Thông tin mục được yêu cầu:

              Section       Type    Address   Location Size(Bytes)
            ---------  ---------  ---------  ---------  ---------
           _entry_scn       code   0x000000    program   0x000006
               .cinit    romdata   0x000006    program   0x000002
      .romdata_Main.o    romdata   0x000008    program   0x000800
         .code_Main.o       code   0x000808    program   0x000124
           _cinit_scn       code   0x00092c    program   0x00009e
        .code_Debug.o       code   0x0009ca    program   0x000080
       .code_Signal.o       code   0x000a4a    program   0x000040
                 PROG       code   0x000a8a    program   0x00003c
       .code_t0open.o       code   0x000ac6    program   0x000038
          .code_ADC.o       code   0x000afe    program   0x000032
         .stringtable    romdata   0x000b30    program   0x000026
                .code       code   0x000b56    program   0x000020
         _startup_scn       code   0x000b76    program   0x00001c
       .code___init.o       code   0x000b92    program   0x000002
    .romdata_t0open.o    romdata   0x000b94    program   0x000000
    .idata___init.o_i    romdata   0x000b94    program   0x000000
    .idata_t0open.o_i    romdata   0x000b94    program   0x000000
     .romdata_Debug.o    romdata   0x000b94    program   0x000000
     .idata_Debug.o_i    romdata   0x000b94    program   0x000000
    .romdata___init.o    romdata   0x000b94    program   0x000000
    .romdata_Signal.o    romdata   0x000b94    program   0x000000
    .idata_Signal.o_i    romdata   0x000b94    program   0x000000
      .idata_Main.o_i    romdata   0x000b94    program   0x000000
       .romdata_ADC.o    romdata   0x000b94    program   0x000000
       .idata_ADC.o_i    romdata   0x000b94    program   0x000000
        .code_c018i.o       code   0x000b94    program   0x000000
     .romdata_c018i.o    romdata   0x000b94    program   0x000000
     .idata_c018i.o_i    romdata   0x000b94    program   0x000000
.config_300001_Main.o    romdata   0x300001    program   0x000001
.config_300002_Main.o    romdata   0x300002    program   0x000001
.config_300003_Main.o    romdata   0x300003    program   0x000001
.config_300005_Main.o    romdata   0x300005    program   0x000001
.config_300006_Main.o    romdata   0x300006    program   0x000001
            MATH_DATA      udata   0x000000       data   0x000014
             .tmpdata      udata   0x000014       data   0x000000
               .stack      udata   0x000060       data   0x000050
       .udata_c018i.o      udata   0x0000b0       data   0x00000a
      .udata_Signal.o      udata   0x0000ba       data   0x000002
       .idata_c018i.o      idata   0x0000bc       data   0x000000
         .udata_ADC.o      udata   0x0000bc       data   0x000000
         .idata_ADC.o      idata   0x0000bc       data   0x000000
        .udata_Main.o      udata   0x0000bc       data   0x000000
        .idata_Main.o      idata   0x0000bc       data   0x000000
      .idata_Signal.o      idata   0x0000bc       data   0x000000
       .udata_Debug.o      udata   0x0000bc       data   0x000000
       .idata_Debug.o      idata   0x0000bc       data   0x000000
      .udata_t0open.o      udata   0x0000bc       data   0x000000
      .idata_t0open.o      idata   0x0000bc       data   0x000000
      .udata___init.o      udata   0x0000bc       data   0x000000
      .idata___init.o      idata   0x0000bc       data   0x000000
        SFR_UNBANKED0      udata   0x000f68       data   0x000098

Câu trả lời:


8

Không có lý do cố hữu mảng này sẽ gây ra thiết lập lại. Bạn rõ ràng đang khai báo 2 kBytes của hằng số trong bộ nhớ chương trình. PIC đó có 8 kBytes bộ nhớ chương trình, vì vậy điều đó sẽ ổn.

Nhiều khả năng, có một lỗi ở nơi khác. Mảng này có lẽ là thứ lớn nhất mà trình liên kết phải đặt, vì vậy tất cả các mã không ở các địa chỉ cố định cụ thể sẽ có khả năng di chuyển xung quanh khi kích thước mảng bị thay đổi, có thể làm cho một số lỗi xuất hiện và biến mất.

Có thể hữu ích khi hiển thị phần "Thông tin Mục" của tệp MAP liên kết để chúng ta có thể thấy những gì đã kết thúc ở đâu. Ngoài ra, hãy thử bước qua điều này với trình giả lập và xem liệu cuối cùng bạn có thực hiện các vị trí ngoài ý muốn hay không.

Thêm:

Từ từ khóa "rom", rõ ràng bạn dự định mảng này sẽ nằm trong bộ nhớ chương trình. Hãy chắc chắn rằng trình biên dịch C đã hiểu chính xác điều này. Tôi sử dụng C18 không thường xuyên và không nhớ câu thần chú chính xác là gì để xác định các hằng số trong bộ nhớ chương trình. Nếu trình biên dịch không đặt nó ở đó, tất cả các cách lạ có thể xảy ra. Một lần nữa, tập tin bản đồ liên kết sẽ làm rõ điều này.

Đã thêm 2:

Bây giờ chúng ta có một tệp bản đồ liên kết, chúng ta có thể thấy vấn đề. 1024 từ 16 bit mỗi bit là 2048 byte, tức là 800h. Chỉ có một phần ở bất cứ đâu gần kích thước đó và nó chính xác là 800 giờ byte, vì vậy trình biên dịch đã hiểu để đưa nó vào bộ nhớ chương trình. Tuy nhiên, lưu ý rằng nó được đặt tại địa chỉ 8. Đó là địa chỉ vectơ ngắt ưu tiên đơn hoặc cao. Mảng này cũng chồng lấp địa chỉ ngắt ưu tiên thấp ở 16, do đó, một trong hai cách ngắt không thể được sử dụng với vị trí của mảng này.

Thực tế là trình liên kết đã đặt mảng ở đó nó có nghĩa là không có gì khác yêu cầu địa chỉ cố định của vectơ ngắt. Tôi không sử dụng C cho các thói quen ngắt, nhưng điều này cho tôi biết rằng trình biên dịch C không hiểu rằng thói quen ngắt của bạn thực sự là một thói quen ngắt hoặc nó không được bao gồm trong liên kết.

Tôi không biết những gì bạn gọi là mô-đun thường trình ngắt, nhưng nó có được liệt kê ở tất cả trong bản đồ liên kết không? Nếu vậy, thì bạn đã quên lẩm bẩm câu thần chú chính xác để trình biên dịch biết một thói quen ngắt và do đó buộc nó đến một địa chỉ cụ thể. Nếu không, thì nó không bị chặn trong liên kết nào đó. Điều này có thể xảy ra nếu bạn đặt tất cả các tệp đối tượng vào thư viện để trình liên kết có thể chọn những gì nó muốn và không có phần bên ngoài bị thiếu cho mô-đun ngắt. Điều đó có thể xảy ra với một mô-đun ngắt vì nó không bao giờ được gọi một cách rõ ràng. Trong trường hợp đó, tệp đối tượng mô-đun ngắt phải được cung cấp cho trình liên kết một cách rõ ràng.


Tôi đã thêm thông tin phần. '.romdata_Main.o' 2024 byte được đặt tại địa chỉ 0x0008. Không phải đó là địa chỉ vectơ ngắt sao? Điều đó sẽ giải thích tại sao nó được thiết lập lại khi một ngắt được tăng lên ...
PetPaulsen

Cảm ơn bạn rất nhiều! Bây giờ tôi ít nhất có thể làm việc xung quanh vấn đề này .
PetPaulsen

0

câu trả lời của Olin, tôi đã có thể loại bỏ vấn đề.

Như Olin đã viết, trình liên kết đặt mảng tại địa chỉ 0x08. Đây là địa chỉ vector ngắt.

Một 'cách giải quyết' hiện là đặt mã rõ ràng tại địa chỉ 0x08, nhảy đến ISR. (Lấy cảm hứng từ hướng dẫn người dùng C18 trang 29):

void isr(void);

#pragma code high_vector=0x08
void interrupt_at_high_vector(void)
{
  _asm GOTO isr _endasm
}
#pragma code
#pragma interrupt isr
void isr (void)
{
  /* ... */
}

hoặc thậm chí đơn giản hơn:

#pragma code high_vector=0x08
#pragma interrupt isr
void isr()
{
  /* ... */
}

1
Đó là trình liên kết đặt mảng ở 8, không phải trình biên dịch. Tuy nhiên, như tôi đã nói, tôi không sử dụng trình biên dịch cho mã ngắt, nhưng tôi ngạc nhiên trình biên dịch không đặt thói quen hoặc ít nhất là sơ khai ở vectơ ngắt cố định cho bạn. Nhưng, nếu bạn có thể đặt cuống asm ở mức 8, tại sao bạn không thể đặt thói quen ngắt ở mức 8 thay vì sử dụng cùng một cơ chế? Bằng cách đó, bạn không cần phải sơ khai gì cả.
Olin Lathrop

@Olin Lathrop - Bạn nói đúng ... Tôi có thể đặt isr ở 0x08. Không cần sơ khai. Nhưng vẫn còn nghiêm trọng hơn, rằng tôi phải nói rằng trình liên kết rằng tôi không muốn vectơ ngắt bị ghi đè bởi một số dữ liệu.
PetPaulsen

Bạn không thực sự nói với trình liên kết rằng bạn không muốn vectơ ngắt quá mức, nhưng trong trường hợp này bạn muốn mã này ở một địa chỉ cụ thể. Nếu bạn không nói điều đó, trình liên kết có thể tự do đặt mọi thứ ở bất cứ đâu, trong trường hợp này xảy ra dẫn đến mảng của bạn ở mức 8. Cũng có thể có một thứ khác ở đó. Vấn đề này không liên quan gì đến mảng của bạn, nhưng bạn đã không hiểu được nơi mà thói quen ngắt cần phải đi.
Olin Lathrop
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.