2014-11-18 23 views
9

Tôi hy vọng tiêu đề đủ mô tả. Vì vậy, đây là những gì tôi muốn làm và những gì tôi đã chơi đùa với.Ghi dữ liệu đến địa chỉ cụ thể trong thời gian biên dịch

Đợi, trước hết, đây là ứng dụng được nhúng. Atmel SAM4L vi điều khiển, bằng cách sử dụng Atmel Studio IDE và trình biên dịch GCC/linker.

Phải, tôi đang viết bộ nạp khởi động, nhưng muốn lưu phiên bản bộ nạp khởi động vào bộ nhớ chương trình vào cuối không gian được cấp phát cho bộ nạp khởi động (giả sử 0x3FF0). Bằng cách này, ứng dụng cũng có thể kiểm tra phiên bản bộ nạp khởi động bằng cách chỉ cần nhìn vào địa chỉ cụ thể. Tại thời điểm này tôi đang bận rộn với một tiện ích cho ứng dụng để cập nhật trình tải khởi động, nhưng tôi không muốn ứng dụng hoặc bộ tải khởi động cập nhật phiên bản tại 0x3FF0 bằng lệnh hoặc mã, tôi muốn nó như một phần của Tệp .bin/.hex, vì vậy khi tôi flash bộ nạp khởi động, phiên bản được nhấp nháy cùng với nó. Vì vậy, hiện tại tôi có một #define cho kiểu bộ nạp khởi động, phiên bản chính và phiên bản phụ mà tất cả đều nằm trong tệp globals.h trong dự án. Về cơ bản tôi chỉ muốn viết những 3 byte để 0x3FF0 khi tôi nhấn biên dịch.

Như tôi hiểu có rất nhiều thủ thuật tôi có thể kéo với trình liên kết, nhưng chưa bao giờ được chơi với tập lệnh liên kết cho đến ngày hôm qua và có thể thực hiện một số việc với nó, nhưng không phải những gì tôi muốn. Dự án cũng tạo ra một kịch bản liên kết khá mãnh liệt, vì vậy tôi cũng hơi cảnh giác về nơi để nhảy vào và kết xuất ba byte của mình. Tôi biết bạn không được phép di chuyển con trỏ địa chỉ trở lại.

Đây là kịch bản mối liên kết được tạo ra bởi dự án

/** 
* \file 
* 
* \brief Flash Linker script for SAM. 
* 
* Copyright (c) 2013 Atmel Corporation. All rights reserved. 
* 
* \asf_license_start 
* 
* \page License 
* 
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions are met: 
* 
* 1. Redistributions of source code must retain the above copyright notice, 
* this list of conditions and the following disclaimer. 
* 
* 2. Redistributions in binary form must reproduce the above copyright notice, 
* this list of conditions and the following disclaimer in the documentation 
* and/or other materials provided with the distribution. 
* 
* 3. The name of Atmel may not be used to endorse or promote products derived 
* from this software without specific prior written permission. 
* 
* 4. This software may only be redistributed and used in connection with an 
* Atmel microcontroller product. 
* 
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED 
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE 
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR 
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
* POSSIBILITY OF SUCH DAMAGE. 
* 
* \asf_license_stop 
* 
*/ 

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 
OUTPUT_ARCH(arm) 
SEARCH_DIR(.) 

/* 
* NOTE: to keep binary compatibility with SAM4L4 device on SAM4L Xplained Pro, 
* we use SAM4L4 memory space here instead SAM4L8. You may change it if you are 
* using SAM4L8 device. 
*/ 
/* Memory Spaces Definitions */ 
MEMORY 
{ 
    rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 /* flash, 256K */ 
    ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* sram, 32K */ 
    /* rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000 */ /* flash, 512K */ 
    /* ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010000 */ /* sram, 64K */ 
} 

/* The stack size used by the application. NOTE: you need to adjust according to your application. */ 
__stack_size__ = DEFINED(__stack_size__) ? __stack_size__ : 0x1000; 
__ram_end__ = ORIGIN(ram) + LENGTH(ram) - 4; 

