Keil stm32,使用程序集,分散文件和c。如何将C代码入口点导出到汇编中?

时间:2019-03-18 19:11:34

标签: c assembly stm32 keil

为了结合.c和汇编语言,我想传递 .c代码的起始地址,并对微控制器进行编程以使其程序从该地址开始。 我将我的启动文件写入程序集时,我需要将.c代码起始地址传递给程序集,然后将此地址写入微控制器的特定存储区(因此,微控制器可以在 RESET

之后在该地址上开始执行

尝试在Keil中使用以下结构为stm32f103创建一个项目:

某些.c文件,例如main.c(用于程序的主要部分)。
使用汇编语言的启动文件。它将获取写入某些.c文件中的函数的入口地址,并将其传递给Reset_Handler
分散文件,以这种方式编写:

import gi
import math
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GdkPixbuf

class MainWindow(Gtk.Window):

  def __init__(self):
    Gtk.Window.__init__(self, title = "Test")
    self.drag = False
    self.drag_x = 0
    self.drag_y = 0
    self.pos = []
    viewport = Gtk.Viewport()
    self.darea = Gtk.DrawingArea()
    self.darea.connect("draw", self.expose)

    self.pixbuf = GdkPixbuf.Pixbuf.new_from_file("anntool/test.jpg")
    self.darea.set_size_request(self.pixbuf.get_width(), self.pixbuf.get_height());

    self.maximize() # maximize window on load
    grid = Gtk.Grid()
    self.add(grid)

    scrolled = Gtk.ScrolledWindow()
    scrolled.set_hexpand(True)
    scrolled.set_vexpand(True)
    scrolled.set_kinetic_scrolling(True)
    self.v_scroll = scrolled.get_vadjustment()
    self.h_scroll = scrolled.get_hadjustment()
    scrolled.add_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK)
    scrolled.connect("button-release-event", self.release)
    scrolled.connect("button-press-event", self.click)
    scrolled.connect("motion-notify-event", self.mousemove)
    # scrolled.connect("scroll_event", self.scroll)

    viewport.add(self.darea)
    scrolled.add(viewport)

    grid.add(scrolled)

  def click(self, widget, event):
    if (event.button == 1):
      cr = self.darea.get_parent_window().cairo_create()
      x = self.h_scroll.get_value() + event.x
      y = self.v_scroll.get_value() + event.y
      cr.arc(x, y, 10, 0, 2 * math.pi)
      cr.set_source_rgba(0.0, 0.6, 0.0, 1)
      cr.fill()
    if (event.button == 2):
      self.drag =  True
      self.drag_x = event.x
      self.drag_y = event.y
      self.pos = [self.h_scroll.get_value(), self.v_scroll.get_value()]

  def release(self, widget, event):
    self.drag =  False
    default = Gdk.Cursor(Gdk.CursorType.ARROW)
    widget.get_window().set_cursor(default)

  def mousemove(self, widget, event):
    if self.drag:
      self.h_scroll.set_value(self.pos[0] + self.drag_x - event.x)
      self.v_scroll.set_value(self.pos[1] + self.drag_y - event.y)
      hand = Gdk.Cursor(Gdk.CursorType.HAND1)
      widget.get_window().set_cursor(hand)

  def scroll(self, widget, event):
    print("scrolled")

  def expose(self, widget, event):
    Gdk.cairo_set_source_pixbuf(event, self.pixbuf, 0, 0)
    event.paint()

win = MainWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

问题是将入口点传递给.c函数。需要通过__main传递的.c入口点(起始地址)的Reset_Handler看起来像这样:

