Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to all c based project, improve linker script to initialize statics properly, fix debugging. #2

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gdbinit
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
target extended-remote localhost:3333
monitor arm semihosting enable
set remotetimeout 1000
set arm force-mode thumb
load
11 changes: 8 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ DEPDIR := $(GENDIR)/dep/
CROSS_PREFIX := arm-none-eabi
AS := $(CROSS_PREFIX)-as
CC := $(CROSS_PREFIX)-gcc
LD := $(CROSS_PREFIX)-ld.bfd
LD := $(CROSS_PREFIX)-gcc
OBJCOPY := $(CROSS_PREFIX)-objcopy

# Debug symbols are enabled with -g, but since we compile ELFs down to bin files, these don't
# affect the code size on-device.
CCFLAGS := -mcpu=cortex-m3 -mthumb -g
CCFLAGS := -mcpu=cortex-m3 -mthumb -g -gdwarf-2

# Used to rebuild when headers used by a source file change.
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
Expand All @@ -39,7 +39,12 @@ INCLUDES := \
ASFLAGS :=

# Defines the offsets used when linking binaries for the STM32.
LDFLAGS := -T stm32_linker_layout.lds

LDFLAGS := -T stm32_linker_layout.lds -Wl,-Map=gen/$(TARGET).map,--cref -Wl,--gc-sections

# Use this to do libc
# LDFLAGS += -specs rdimon.specs -lc -lm -lrdimon -mfloat-abi=soft


# Rule used when no target is specified.
all: \
Expand Down
49 changes: 46 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,19 +198,62 @@ You can then debug a program by executing:

```
cd ~/stm32_bare_lib/
arm-none-eabi-gdb --eval-command="target remote localhost:3333" gen/elf/examples/blink.elf
arm-none-eabi-gdb gen/elf/examples/blink.elf
```

You should see a gdb prompt, and you can execute commands to inspect variables:

For example, recompile and load the binary to the device again
```
(gdb) info locals
(gdb) make
...
(gdb) load
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x080001c4 msp: 0x20005000, semihosting
Loading section .interrupt_vector, size 0x118 lma 0x8000000
Loading section .text, size 0x190 lma 0x8000118
Loading section .init, size 0xc lma 0x80002a8
Loading section .fini, size 0xc lma 0x80002b4
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x080001c4 msp: 0x20005000, semihosting
Start address 0x80001c4, load size 704
Transfer rate: 3 KB/sec, 176 bytes/write.
shift = 536891384
old_config = 2101681877
cleared_config = 172
```
Then you can rerun the program
```
(gdb) cont
Continuing.
```

And interrupt it...
```
(PRESS CTRL-C)
Program received signal SIGINT, Interrupt.
0x08000276 in BusyWaitMicroseconds (us=200000) at ./include/timers.h:37
37 for (; count > 0; --count)
```

Inspect variables...
```
(gdb) p count
$1 = 103869
```

Inspect the stack...
```
(gdb) backtrace
#0 0x08000272 in BusyWaitMicroseconds (us=200000) at ./include/timers.h:37
#1 0x08000296 in OnReset () at examples/blink/blink_main.c:30
#2 0x080001d4 in _main () at source/startup.c:66
```


Set breakpoints, inspect stacks, etc. all like you do in normal self-hosted gdb.


If the program has crashed, you should also be able to inspect the call stack. I haven't found it easy to step through programs or continue execution though.

## Using the Library