/* Section Definitions */ 
SECTIONS 
{ 
    .text : 
    { 
     . = ALIGN(4); 
     _sfixed = .; 
     KEEP(*(.vectors .vectors.*)) 
     *(.text .text.* .gnu.linkonce.t.*) 
     *(.glue_7t) *(.glue_7) 
     *(.rodata .rodata* .gnu.linkonce.r.*) 
     *(.ARM.extab* .gnu.linkonce.armextab.*) 

     /* Support C constructors, and C destructors in both user code 
      and the C library. This also provides support for C++ code. */ 
     . = ALIGN(4); 
     KEEP(*(.init)) 
     . = ALIGN(4); 
     __preinit_array_start = .; 
     KEEP (*(.preinit_array)) 
     __preinit_array_end = .; 

     . = ALIGN(4); 
     __init_array_start = .; 
     KEEP (*(SORT(.init_array.*))) 
     KEEP (*(.init_array)) 
     __init_array_end = .; 

     . = ALIGN(0x4); 
     KEEP (*crtbegin.o(.ctors)) 
     KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 
     KEEP (*(SORT(.ctors.*))) 
     KEEP (*crtend.o(.ctors)) 

     . = ALIGN(4); 
     KEEP(*(.fini)) 

     . = ALIGN(4); 
     __fini_array_start = .; 
     KEEP (*(.fini_array)) 
     KEEP (*(SORT(.fini_array.*))) 
     __fini_array_end = .; 

     KEEP (*crtbegin.o(.dtors)) 
     KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 
     KEEP (*(SORT(.dtors.*))) 
     KEEP (*crtend.o(.dtors)) 

     . = ALIGN(4); 
     _efixed = .;   /* End of text section */ 
    } > rom 

    /* .ARM.exidx is sorted, so has to go in its own output section. */ 
    PROVIDE_HIDDEN (__exidx_start = .); 
    .ARM.exidx : 
    { 
     *(.ARM.exidx* .gnu.linkonce.armexidx.*) 
    } > rom 
    PROVIDE_HIDDEN (__exidx_end = .); 

    . = ALIGN(4); 
    _etext = .; 

    .relocate : AT (_etext) 
    { 
     . = ALIGN(4); 
     _srelocate = .; 
     *(.ramfunc .ramfunc.*); 
     *(.data .data.*); 
     . = ALIGN(4); 
     _erelocate = .; 
    } > ram 

    /* .bss section which is used for uninitialized data */ 
    .bss (NOLOAD) : 
    { 
     . = ALIGN(4); 
     _sbss = . ; 
     _szero = .; 
     *(.bss .bss.*) 
     *(COMMON) 
     . = ALIGN(4); 
     _ebss = . ; 
     _ezero = .; 
    } > ram 

    /* stack section */ 
    .stack (NOLOAD): 
    { 
     . = ALIGN(8); 
     _sstack = .; 
     . = . + __stack_size__; 
     . = ALIGN(8); 
     _estack = .; 
    } > ram 

    . = ALIGN(4); 
    _end = . ; 
} 

Vì vậy, như xa như tôi hiểu, .ARM.exidx là phần cuối cùng được đặt trong ROM và .relocate sẽ được đặt trong RAM (từ 0x20000000 trở đi) dựa trên các vùng và khai báo MEMORY, vì vậy ba byte của tôi nên ở đâu đó giữa hai thứ đó.

Sau đó, như thế nào, tôi đã thử ví dụ này http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0803a/BABDJCAA.html nhưng tôi không nhìn thấy nó được phản ánh trong .bin của tôi hoặc các tập tin hex. Tôi đoán nó chỉ phân bổ bộ nhớ và không thực sự tải bất cứ thứ gì vì nó chỉ là một biến. Tôi cũng đã tìm thấy những thứ như thế này gcc linker description file force symbol to be at specific address , nhưng tôi không phải vì nó không phải là mã thực mà tôi đang cố gắng tải đến một địa chỉ cụ thể, tôi không thấy cách sử dụng phương pháp này.

Tôi vẫn đang chơi xung quanh với thao tác tập lệnh trình liên kết và xem những gì tôi có thể đạt được, nhưng mọi trợ giúp sẽ được đánh giá cao.

Nếu cần thêm thông tin, vui lòng hỏi và tôi sẽ cung cấp. (Hoặc nếu tôi cần thay đổi tiêu đề hoặc thẻ để có lượt truy cập tốt hơn.)

+0

Tôi không biết cách gcc xử lý việc này, nhưng với các công cụ khác thì không có nhiều sự khác biệt giữa các hàm và biến. Vì vậy, thường vị trí được thực hiện theo cùng một cách. – user694733

+0

