Teensy3.5 bare minimum

This page contains the source code for programming the Teensy3.5 in assembly. No frameworks like Adruino or external dependencies are required. It can be used by people who want to learn assembly and experiment with the teensy3.5 developement board.

Most of the work was done by sources found on the internet:

Prerequisites
  1. OpenBSD system
  2. Teensy3.5 Development Board

Documentation
# Need to login
https://www.nxp.com/part/MK64FX512VMD12#/
KQRUG, Kinetis K Quick Reference User Guide

Kinetis K64F Sub-Family Data Sheet
https://www.nxp.com/docs/en/data-sheet/K64P144M120SF5.pdf

ARMv7-M Architecture Reference Manual
https://developer.arm.com/documentation/ddi0403/ee/

# Note
## We used pdftotext (from the poppler-utils-21.12.0 package) to convert the pdf files to text for easy access from the commandline.
pdftotext -layout K64P144M120SF5RM.pdf > K64P144M120SF5RM.txt
Commands
pkg_add teensyloader
pkg_add arm-none-eabi-binutils-2.31.1
pkg_add arm-none-eabi-newlib-2.2.0.1p1
#pkg_add arm-none-eabi-gcc-linaro-7.4.2019.02p0
#pkg_add arm-none-eabi-gdb-7.12.1p0

pgk_add gmake

wget https://aoeu-it.nl/howto/teensy3.5-bare-mimimum.tar.gz
tar -xzf teensy3.5-bare-mimimum.tar.gz
cd teensy3.5-bare-mimimum

gmake clean
gmake all