Expand Down
16 changes: 15 additions & 1 deletion examples/hello_world/hello_world_main.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/* Copyright 2017 Pete Warden. All Rights Reserved.
/* Copyright 2018 TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -17,9 +20,20 @@ limitations under the License.
#include "debug_log.h"

// The function that's called when the chip is started.

// test static initialization
static char foo_static[] = {'s','t','a','t','i','c','\n'};
static long zeros[4];

void OnReset(void) {
// Output "Hello World!" to the OpenOCD console.
// This call can take hundreds of milliseconds, so don't use it in
// performance-critical code!
// printf("I'm cooler than DebugLog %d\n", 3);
DebugLog("Hello World!\n");
while(1) {
// Busy wait and keep printing
for(long k = 0; k < 100000; k++);
DebugLog(foo_static);
}
}
25 changes: 9 additions & 16 deletions source/boot.s
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright 2017 Pete Warden. All Rights Reserved.
/* Copyright 2018 Pete Warden, TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Expand All @@ -24,15 +24,16 @@ limitations under the License.
// .bin has this table of vectors right at the start. If you don't ensure this,
// you'll see weird hangs when you reset the device.

.cpu cortex-m3
.thumb
.section .interrupt_vector,"a",%progbits
.cpu cortex-m3
.thumb

.word 0x20005000 // Stack start address, at the top of SRAM.
.word _on_reset_asm // Reset.
.word _ld_stack_end_addr // 0x20005000 // Stack start address, at the top of SRAM.
.word _main // Reset.
.word _infinite_loop // NMI.
.word _infinite_loop // Hard Fault.
.word _infinite_loop // MM Fault.
.word _infinite_loop // Bus Fault.
.word _hard_fault_handler // Hard Fault.
.word _mem_fault_handler // MM Fault.
.word _bus_fault_handler // Bus Fault.
.word _infinite_loop // Usage Fault.
.word _infinite_loop // Unused.
.word _infinite_loop // Unused.
Expand Down Expand Up @@ -99,14 +100,6 @@ limitations under the License.

_infinite_loop: b _infinite_loop

.thumb_func
_on_reset_asm:
// OnReset() should be a C-linkage function symbol that's defined elsewhere in
// your program. It works like main() in a non-embedded context, but with no
// arguments.
bl OnReset
b .

.weak OnAdcInterrupt
.thumb_set OnAdcInterrupt, _infinite_loop

Expand Down
67 changes: 67 additions & 0 deletions source/startup.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

typedef long uint32;

// Symbols initialized by the linker script
// zero data initialization
extern uint32 _ld_data_load_source;
extern uint32 _ld_data_load_dest_stop;
extern uint32 _ld_data_load_dest_start;
extern uint32 _ld_bss_data_start;
extern uint32 _ld_bss_data_stop;

// Current main entry point. TODO(aselle): change this to main()
extern void OnReset();

// Used for rdimon semihosting (printf debugging)
extern void initialise_monitor_handles(void);

// Unhandled exceptions
__attribute__ ((section(".text.interrupt_handler")))
void _hard_fault_handler() {
while(1);
}
__attribute__ ((section(".text.interrupt_handler")))
void _mem_fault_handler() {
while(1);
}
__attribute__ ((section(".text.interrupt_handler")))
void _bus_fault_handler() {
while(1);
}


// Copy read-write static initialized memory from flash to ram.
void _load_data_from_flash() {
uint32* src = &_ld_data_load_source;
for(uint32* dest = &_ld_data_load_dest_start; dest != &_ld_data_load_dest_stop;)
*dest++ = *src++;
}

// "Zero" unitialized data with DEADBEEF
void _zero_initialize_bss_data() {
for(uint32* dest = &_ld_bss_data_start; dest != &_ld_bss_data_stop; dest++)
*dest = 0xDEADBEEF;
}
// Put this in the .text.reset segment so the linker script can
// make sure this is not pruned.
__attribute__ ((section(".text.reset")))
int _main() {
_load_data_from_flash();
_zero_initialize_bss_data();
// initialise_monitor_handles();
OnReset();
}
95 changes: 84 additions & 11 deletions stm32_linker_layout.lds
Original file line number Diff line number Diff line change
@@ -1,23 +1,96 @@
/*************************************************************************************
* Memory layout for STM32 linking
*
* Defines where to access the flash and sram for linking purposes. Here's the overall
* layout (from https://github.com/trebisky/stm32f103/blob/master/blink1/blink.lds).
*
/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
/*
* 0x00000000 - 0x07ffffff - aliased to flash or sys memory depending on BOOT jumpers.
* 0x08000000 - 0x0800ffff - Flash.
* 0x1ffff000 - 0x1ffff7ff - Boot firmware in system memory.
* 0x1ffff800 - 0x1fffffff - Option bytes.
* 0x20000000 - 0x20004fff - SRAM.
* 0x40000000 - 0x40023400 - Peripherals
*/


/* Define main entry point */
ENTRY(_main)

/* STM32F103C8T has 20K of RAM and 64K of FLASH */
MEMORY {
flash(RX) : ORIGIN = 0x00000000, LENGTH = 64K
sram(WAIL) : ORIGIN = 0x20000000, LENGTH = 20K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K
}

/* Compute where the stack ends rather than hard coding it */
_ld_stack_end_addr = ORIGIN(RAM) + LENGTH(RAM);
_ld_min_stack_size = 0x200;

SECTIONS {
.text : { *(.text*) } > flash
.bss : { *(.bss*) } > sram

/* interrupt vector goes to top of flash */

.interrupt_vector : {
. = ALIGN(4);
KEEP(*(.interrupt_vector))
. = ALIGN(4);
} >FLASH

/* read only .text and .rodata go to flash */

.text : {
. = ALIGN(4);
KEEP(*(.text.interrupt_handler))
*(.text*)
} >FLASH

.rodata : {
. = ALIGN(4);
*(.rodata*)
. = ALIGN(4);
} >FLASH

/* read mwrite data needs to be stored in flash but copied to ram */
.data : {
. = ALIGN(4);
_ld_data_load_dest_start = .; /* export where to load from */
*(.data*)
. = ALIGN(4);
_ld_data_load_dest_stop = .; /* export where to load from */
} >RAM AT> FLASH
_ld_data_load_source = LOADADDR(.data);

/* unitialized data section needs zero initialization */
.bss :
{
. = ALIGN(4);
_ld_bss_data_start = .;
*(.bss*)
. = ALIGN(4);
_ld_bss_data_stop = .;
} >RAM

._user_heap_stack :
{
. = ALIGN(8);
. += _ld_min_stack_size;
PROVIDE(end = .);
. = ALIGN(8);
} >RAM

/DISCARD/ :
{
libc.a (*)
libm.a (*)
libgcc.a (*)
}

} /* SECTIONS */