Tham chiếu tốt nhất cho thông tin này là [** Hướng dẫn sử dụng ld (phần mềm nguồn) **] (https://sourceware.org/binutils/docs/ld/index.html). Trong trường hợp của bạn với các hệ thống nhúng hoặc với bản thân assembly, việc biết 'ld' là quan trọng như việc biết chính trình biên dịch. Hãy xem và xem bạn có thể thu hẹp câu hỏi của bạn một chút không. –

+0

Cảm ơn, tôi sẽ có một cái nhìn ở đó. – kowalski5233

Trả lời

0

Vì vậy, đối với những người đến đây tìm kiếm câu trả lời, đây là ví dụ chi tiết hơn về những gì tôi đã làm.

Trong main.c tôi xác định một nguyên mẫu đầu tiên có được ví dụ làm việc, sau đó tôi đã cố gắng nhận được một mảng đi:

void jver(void) __attribute__((section(".jver"))); 

static uint8_t jvar[10] __attribute__((section(".jvar"))) = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; 

void jver(void) 
{ 
    //static uint8_t sbuf[10] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; 
    jamba_TxBuff(jvar, 10); 

} 

Sau đó, trong kịch bản mối liên kết, sau phần cuối cùng được đặt trong vùng 'rom', tôi thêm những thứ mà tôi muốn thêm vào vùng 'rom':

_jverstart = 0x3FF0; 
.jver : AT (_jverstart) 
{ 
    *(.jver) 
} > rom 


_jvarstart = 0x4100; 
.jvar : AT (_jvarstart) 
{ 
    *(.jvar) 
} > rom 

Lưu ý ở đây tôi phải chỉnh sửa ví dụ, chỉ cần tạo con trỏ bằng giá trị không hoạt động. Tôi đã phải tạo một biến và sử dụng chức năng AT. Trong quá trình thử nghiệm, tôi đã thêm vùng 'rom' và chưa kiểm tra xem nó có hoạt động hay không nếu tôi xóa nó.

Khi tôi biên dịch, tôi nhận được kết quả sau:

:103FF00008B502480A21024B984708BDA02D0000D1 
:04400000310D00007E 
:0C410000303132333435363738390000A6 
:0400000300001A657A 
:00000001FF 

Từ mã cuối cùng để 0x3FF0 file .bin lấp đầy với 0x00, thì vài byte mã cho jver của tôi (void) chức năng (mà có lẽ chỉ là một cuộc gọi đến hàm jamba_TxBuff), sau đó điền 0x00 tất cả các cách để 0x4100 nơi "" được đặt. BOOM !!! Tất cả những gì tôi sẽ thêm vào bây giờ là hàm 'FILL' trong kịch bản trình liên kết để điền vào với 0xFF thay vì 0x00.

Cảm ơn bạn một lần nữa vì đã tham khảo và tư vấn.

+0

Vì vậy, điền vào chỉ lấp đầy khoảng trống bên trong phần, không phải khoảng trống giữa các phần. Muốn làm điều này vì giao diện người dùng của tôi, tôi đã tạo cho tải khởi động, nhấp nháy tệp .bin, chứ không phải tệp .hex. – kowalski5233

1

Địa chỉ của mọi thứ được xác định ở giai đoạn trình liên kết và cho tất cả mọi thứ chỉ là biểu tượng. Vì vậy, trong khi gcc linker description file force symbol to be at specific address của bạn cho một ví dụ về hàm hoạt động bình đẳng cho dữ liệu. Xác định phiên bản của bạn và đặt nó trong một phần "phiên bản" riêng biệt trong mã C. Sau đó, trình liên kết có thể đặt phần đó ở đâu đó.

Bây giờ phần khó khăn là đến được số kết thúc của rom, có nghĩa là chỉ định địa chỉ xuất phát đủ thấp để phần đó kết thúc vào cuối rom. Làm cho nó một kích thước cố định (3 Bytes của bạn) làm cho đơn giản hơn. Hãy xem cách ram_end được xác định trong tập lệnh trình liên kết.Làm tương tự cho rom_version_start nhưng với rom thay vì ram và sử dụng để đặt phần đầu của phiên bản "" bằng cách sử dụng '. = rom_version_start; '

+0

Xin cảm ơn! Tôi phải chơi xung quanh một chút để có được nó để từ, nhưng thực sự, khái niệm cơ bản là như nhau. – kowalski5233

Các vấn đề liên quan