LR_IROM1 0x08000000 0x00010000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00010000  {  ; load address = execution address
   *.o (RESET, +First)   ; RESET is code section with I.V.T.
   * (InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_IRAM1 0x20000000 0x00005000  {  ; RW data
   .ANY (+RW +ZI)
  }
}

回合入口点__main,作为对被绑住question的一个程序集的回答:

  

__ main()是编译器为您的C代码提供的入口点。它不是您编写的main()函数,而是对   标准库,静态数据,调用“ main()”之前的堆   功能。

那么,如何在我的汇编文件中获取此入口点?

编辑>>如果有人对KEIL解决方案感兴趣,就这么简单!

简单的组装启动文件:

Reset_Handler PROC

    EXPORT Reset_Handler [WEAK]
    IMPORT __main
    LDR R0, =__main
    BX R0

    ENDP

简单的c文件:

        AREA STACK, NOINIT, READWRITE
        SPACE 0x400       
Stack_top                 

        AREA RESET, DATA, READONLY
        dcd Stack_top     
        dcd Reset_Handler



        EXPORT _InitMC
        IMPORT notmain

        AREA PROGRAM, CODE, READONLY

Reset_Handler PROC
        bl notmain
        ENDP

_InitMC   PROC          ;start of the assembly procedure
Loop
        b Loop          ;infinite loop
        ENDP

        END

链接器与上述链接器相同。 项目构建成功。

1 个答案:

答案 0 :(得分:2)

例如,使用gnu工具链:

引导程序:

17.000000100

C入口点(函数名称无关,有时使用main()会增加垃圾,取决于编译器/工具链)

.cpu cortex-m0
.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word loop
.word loop
.word loop

.thumb_func
reset:
    bl notmain
    b loop
.thumb_func
loop:   b .

.align

.thumb_func
.globl fun
fun:
    bx lr

.end

链接脚本

void fun ( unsigned int );
int notmain ( void )
{
    unsigned int ra;
    for(ra=0;ra<1000;ra++) fun(ra);
    return(0);
}

构建

MEMORY
{
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > rom
    .rodata : { *(.rodata*) } > rom
    .bss : { *(.bss*) } > ram
}

结果(所有拇指版本)

arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding  -mthumb -mcpu=cortex-m0 -march=armv6-m -c so.c -o so.thumb.o
arm-none-eabi-ld -o so.thumb.elf -T flash.ld flash.o so.thumb.o
arm-none-eabi-objdump -D so.thumb.elf > so.thumb.list
arm-none-eabi-objcopy so.thumb.elf so.thumb.bin -O binary
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding  -mthumb -mcpu=cortex-m3 -march=armv7-m -c so.c -o so.thumb2.o
arm-none-eabi-ld -o so.thumb2.elf -T flash.ld flash.o so.thumb2.o
arm-none-eabi-objdump -D so.thumb2.elf > so.thumb2.list
arm-none-eabi-objcopy so.thumb2.elf so.thumb2.bin -O binary

当然,必须使用某些工具将其放置在Flash中的正确位置。

向量表通过逻辑映射到stm32系列中的0x00000000。

Disassembly of section .text:

08000000 <_start>:
 8000000:   20001000
 8000004:   08000015
 8000008:   0800001b
 800000c:   0800001b
 8000010:   0800001b

08000014 <reset>:
 8000014:   f000 f804   bl  8000020 <notmain>
 8000018:   e7ff        b.n 800001a <loop>

0800001a <loop>:
 800001a:   e7fe        b.n 800001a <loop>

0800001c <fun>:
 800001c:   4770        bx  lr
 800001e:   46c0        nop         ; (mov r8, r8)

08000020 <notmain>:
 8000020:   b570        push    {r4, r5, r6, lr}
 8000022:   25fa        movs    r5, #250    ; 0xfa
 8000024:   2400        movs    r4, #0
 8000026:   00ad        lsls    r5, r5, #2
 8000028:   0020        movs    r0, r4
 800002a:   3401        adds    r4, #1
 800002c:   f7ff fff6   bl  800001c <fun>
 8000030:   42ac        cmp r4, r5
 8000032:   d1f9        bne.n   8000028 <notmain+0x8>
 8000034:   2000        movs    r0, #0
 8000036:   bd70        pop {r4, r5, r6, pc}

,在此最少的代码中,重置处理程序将C代码弄乱,然后返回。从技术上讲,它是大多数stm32的完整函数程序(对于RAM较小的那些(例如0x20000400),将堆栈init更改为较小的值,并且应通过单独使用-mthumb(armv4t)或添加cortex-m0来在任何地方工作。很好,不是armv8ms从技术上讲,它们不能支持全部armv6m,但我所熟悉的领域可以支持。

我没有基尔(Kiel),所以不知道如何翻译,但这只是语法而已。