# Connect the Teensy3.5 development board to the system.
gmake program
# Push the reset button to upload the binary (*.hex)
```
crt0.s
/*
 * File:        crt0.s
 * Purpose:     Lowest level routines for Kinetis.
 *
 * Notes:  This code is modified from the original from the Kinetis K20
 * package from Freescale (kinetis_50MHz_sc.zip).  Vector table entries
 * are based on the K20P64M72F1 Reference Manual by Freescale; refer to
 * the NVIC section in Chapter 3.
 *
 */

        .syntax unified

        .section ".interrupt_vector_table"
        .global __interrupt_vector_table

__interrupt_vector_table:
        .long _estack
        .long _startup /* Reset Handler */
        .long _halt
        .long _halt
        .long _halt
        .long _halt
        .long _halt

        .section ".flash_config"
        .global __flash_config

__flash_config:
  .long 0xFFFFFFFF
  .long 0xFFFFFFFF
  .long 0xFFFFFFFF
  .long 0xFFFFFFFE

        .section ".startup","x",%progbits
        .thumb_func
        .global _startup

_startup:
  mov     r0,#0
        mov     r1,#0
        mov     r2,#0
        mov     r3,#0
        mov     r4,#0
        mov     r5,#0
        mov     r6,#0
        mov     r7,#0
        mov     r8,#0
        mov     r9,#0
        mov     r10,#0
        mov     r11,#0
        mov     r12,#0

  // Disable watchdog interrupt
  cpsid i

  // WDOG_UNLOCK
  ldr r6, =0x4005200E
  ldr r0, =0xC520
  strh r0, [r6]
  ldr r0, =0xD928
  strh r0, [r6]

  // WDOG_STCTRLH
  ldr r6, =0x40052000
  ldr r0, =0x01D2
  strh r0, [r6]

  cpsie i

  // clocks
  ldr r6, =0x40048038
  ldr r0, =0x043F82
  str r0, [r6]

  // Turn on light.
  // PORTC_PCR5
  ldr r6, =0x4004B014
  ldr r0, =0x00000143
  str r0, [r6]

  // GPIOC_PDDR
  ldr r6, =0x400ff094
  ldr r0, =0x20
  str r0, [r6]

  // GPIOC_PSOR
  ldr r6, =0x400FF084
  ldr r0, =0x20
  str r0, [r6]

  b     .

_halt:
        b       .
mk64fx512.ld
/* Teensyduino Core Library
 * http://www.pjrc.com/teensy/
 * Copyright (c) 2017 PJRC.COM, LLC.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * 1. The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * 2. If the Software is incorporated into a build system that allows
 * selection among a list of target devices, then similar target
 * devices manufactured by PJRC.COM must be included in the list of
 * target devices and selectable in the same manner.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

MEMORY
{
        FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
        RAM  (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 64K
}

ENTRY(_startup)

SECTIONS
{
        .text : {
                . = 0;
                KEEP(*(.interrupt_vector_table))
                . = 0x400;
                KEEP(*(.flash_config*))
                *(.startup*)
                *(.text*)
        } > FLASH = 0xFF

        .ARM.exidx : {
                __exidx_start = .;
                *(.ARM.exidx* .gnu.linkonce.armexidx.*)
                __exidx_end = .;
        } > FLASH
        _etext = .;

        _estack = ORIGIN(RAM) + LENGTH(RAM);
        _teensy_model_identifier = 0x1F;
}
Makefile
PROJECT=bare
CPU = cortex-m4
OBJECTS = crt0.o

TOOLPATH = /usr/local
TEENSY3X_BASEPATH = ${HOME}/minimal-setup-teensy
TARGETTYPE = arm-none-eabi

TEENSY3X_INC     = $(TEENSY3X_BASEPATH)
GCC_INC          = $(TOOLPATH)/$(TARGETTYPE)

INCDIRS  = -I$(GCC_INC)
INCDIRS += -I$(TEENSY3X_INC)
INCDIRS += -I.

LSCRIPT = $(TEENSY3X_BASEPATH)/mk64fx512.ld
LIBDIRS  = -L"$(TOOLPATH)/$(TARGETTYPE)/lib"
LIBS =

ASFLAGS = -mcpu=$(CPU) -mthumb
ASFLAGS += -alhs -g

LDFLAGS  = -Map=$(PROJECT).map -T$(LSCRIPT)
#LDFLAGS  = -nostdlib -nostartfiles -shared -Map=$(PROJECT).map -T$(LSCRIPT)
#LDFLAGS  = -nostdlib -nostartfiles -Map=$(PROJECT).map -T$(LSCRIPT)
LDFLAGS += --cref
LDFLAGS += $(LIBDIRS)
LDFLAGS += $(LIBS)

BINDIR = /usr/local/bin
AS = $(BINDIR)/arm-none-eabi-as
AR = $(BINDIR)/arm-none-eabi-ar
LD = $(BINDIR)/arm-none-eabi-ld
OBJCOPY = $(BINDIR)/arm-none-eabi-objcopy
SIZE = $(BINDIR)/arm-none-eabi-size
OBJDUMP = $(BINDIR)/arm-none-eabi-objdump

REMOVE = rm -f

#########################################################################

all:: $(PROJECT).hex $(PROJECT).bin stats dump
#all:: $(PROJECT).hex $(PROJECT).bin

$(PROJECT).hex: $(PROJECT).elf
        @echo "Objcopy (hex)"
        $(OBJCOPY) -R .stack -O ihex $(PROJECT).elf $(PROJECT).hex
        @echo ""

$(PROJECT).bin: $(PROJECT).elf
        @echo "# Objcopy (bin)"
        $(OBJCOPY) -O binary -j .text -j .data $(PROJECT).elf $(PROJECT).bin
        @echo ""

stats: $(PROJECT).elf
        $(SIZE) $(PROJECT).elf

dump: $(PROJECT).elf
        $(OBJDUMP) -h $(PROJECT).elf

#  Linker invocation
$(PROJECT).elf: $(OBJECTS)
        @echo Linking $<
        $(LD) $(OBJECTS) $(LDFLAGS) -o $(PROJECT).elf
        @echo ""

.s.o :
        @echo "# Assembling $< -> $@:"
        $(AS) $(ASFLAGS) -o $@ $<  > $(basename $@).lst
        @echo ""

clean:
        $(REMOVE) *.o
        $(REMOVE) $(PROJECT).hex
        $(REMOVE) $(PROJECT).elf
        $(REMOVE) $(PROJECT).map
        $(REMOVE) $(PROJECT).bin
        $(REMOVE) *.lst

program:
        teensyloader -w --mcu=TEENSY35 blinky.hex

Liability

The information provided herein is for general educational purpose only and does not constitute professional advice. While effort has been made to ensure the accuracy and reliability of the information, no guarantee is given regarding its completeness or applicability. The reader assumes full responsibility for any actions taken based on the information provided. The author shall not be held liable for any direct, indirect, consequential or incidental damages arising from the use or misuse of the information presented.