From c3c5f1e5fe27574220c3e94a79048e066cacc121 Mon Sep 17 00:00:00 2001 From: Tomasz Kramkowski Date: Thu, 20 Oct 2016 23:43:29 +0100 Subject: Init commit --- .gitignore | 11 +++ Makefile | 42 ++++++++++++ asm.h | 7 ++ crt0.s | 32 +++++++++ flashconf.s | 6 ++ fmk.c | 9 +++ layout.ld | 38 ++++++++++ lib/le.c | 54 +++++++++++++++ lib/le.h | 12 ++++ lib/reg.h | 45 ++++++++++++ lib/reg/gpio.h | 41 +++++++++++ lib/reg/mcg.h | 56 +++++++++++++++ lib/reg/pmc.h | 27 ++++++++ lib/reg/port.h | 42 ++++++++++++ lib/reg/regdefs.h | 25 +++++++ lib/reg/sim.h | 70 +++++++++++++++++++ lib/reg/uart.h | 8 +++ lib/reg/usbotg.h | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/reg/wdog.h | 37 ++++++++++ lib/string.c | 38 ++++++++++ lib/string.h | 10 +++ setup.c | 90 ++++++++++++++++++++++++ uart/uart.c | 5 ++ uart/uart.h | 6 ++ usb/bdt.h | 14 ++++ usb/ds_conf.xxd | 34 +++++++++ usb/ds_dev.xxd | 18 +++++ usb/ds_lang.xxd | 4 ++ usb/ds_str1.xxd | 22 ++++++ usb/endpt0.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++ usb/endpt0.h | 10 +++ usb/endpt1.c | 36 ++++++++++ usb/endpt1.h | 8 +++ usb/usb.c | 94 +++++++++++++++++++++++++ usb/usb.h | 7 ++ vectors.s | 98 ++++++++++++++++++++++++++ 36 files changed, 1457 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 asm.h create mode 100644 crt0.s create mode 100644 flashconf.s create mode 100644 fmk.c create mode 100644 layout.ld create mode 100644 lib/le.c create mode 100644 lib/le.h create mode 100644 lib/reg.h create mode 100644 lib/reg/gpio.h create mode 100644 lib/reg/mcg.h create mode 100644 lib/reg/pmc.h create mode 100644 lib/reg/port.h create mode 100644 lib/reg/regdefs.h create mode 100644 lib/reg/sim.h create mode 100644 lib/reg/uart.h create mode 100644 lib/reg/usbotg.h create mode 100644 lib/reg/wdog.h create mode 100644 lib/string.c create mode 100644 lib/string.h create mode 100644 setup.c create mode 100644 uart/uart.c create mode 100644 uart/uart.h create mode 100644 usb/bdt.h create mode 100644 usb/ds_conf.xxd create mode 100644 usb/ds_dev.xxd create mode 100644 usb/ds_lang.xxd create mode 100644 usb/ds_str1.xxd create mode 100644 usb/endpt0.c create mode 100644 usb/endpt0.h create mode 100644 usb/endpt1.c create mode 100644 usb/endpt1.h create mode 100644 usb/usb.c create mode 100644 usb/usb.h create mode 100644 vectors.s diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98b3802 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*.o +*.bin +fmk + +*.xxo +*.xxh + +*.d + +tags +TAGS diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..64ab87d --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ +CPU = cortex-m4 +MCU = MK20DX256 +TARGET_ARCH = -mcpu=$(CPU) -mthumb + +AS = arm-none-eabi-as +CC = arm-none-eabi-gcc +OBJCOPY = arm-none-eabi-objcopy +XXD = xxd + +HKTOOL = hktool $(MCU) + +WARNINGS = -Wpointer-arith -Wcast-align -Wformat=2 \ + -Wsuggest-attribute=format -Wall \ + -Wextra -Wpedantic -Winit-self -Wshadow -Wcast-qual \ + -Wstrict-prototypes -Wmissing-prototypes +CFLAGS = -std=c11 $(WARNINGS) -O2 -flto -MMD -MP -ffreestanding -nostdlib -Ilib +LDFLAGS = -T layout.ld -O2 -flto -ffreestanding -nostdlib +ASFLAGS = $(TARGET_ARCH) + +OBJ := crt0.o vectors.o flashconf.o setup.o fmk.o lib/string.o lib/le.o usb/usb.o usb/endpt0.o usb/endpt1.o + +%.bin: % + $(OBJCOPY) -O binary $< $@ +%.xxo: %.xxd + awk '{print $$1}' $< | $(XXD) -r -p -c1 >$@ +%.xxh: %.xxo + $(XXD) -i $< | sed -e 's/_xxo//' >$@ + +all: fmk.bin +fmk: $(OBJ) + +flash: fmk.bin + hktool 0x40000 1024 64 0 $< + hktool -r + +clean: + $(RM) $(OBJ) $(OBJ:.o=.d) $(wildcard usb/*.xxh) fmk fmk.bin + +-include $(OBJ:.o=.d) +usb/endpt0.o: usb/ds_dev.xxh usb/ds_conf.xxh usb/ds_lang.xxh usb/ds_str1.xxh + +.PHONY: all flash clean diff --git a/asm.h b/asm.h new file mode 100644 index 0000000..f6489e6 --- /dev/null +++ b/asm.h @@ -0,0 +1,7 @@ +#ifndef ASM_H +#define ASM_H + +#define CLI() __asm__ volatile ("cpsid i") +#define STI() __asm__ volatile ("cpsie i") + +#endif /* ASM_H */ diff --git a/crt0.s b/crt0.s new file mode 100644 index 0000000..6949ecc --- /dev/null +++ b/crt0.s @@ -0,0 +1,32 @@ +.syntax unified + +.extern setup +.extern main + +.section ".startup","x",%progbits + +.thumb_func +.global _start +_start: + 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 + + bl setup + bl main + + b _halt + +.thumb_func +.global _halt +_halt: b . diff --git a/flashconf.s b/flashconf.s new file mode 100644 index 0000000..9a82db2 --- /dev/null +++ b/flashconf.s @@ -0,0 +1,6 @@ +.syntax unified +.section ".flashconfig" +.long 0xFFFFFFFF +.long 0xFFFFFFFF +.long 0xFFFFFFFF +.long 0xFFFFFFFE diff --git a/fmk.c b/fmk.c new file mode 100644 index 0000000..9df6082 --- /dev/null +++ b/fmk.c @@ -0,0 +1,9 @@ +#include +#include + +int main(void) +{ + /* TODO: Replace with an indefinite wait */ + while (1) + ; +} diff --git a/layout.ld b/layout.ld new file mode 100644 index 0000000..7431496 --- /dev/null +++ b/layout.ld @@ -0,0 +1,38 @@ +MEMORY { + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K + RAM (rw!x) : ORIGIN = 0x1FFF8000, LENGTH = 64K +} + +SECTIONS { + . = 0x00000000; + .text : { + KEEP(*(.vectors)) + . = 0x400; + KEEP(*(.flashconfig*)) + *(.startup*) + *(.text*) + *(.rodata*) + . = ALIGN(4); + } > FLASH + + .data : { + . = ALIGN(4); + _sflashdata = LOADADDR(.data); + _sdata = .; + *(.fastrun*) + *(.data*) + . = ALIGN(4); + _edata = .; + } > RAM AT > FLASH + + .bss : { + . = ALIGN(4); + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } > RAM + + _estack = ORIGIN(RAM) + LENGTH(RAM); +} diff --git a/lib/le.c b/lib/le.c new file mode 100644 index 0000000..47ed5f8 --- /dev/null +++ b/lib/le.c @@ -0,0 +1,54 @@ +/* lib/le.c -- Basic little endian byte order functions + * + * Copyright (C) 2016 Tomasz Kramkowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include + +#include "le.h" + +uint16_t le16toh(const void *_data) +{ + const unsigned char *data = _data; + + return (uint16_t)data[0] | (uint16_t)data[1] << 8; +} + +uint32_t le32toh(const void *_data) +{ + const unsigned char *data = _data; + + return (uint32_t)data[0] | (uint32_t)data[1] << 8 + | (uint32_t)data[2] << 16 | (uint32_t)data[3] << 24; +} + +void htole16(void *_data, uint16_t value) +{ + unsigned char *data = _data; + + data[0] = value >> 0 & 0xff; + data[1] = value >> 8 & 0xff; +} + +void htole32(void *_data, uint32_t value) +{ + unsigned char *data = _data; + + data[0] = value >> 0 & 0xff; + data[1] = value >> 8 & 0xff; + data[2] = value >> 16 & 0xff; + data[3] = value >> 24 & 0xff; +} diff --git a/lib/le.h b/lib/le.h new file mode 100644 index 0000000..e1341a7 --- /dev/null +++ b/lib/le.h @@ -0,0 +1,12 @@ +#ifndef LE_H +#define LE_H + +#include + +uint16_t le16toh(const void *data); +uint32_t le32toh(const void *data); + +void htole16(void *data, uint16_t value); +void htole32(void *data, uint32_t value); + +#endif /* LE_H */ diff --git a/lib/reg.h b/lib/reg.h new file mode 100644 index 0000000..1a10792 --- /dev/null +++ b/lib/reg.h @@ -0,0 +1,45 @@ +#ifndef LIB_REG_H +#define LIB_REG_H + +#include +#include +//#include +//#include +#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include +#include +//#include +//#include +//#include +//#include +/*#include */ +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include +//#include +#include +//#include +//#include + +#endif /* LIB_REG_H */ diff --git a/lib/reg/gpio.h b/lib/reg/gpio.h new file mode 100644 index 0000000..6bb8d34 --- /dev/null +++ b/lib/reg/gpio.h @@ -0,0 +1,41 @@ +#ifndef LIB_REG_GPIO_H +#define LIB_REG_GPIO_H + +#include + +#define GPIOA_PDOR REG_32(0x400FF000) /* Port Data Output Register */ +#define GPIOA_PSOR REG_32(0x400FF004) /* Port Set Output Register */ +#define GPIOA_PCOR REG_32(0x400FF008) /* Port Clear Output Register */ +#define GPIOA_PTOR REG_32(0x400FF00C) /* Port Toggle Output Register */ +#define GPIOA_PDIR REG_32(0x400FF010) /* Port Data Input Register */ +#define GPIOA_PDDR REG_32(0x400FF014) /* Port Data Direction Register */ + +#define GPIOB_PDOR REG_32(0x400FF040) /* Port Data Output Register */ +#define GPIOB_PSOR REG_32(0x400FF044) /* Port Set Output Register */ +#define GPIOB_PCOR REG_32(0x400FF048) /* Port Clear Output Register */ +#define GPIOB_PTOR REG_32(0x400FF04C) /* Port Toggle Output Register */ +#define GPIOB_PDIR REG_32(0x400FF050) /* Port Data Input Register */ +#define GPIOB_PDDR REG_32(0x400FF054) /* Port Data Direction Register */ + +#define GPIOC_PDOR REG_32(0x400FF080) /* Port Data Output Register */ +#define GPIOC_PSOR REG_32(0x400FF084) /* Port Set Output Register */ +#define GPIOC_PCOR REG_32(0x400FF088) /* Port Clear Output Register */ +#define GPIOC_PTOR REG_32(0x400FF08C) /* Port Toggle Output Register */ +#define GPIOC_PDIR REG_32(0x400FF090) /* Port Data Input Register */ +#define GPIOC_PDDR REG_32(0x400FF094) /* Port Data Direction Register */ + +#define GPIOD_PDOR REG_32(0x400FF0C0) /* Port Data Output Register */ +#define GPIOD_PSOR REG_32(0x400FF0C4) /* Port Set Output Register */ +#define GPIOD_PCOR REG_32(0x400FF0C8) /* Port Clear Output Register */ +#define GPIOD_PTOR REG_32(0x400FF0CC) /* Port Toggle Output Register */ +#define GPIOD_PDIR REG_32(0x400FF0D0) /* Port Data Input Register */ +#define GPIOD_PDDR REG_32(0x400FF0D4) /* Port Data Direction Register */ + +#define GPIOE_PDOR REG_32(0x400FF100) /* Port Data Output Register */ +#define GPIOE_PSOR REG_32(0x400FF104) /* Port Set Output Register */ +#define GPIOE_PCOR REG_32(0x400FF108) /* Port Clear Output Register */ +#define GPIOE_PTOR REG_32(0x400FF10C) /* Port Toggle Output Register */ +#define GPIOE_PDIR REG_32(0x400FF110) /* Port Data Input Register */ +#define GPIOE_PDDR REG_32(0x400FF114) /* Port Data Direction Register */ + +#endif /* LIB_REG_GPIO_H */ diff --git a/lib/reg/mcg.h b/lib/reg/mcg.h new file mode 100644 index 0000000..bc1afcf --- /dev/null +++ b/lib/reg/mcg.h @@ -0,0 +1,56 @@ +#ifndef LIB_REG_MCG_H +#define LIB_REG_MCG_H + +#include + +#define MCG_C1 REG_8(0x40064000) /* MCG Control 1 Register */ +#define C1_CLKS 6 /* Clock Source Select */ +#define C1_CLKS_M (uint8_t)(BITS(2) << C1_CLKS) +#define C1_FRDIV 3 /* FLL External Reference Divider */ +#define C1_FRDIV_M (uint8_t)(BITS(3) << C1_FRDIV) +#define C1_IREFS 2 /* Internal Reference Select */ +#define C1_IRCLKEN 1 /* Internal Reference Clock Enable */ +#define C1_IREFSTEN 0 /* Internal Reference Stop Enable */ + +#define MCG_C2 REG_8(0x40064001) /* MCG Control 2 Register */ +#define C2_LOCRE0 7 /* Loss of Clock Reset Enable */ +#define C2_RANGE0 4 /* Frequency Range Select */ +#define C2_RANGE0_M (uint8_t)(BITS(2) << C2_RANGE0) +#define C2_HGO0 3 /* High Gain Oscillator Select */ +#define C2_EREFS0 2 /* External Reference Select */ +#define C2_LP 1 /* Low Power Select */ +#define C2_IRCS 0 /* Internal Reference Clock Select */ + +#define MCG_C3 REG_8(0x40064002) /* MCG Control 3 Register */ +#define MCG_C4 REG_8(0x40064003) /* MCG Control 4 Register */ + +#define MCG_C5 REG_8(0x40064004) /* MCG Control 5 Register */ +#define C5_PLLCLKEN0 6 /* PLL Clock Enable */ +#define C5_PLLSTEN0 5 /* PLL Stop Enable */ +#define C5_PRDIV0 0 /* PLL External Reference Divider */ +#define C5_PRDIV0_M (uint8_t)(BITS(5) << C5_PRDIV0) + +#define MCG_C6 REG_8(0x40064005) /* MCG Control 6 Register */ +#define C6_LOLIE0 7 /* Loss of Lock Interrrupt Enable */ +#define C6_PLLS 6 /* PLL Select */ +#define C6_CME0 5 /* Clock Monitor Enable */ +#define C6_VDIV0 0 /* VCO 0 Divider */ +#define C6_VDIV0_M (uint8_t)(BITS(5) << C6_VDIV0) + +#define MCG_S REG_8(0x40064006) /* MCG Status Register */ +#define S_LOLS0 7 /* Loss of Lock Status */ +#define S_LOCK0 6 /* Lock Status */ +#define S_PLLST 5 /* PLL Select Status */ +#define S_IREFST 4 /* Internal Reference Status */ +#define S_CLKST 2 /* Clock Mode Status */ +#define S_CLKST_M (uint8_t)(BITS(2) << S_CLKST) +#define S_OSCINIT0 1 /* OSC Initialization */ +#define S_IRCST 0 /* Internal Reference Clock Status */ + +#define MCG_SC REG_8(0x40064008) /* MCG Status and Control Register */ +#define MCG_ATCVH REG_8(0x4006400A) /* MCG Auto Trim Compare Value High Register */ +#define MCG_ATCVL REG_8(0x4006400B) /* MCG Auto Trim Compare Value Low Register */ +#define MCG_C7 REG_8(0x4006400C) /* MCG Control 7 Register */ +#define MCG_C8 REG_8(0x4006400D) /* MCG Control 8 Register */ + +#endif /* LIB_REG_MCG_H */ diff --git a/lib/reg/pmc.h b/lib/reg/pmc.h new file mode 100644 index 0000000..4aef0be --- /dev/null +++ b/lib/reg/pmc.h @@ -0,0 +1,27 @@ +#ifndef LIB_REG_PMC_H +#define LIB_REG_PMC_H + +#include + +#define PMC_LVDSC1 REG_8(0x4007D000) /* Low Voltage Detect Status And Control 1 register */ +#define LVDSC1_LVDF 7 /* Low-Voltage Detect Flag */ +#define LVDSC1_LVDACK 6 /* Low-Voltage Detect Acknowledge */ +#define LVDSC1_LVDIE 5 /* Low-Voltage Detect Interrupt Enable */ +#define LVDSC1_LVDRE 4 /* Low-Voltage Detect Reset Enable */ +#define LVDSC1_LVDV 0 /* Low-Voltage Detect Voltage Select */ +#define LVDSC1_LVDV_M (uint8_t)(BITS(2) << LVDSC1_LVDV) + +#define PMC_LVDSC2 REG_8(0x4007D001) /* Low Voltage Detect Status And Control 2 register */ +#define LVDSC2_LVWF 7 /* Low-Voltage Warning Flag */ +#define LVDSC2_LVWACK 6 /* Low-Voltage Warning Acknowledge */ +#define LVDSC2_LVWIE 5 /* Low-Voltage Warning Interrupt Enable */ +#define LVDSC2_LVWV 0 /* Low-Voltage Warning Voltage Select */ +#define LVDSC2_LVWV_M (uint8_t)(BITS(2) << LVDSC2_LVWV) + +#define PMC_REGSC REG_8(0x4007D002) /* Regulator Status And Control register */ +#define REGSC_BGEN 4 /* Bandgap Enable In VLPx Operation */ +#define REGSC_ACKISO 3 /* Acknowledge Isolation */ +#define REGSC_REGONS 2 /* Regulator In Run Regulation Status */ +#define REGSC_BGBE 1 /* Bandgap Buffer Enable */ + +#endif /* LIB_REG_PMC_H */ diff --git a/lib/reg/port.h b/lib/reg/port.h new file mode 100644 index 0000000..76b8d9c --- /dev/null +++ b/lib/reg/port.h @@ -0,0 +1,42 @@ +#ifndef LIB_REG_PORT_H +#define LIB_REG_PORT_H + +#include + +#define PORTA_PCR(n) REG_32(0x40049000 + 4 * (n)) /* Pin Control Register n */ +#define PORTB_PCR(n) REG_32(0x4004A000 + 4 * (n)) /* Pin Control Register n */ +#define PORTC_PCR(n) REG_32(0x4004B000 + 4 * (n)) /* Pin Control Register n */ +#define PORTD_PCR(n) REG_32(0x4004C000 + 4 * (n)) /* Pin Control Register n */ +#define PORTE_PCR(n) REG_32(0x4004D000 + 4 * (n)) /* Pin Control Register n */ +#define PCR_ISF 24 /* Interrupt Status Flag */ +#define PCR_IRQC 16 /* Interrupt Configuration */ +#define PCR_IRQC_M (uint32_t)(BITS(4) << PCR_IRQC) +#define PCR_LK 15 /* Lock Register */ +#define PCR_MUX 8 /* Pin Mux Control */ +#define PCR_MUX_M (uint32_t)(BITS(3) << PCR_MUX) +#define PCR_DSE 6 /* Drive Strength Enable */ +#define PCR_ODE 5 /* Open Drain Enable */ +#define PCR_PFE 4 /* Passive Filter Enable */ +#define PCR_SRE 2 /* Slew Rate Enable */ +#define PCR_PE 1 /* Pull Enable */ +#define PCR_PS 0 /* Pull Select */ + +#define PORTA_GPCLR REG_32(0x40049080) /* Global Pin Control Low Register */ +#define PORTB_GPCLR REG_32(0x4004A080) /* Global Pin Control Low Register */ +#define PORTC_GPCLR REG_32(0x4004B080) /* Global Pin Control Low Register */ +#define PORTD_GPCLR REG_32(0x4004C080) /* Global Pin Control Low Register */ +#define PORTE_GPCLR REG_32(0x4004D080) /* Global Pin Control Low Register */ + +#define PORTA_GPCHR REG_32(0x40049084) /* Global Pin Control High Register */ +#define PORTB_GPCHR REG_32(0x4004A084) /* Global Pin Control High Register */ +#define PORTC_GPCHR REG_32(0x4004B084) /* Global Pin Control High Register */ +#define PORTD_GPCHR REG_32(0x4004C084) /* Global Pin Control High Register */ +#define PORTE_GPCHR REG_32(0x4004D084) /* Global Pin Control High Register */ + +#define PORTA_ISFR REG_32(0x400490A0) /* Interrupt Status Flag Register */ +#define PORTB_ISFR REG_32(0x4004A0A0) /* Interrupt Status Flag Register */ +#define PORTC_ISFR REG_32(0x4004B0A0) /* Interrupt Status Flag Register */ +#define PORTD_ISFR REG_32(0x4004C0A0) /* Interrupt Status Flag Register */ +#define PORTE_ISFR REG_32(0x4004D0A0) /* Interrupt Status Flag Register */ + +#endif /* LIB_REG_PORT_H */ diff --git a/lib/reg/regdefs.h b/lib/reg/regdefs.h new file mode 100644 index 0000000..6a38c76 --- /dev/null +++ b/lib/reg/regdefs.h @@ -0,0 +1,25 @@ +#ifndef LIB_REG_REGDEFS_H +#define LIB_REG_REGDEFS_H + +#include + +#define REG_8(a) (*(volatile uint8_t *)(a)) +#define REG_16(a) (*(volatile uint16_t *)(a)) +#define REG_32(a) (*(volatile uint32_t *)(a)) + +#define BV(b) (1 << (b)) +#define IS_BIT_SET(reg, bit) (!!((reg) & BV(bit))) +#define WAIT_BIT_UNSET(reg, bit) do { } while (IS_BIT_SET(reg, bit)) +#define WAIT_BIT_SET(reg, bit) do { } while (!IS_BIT_SET(reg, bit)) + +#define SET_BIT(reg, bit) ((reg) |= BV(bit)) +#define UNSET_BIT(reg, bit) ((reg) &= ~BV(bit)) + +#define GET_BIT(reg, bit) !!((reg) & BV(bit)) +#define GET_BITS(reg, offset) (((reg) & (offset ## _M)) >> (offset)) + +#define SET_MASKED(reg, mask, bits) ((reg) = ((reg) & ~(mask)) | ((bits) & (mask))) + +#define BITS(n) (0xffffffff >> (32 - (n))) + +#endif /* LIB_REG_REGDEFS_H */ diff --git a/lib/reg/sim.h b/lib/reg/sim.h new file mode 100644 index 0000000..93839e8 --- /dev/null +++ b/lib/reg/sim.h @@ -0,0 +1,70 @@ +#ifndef LIB_REG_SIM_H +#define LIB_REG_SIM_H + +#include + +#define SIM_SOPT REG_32(0x140047000) /* System Options Register 1 */ +#define SIM_SOPT1CFG REG_32(0x40047004) /* SOPT1 Configuration Register */ + +#define SIM_SOPT2 REG_32(0x40048004) /* System Options Register 2 */ +#define SOPT2_USBSRC 18 /* USB clock source select */ +#define SOPT2_PLLFLLSEL 16 /* PLL/FLL clock select */ +#define SOPT2_TRACECLKSEL 12 /* Debug trace clock select */ +#define SOPT2_PTD7PAD 11 /* PTD7 pad drive strength */ +#define SOPT2_CLKOUTSEL 5 /* CLKOUT select */ +#define SOPT2_CLKOUTSEL_M (BITS(3) << SOPT2_CLKOUTSEL) +#define SOPT2_RTCCLKOUTSEL 4 /* RTC clock out select */ + +#define SIM_SOPT4 REG_32(0x4004800C) /* System Options Register 4 */ +#define SIM_SOPT5 REG_32(0x40048010) /* System Options Register 5 */ +#define SIM_SOPT7 REG_32(0x40048018) /* System Options Register 7 */ +#define SIM_SDID REG_32(0x40048024) /* System Device Identification Register */ +#define SIM_SCGC1 REG_32(0x40048028) /* System Clock Gating Control Register 1 */ +#define SIM_SCGC2 REG_32(0x4004802C) /* System Clock Gating Control Register 2 */ +#define SIM_SCGC3 REG_32(0x40048030) /* System Clock Gating Control Register 3 */ + +#define SIM_SCGC4 REG_32(0x40048034) /* System Clock Gating Control Register 4 */ +#define SCGC4_VREF 20 /* VREF Clock Gate Control */ +#define SCGC4_CMP 19 /* Comparator Clock Gate Control */ +#define SCGC4_USBOTG 18 /* USB Clock Gate Control */ +#define SCGC4_UART2 12 /* UART2 Clock Gate Control */ +#define SCGC4_UART1 11 /* UART1 Clock Gate Control */ +#define SCGC4_UART0 10 /* UART0 Clock Gate Control */ +#define SCGC4_I2C1 7 /* I2C1 Clock Gate Control */ +#define SCGC4_I2C0 6 /* I2C0 Clock Gate Control */ +#define SCGC4_CMT 2 /* CMT Clock Gate Control */ +#define SCGC4_EWM 1 /* EWM Clock Gate Control */ + +#define SIM_SCGC5 REG_32(0x40048038) /* System Clock Gating Control Register 5 */ +#define SCGC5_PORTE 13 /* Port E Clock Gate Control */ +#define SCGC5_PORTD 12 /* Port D Clock Gate Control */ +#define SCGC5_PORTC 11 /* Port C Clock Gate Control */ +#define SCGC5_PORTB 10 /* Port B Clock Gate Control */ +#define SCGC5_PORTA 9 /* Port A Clock Gate Control */ +#define SCGC5_TSI 5 /* TSI Clock Gate Control */ +#define SCGC5_LPTIMER 0 /* Low Power Timer Access Control */ + +#define SIM_SCGC6 REG_32(0x4004803C) /* System Clock Gating Control Register 6 */ +#define SIM_SCGC7 REG_32(0x40048040) /* System Clock Gating Control Register 7 */ + +#define SIM_CLKDIV1 REG_32(0x40048044) /* System Clock Divider Register 1 */ +#define CLKDIV1_OUTDIV1 28 /* Clock 1 output divider value */ +#define CLKDIV1_OUTDIV1_M (uint32_t)(BITS(4) << CLKDIV1_OUTDIV1) +#define CLKDIV1_OUTDIV2 24 /* Clock 2 output divider value */ +#define CLKDIV1_OUTDIV2_M (uint32_t)(BITS(4) << CLKDIV1_OUTDIV2) +#define CLKDIV1_OUTDIV4 16 /* Clock 4 output divider value */ +#define CLKDIV1_OUTDIV4_M (uint32_t)(BITS(4) << CLKDIV1_OUTDIV4) + +#define SIM_CLKDIV2 REG_32(0x40048048) /* System Clock Divider Register 2 */ +#define CLKDIV2_USBDIV 1 /* USB clock divider divisor */ +#define CLKDIV2_USBDIV_M (uint32_t)(BITS(3) << CLKDIV2_USBDIV) +#define CLKDIV2_USBFRAC 0 /* USB clock divider fraction */ + +#define SIM_FCFG1 REG_32(0x4004804C) /* Flash Configuration Register 1 */ +#define SIM_FCFG2 REG_32(0x40048050) /* Flash Configuration Register 2 */ +#define SIM_UIDH REG_32(0x40048054) /* Unique Identification Register High */ +#define SIM_UIDMH REG_32(0x40048058) /* Unique Identification Register Mid-High */ +#define SIM_UIDML REG_32(0x4004805C) /* Unique Identification Register Mid Low */ +#define SIM_UIDL REG_32(0x40048060) /* Unique Identification Register Low */ + +#endif /* LIB_REG_SIM_H */ diff --git a/lib/reg/uart.h b/lib/reg/uart.h new file mode 100644 index 0000000..a23d2f6 --- /dev/null +++ b/lib/reg/uart.h @@ -0,0 +1,8 @@ +#ifndef LIB_REG_UART_H +#define LIB_REG_UART_H + +#include "regdefs.h" + + + +#endif /* LIB_REG_UART_H */ diff --git a/lib/reg/usbotg.h b/lib/reg/usbotg.h new file mode 100644 index 0000000..56f00aa --- /dev/null +++ b/lib/reg/usbotg.h @@ -0,0 +1,202 @@ +#ifndef LIB_REG_USBOTG_H +#define LIB_REG_USBOTG_H + +#include "regdefs.h" + +#define USB0_PERID REG_8(0x40072000) /* Peripheral ID register */ +#define PERID_ID 0 /* Peripheral Identification */ +#define PERID_ID_M (uint8_t)(0x3F) + +#define USB0_IDCOMP REG_8(0x40072004) /* Peripheral ID Complement register */ +#define IDCOMP_NID 0 /* Ones complement of peripheral identification bits. */ +#define IDCOMP_NID_M (uint8_t)(0x3F) + +#define USB0_REV REG_8(0x40072008) /* Peripheral Revision register */ +#define REV_REV 0 /* Revision */ +#define REV_REV_M (uint8_t)(0xFF) + +#define USB0_ADDINFO REG_8(0x4007200C) /* Peripheral Additional Info register */ +#define ADDINFO_IRQNUM 3 /* Assigned Interrupt Request Number. */ +#define ADDINFO_IRQNUM_M (uint8_t)(BITS(5) << ADDINFO_IRQNUM) +#define ADDINFO_IEHOST 0 /* Set if SIE is in host mode. */ + +#define USB0_OTGISTAT REG_8(0x40072010) /* OTG Interrupt Status register */ +#define OTGISTAT_IDCHG 7 /* Set on change in the ID Signal from the USB connector. */ +#define OTGISTAT_ONEMSEC 6 /* Set on 1 ms timer expire. */ +#define OTGISTAT_LINE_STATE_CHG 5 /* Set when USB line state changes. */ +#define OTGISTAT_SESSVLDCHG 3 +#define OTGISTAT_B_SESS_CHG 2 +#define OTGISTAT_AVBUSCHG 0 + +#define USB0_OTGICR REG_8(0x40072014) /* OTG Interrupt Control Register */ +#define OTGICR_IDEN 7 /* ID Interrupt Enable */ +#define OTGICR_ONEMSECEN 6 /* One Millisecond Interrupt Enable */ +#define OTGICR_LINESTATEEN 5 /* Line State Change Interrupt Enable */ +#define OTGICR_SESSVLDEN 3 /* Session Valid Interrupt Enable */ +#define OTGICR_BSESSEN 2 /* B Session END Interrupt Enable */ +#define OTGICR_AVBUSEN 0 /* A VBUS Valid Interrupt Enable */ + +#define USB0_OTGSTAT REG_8(0x40072018) /* OTG Status register */ +#define OTGSTAT_ID 7 +#define OTGSTAT_ONEMSECEN 6 +#define OTGSTAT_LINESTATESTABLE 5 +#define OTGSTAT_SESS_VLD 3 +#define OTGSTAT_BSESSEND 2 +#define OTGSTAT_AVBUSVLD 0 + +#define USB0_OTGCTL REG_8(0x4007201C) /* OTG Control register */ +#define OTGCTL_DPHIGH 7 /* D+ Data Line pullup resistor enable */ +#define OTGCTL_DPLOW 5 /* D+ Data Line pull-down resistor enable */ +#define OTGCTL_DMLOW 4 /* D– Data Line pull-down resistor enable */ +#define OTGCTL_OTGEN 2 /* On-The-Go pullup/pulldown resistor enable */ + +#define USB0_ISTAT REG_8(0x40072080) /* Interrupt Status register */ +#define ISTAT_STALL 7 /* Stall Interrupt */ +#define ISTAT_ATTACH 6 /* Attach Interrupt */ +#define ISTAT_RESUME 5 +#define ISTAT_SLEEP 4 +#define ISTAT_TOKDNE 3 +#define ISTAT_SOFTOK 2 +#define ISTAT_ERROR 1 +#define ISTAT_USBRST 0 + +#define USB0_INTEN REG_8(0x40072084) /* Interrupt Enable register */ +#define INTEN_STALLEN 7 /* STALL Interrupt Enable */ +#define INTEN_ATTACHEN 6 /* ATTACH Interrupt Enable */ +#define INTEN_RESUMEEN 5 /* RESUME Interrupt Enable */ +#define INTEN_SLEEPEN 4 /* SLEEP Interrupt Enable */ +#define INTEN_TOKDNEEN 3 /* TOKDNE Interrupt Enable */ +#define INTEN_SOFTOKEN 2 /* SOFTOK Interrupt Enable */ +#define INTEN_ERROREN 1 /* ERROR Interrupt Enable */ +#define INTEN_USBRSTEN 0 /* USBRST Interrupt Enable */ + +#define USB0_ERRSTAT REG_8(0x40072088) /* Error Interrupt Status register */ +#define ERRSTAT_BTSERR 7 +#define ERRSTAT_DMAERR 5 +#define ERRSTAT_BTOERR 4 +#define ERRSTAT_DFN8 3 +#define ERRSTAT_CRC16 2 +#define ERRSTAT_CRC5EOF 1 +#define ERRSTAT_PIDERR 0 + +#define USB0_ERREN REG_8(0x4007208C) /* Error Interrupt Enable register */ +#define ERREN_BTSERREN 7 /* BTSERR Interrupt Enable */ +#define ERREN_DMAERREN 5 /* DMAERR Interrupt Enable */ +#define ERREN_BTOERREN 4 /* BTOERR Interrupt Enable */ +#define ERREN_DFN8EN 3 /* DFN8 Interrupt Enable */ +#define ERREN_CRC16EN 2 /* CRC16 Interrupt Enable */ +#define ERREN_CRC5EOFEN 1 /* CRC5EOF Interrupt Enable */ +#define ERREN_PIDERREN 0 /* PIDERR Interrupt Enable */ + +#define USB0_STAT REG_8(0x40072090) /* Status register */ +#define STAT_ENDP 4 +#define STAT_ENDP_M (uint8_t)(BITS(4) << STAT_ENDP) +#define STAT_TX 3 /* Transmit Indicator */ +#define STAT_ODD 2 + +#define USB0_CTL REG_8(0x40072094) /* Control register */ +#define CTL_JSTATE 7 /* Live USB differential receiver JSTATE signal */ +#define CTL_SE0 6 /* Live USB Single Ended Zero signal */ +#define CTL_TXSUSPENDTOKENBUSY 5 +#define CTL_RESET 4 +#define CTL_HOSTMODEEN 3 +#define CTL_RESUME 2 +#define CTL_ODDRST 1 +#define CTL_USBENSOFEN 0 /* USB Enable */ + +#define USB0_ADDR REG_8(0x40072098) /* Address register */ +#define ADDR_LSEN 7 +#define ADDR_ADDR 0 +#define ADDR_ADDR_M (uint8_t)(BITS(7)) + +#define USB0_BDTPAGE1 REG_8(0x4007209C) /* BDT Page Register 1 */ + +#define USB0_FRMNUML REG_8(0x400720A0) /* Frame Number Register Low */ +#define FRMNUML_FRM 0 +#define FRMNUML_FRM_M (uint8_t)(BITS(8) << FRMNUML_FRM) + +#define USB0_FRMNUMH REG_8(0x400720A4) /* Frame Number Register High */ +#define FRMNUMH_FRM 0 +#define FRMNUMH_FRM_M (uint8_t)(BITS(3) << FRMNUMH_FRM_M) + +#define USB0_TOKEN REG_8(0x400720A8) /* Token register */ +#define TOKEN_TOKENPID 4 +#define TOKEN_TOKENPID_M (uint8_t)(BITS(4) << TOKEN_TOKENPID) +#define TOKEN_TOKENENDPT 0 +#define TOKEN_TOKENENDPT_M (uint8_t)(BITS(4) << TOKEN_TOKENENDPT) + +#define USB0_SOFTHLD REG_8(0x400720AC) /* SOF Threshold Register */ +#define SOFTHLD_CNT 0 +#define SOFTHLD_CNT_M (uint8_t)(BITS(8) << SOFTHLD_CNT) + +#define USB0_BDTPAGE2 REG_8(0x400720B0) /* BDT Page Register 2 */ +#define BDTPAGE2_BDTBA 0 +#define BDTPAGE2_BDTBA_M (uint8_t)(BITS(8) << BDTPAGE2_BDTBA) + +#define USB0_BDTPAGE3 REG_8(0x400720B4) /* BDT Page Register 3 */ +#define BDTPAGE3_BDTBA 0 +#define BDTPAGE3_BDTBA_M (uint8_t)(BITS(8) << BDTPAGE3_BDTBA) + +#define USB0_ENDPT(n) REG_8(0x400720C0 + 4 * (n)) /* Endpoint Control register */ +#define ENDPT_HOSTWOHUB 7 +#define ENDPT_RETRYDIS 6 +#define ENDPT_EPCTLDIS 4 +#define ENDPT_EPRXEN 3 +#define ENDPT_EPTXEN 2 +#define ENDPT_EPSTALL 1 +#define ENDPT_EPHSHK 0 + +#define USB0_USBCTRL REG_8(0x40072100) /* USB Control register */ +#define USBCTRL_SUSP 7 /* Places the USB transceiver into the suspend state. */ +#define USBCTRL_PDE 6 /* Enables the weak pulldowns on the USB transceiver. */ + +#define USB0_OBSERVE REG_8(0x40072104) /* USB OTG Observe register */ +#define OBSERVE_DPPU 7 /* Provides observability of the D+ Pullup */ +#define OBSERVE_DPPD 6 /* Provides observability of the D+ Pulldown */ +#define OBSERVE_DMPD 4 /* Provides observability of the D- Pulldown */ + +#define USB0_CONTROL REG_8(0x40072108) /* USB OTG Control register */ +#define CONTROL_DPPULLUPNONOTG 4 /* DP Pullup in non-OTG device mode state */ + +#define USB0_USBTRC0 REG_8(0x4007210C) /* USB Transceiver Control Register 0 */ +#define USBTRC0_USBRESET 7 /* USB Reset */ +#define USBTRC0_USBRESMEN 5 /* Asynchronous Resume Interrupt Enable */ +#define USBTRC0_SYNC_DET 1 /* Synchronous USB Interrupt Detect */ +#define USBTRC0_USB_RESUME_INT 0 /* USB Asynchronous Interrupt */ + +#define USB0_USBFRMADJUST REG_8(0x40072114) /* Frame Adjust Register */ +#define USBFRMADJUST_ADJ 0 +#define USBFRMADJUST_ADJ_M (uint8_t)(BITS(8) << USBFRMADJUST_ADJ) + +__attribute__ ((packed)) +struct usb0_bd { + uint32_t desc; + void *addr; +}; +//#define USB0_BD(desc, addr) (struct usb0_bd){(desc), (addr)} +#define USB0_BD_INIT(size, data01) ((size) << BD_BC | BV(BD_OWN) | \ + ((data01) & 1) << BD_DATA01 | BV(BD_DTS)) +#define BD_BC 16 /* Byte Count */ +#define BD_BC_M (uint32_t)(BITS(10) << BC) +#define BD_OWN 7 +#define BD_DATA01 6 +#define BD_KEEP 5 +#define BD_NINC 4 +#define BD_DTS 3 +#define BD_BDT_STALL 2 +#define BD_TOK_PID 2 +#define BD_TOK_PID_M (uint32_t)(BITS(4) << BD_TOK_PID) + +#define BD_TOK_PID_OUT 0x1 +#define BD_TOK_PID_IN 0x9 +#define BD_TOK_PID_SETUP 0xd + +#define BD_TOK_PID_DATA0 0x3 +#define BD_TOK_PID_DATA1 0xb +#define BD_TOK_PID_ACK 0x2 +#define BD_TOK_PID_STALL 0xe +#define BD_TOK_PID_NAK 0xa +#define BD_TOK_PID_TIMEOUT 0x0 +#define BD_TOK_PID_ERROR 0xf + +#endif /* LIB_REG_USBOTG_H */ diff --git a/lib/reg/wdog.h b/lib/reg/wdog.h new file mode 100644 index 0000000..a2596c8 --- /dev/null +++ b/lib/reg/wdog.h @@ -0,0 +1,37 @@ +#ifndef LIB_REG_WDOG_H +#define LIB_REG_WDOG_H + +#include + +#define WDOG_STCTRLH REG_16(0x40052000) /* Watchdog Status and Control Register High */ +#define STCTRLH_DISTESTWDOG 14 /* Functional test mode disable */ +#define STCTRLH_BYTESEL 12 /* Byte test mode byte selector */ +#define STCTRLH_BYTESEL_M (uint16_t)(BITS(2) << STCTRLH_BYTESEL) +#define STCTRLH_TESTSEL 11 /* Functional test mode test selector */ +#define STCTRLH_TESTWDOG 10 /* Functional test mode enable */ +#define STCTRLH_WAITEN 7 /* Wait mode WDOG enable */ +#define STCTRLH_STOPEN 6 /* Stop mode WDOG enable */ +#define STCTRLH_DBGEN 5 /* Debug mode WDOG enable */ +#define STCTRLH_ALLOWUPDATE 4 /* Allow further updates to write-once registers */ +#define STCTRLH_WINEN 3 /* Windowing mode enable */ +#define STCTRLH_IRQRSTEN 2 /* Debug breadcrumbs feature enable */ +#define STCTRLH_CLKSRC 1 /* Clock source selector */ +#define STCTRLH_WDOGEN 0 /* WDOG enable */ + +#define WDOG_STCTRLL REG_16(0x40052002) /* Watchdog Status and Control Register Low */ +#define WDOG_TOVALH REG_16(0x40052004) /* Watchdog Time-out Value Register High */ +#define WDOG_TOVALL REG_16(0x40052006) /* Watchdog Time-out Value Register Low */ +#define WDOG_WINH REG_16(0x40052008) /* Watchdog Window Register High */ +#define WDOG_WINL REG_16(0x4005200A) /* Watchdog Window Register Low */ +#define WDOG_REFRESH REG_16(0x4005200C) /* Watchdog Refresh register */ + +#define WDOG_UNLOCK REG_16(0x4005200E) /* Watchdog Unlock Register */ +#define WDOG_UNLOCK_S1 0xC520 /* Unlock Sequence 1/2 */ +#define WDOG_UNLOCK_S2 0xD928 /* Unlock Sequence 2/2 */ + +#define WDOG_TMROUTH REG_16(0x40052010) /* Watchdog Timer Output Register High */ +#define WDOG_TMROUTL REG_16(0x40052012) /* Watchdog Timer Output Register Low */ +#define WDOG_RSTCNT REG_16(0x40052014) /* Watchdog Reset Count register */ +#define WDOG_PRESC REG_16(0x40052016) /* Watchdog Prescaler register */ + +#endif /* LIB_REG_WDOG_H */ diff --git a/lib/string.c b/lib/string.c new file mode 100644 index 0000000..25935b3 --- /dev/null +++ b/lib/string.c @@ -0,0 +1,38 @@ +#include +#include + +void *memcpy(void * restrict _dest, const void * restrict _src, size_t n) +{ + unsigned char *dest = _dest; + const unsigned char *src = _src; + + for (size_t i = 0; i < n; i++) + dest[i] = src[i]; + + return dest; +} + +void *memmove(void *_dest, const void *_src, size_t n) +{ + unsigned char *dest = _dest; + const unsigned char *src = _src; + + if (_src < _dest) { + for (size_t i = 0; i < n; i++) + dest[i] = src[i]; + } else { + for (size_t i = n; i > 0; i++) + dest[i - 1] = src[i - 1]; + } + + return dest; +} + +void *memset(void *_s, int _c, size_t n) +{ + unsigned char *s = _s, c = (unsigned char)_c; + for (size_t i = 0; i < n; i++) + s[i] = c; + + return _s; +} diff --git a/lib/string.h b/lib/string.h new file mode 100644 index 0000000..9c204dd --- /dev/null +++ b/lib/string.h @@ -0,0 +1,10 @@ +#ifndef LIB_STRING_H +#define LIB_STRING_H + +#include + +void *memcpy(void * restrict dest, const void * restrict src, size_t n); +void *memmove(void *dest, const void *src, size_t n); +void *memset(void *s, int c, size_t n); + +#endif /* LIB_STRING_H */ diff --git a/setup.c b/setup.c new file mode 100644 index 0000000..ad29e40 --- /dev/null +++ b/setup.c @@ -0,0 +1,90 @@ +#include +#include +#include + +#include "asm.h" +#include "usb/usb.h" + +extern char _sflashdata[], _sdata[], _edata[]; +extern char _sbss[], _ebss[]; + +#define RANGE0_VAL 2 /* Very High Frequency */ +#define HGO0_VAL 0 /* High Gain Mode Disabled */ +#define FRDIV_VAL 4 /* Divide 16 MHz by 512 to produce 31.25 kHz FLL Reference */ +#define PRDIV0_VAL 7 /* Divide 16 MHz by 8 to produce 2 MHz PLL Reference */ +#define VDIV0_VAL 12 /* Multiply 2 MHz by 36 to produce 72 MHz resulting clock */ + +/* Option 2 Clock Configuration */ +#define OUTDIV1_VAL 0 /* 72 MHz / 1 = 72 MHz Core / system clocks */ +#define OUTDIV2_VAL 1 /* 72 MHz / 2 = 36 MHz Bus clock */ +#define OUTDIV4_VAL 2 /* 72 MHz / 3 = 24 MHz Flash clock */ + +void setup(void); +void setup(void) +{ + /* Disable interrupts for setup */ + CLI(); + + /* Disable Watchdog Timer */ + WDOG_UNLOCK = WDOG_UNLOCK_S1; + WDOG_UNLOCK = WDOG_UNLOCK_S2; + UNSET_BIT(WDOG_STCTRLH, STCTRLH_WDOGEN); + + /* Copy data and clear bss */ + memcpy(_sdata, _sflashdata, _edata - _sdata); + memset(_sbss, 0, _ebss - _sdata); + + /* Enable port clocks */ + SIM_SCGC5 |= BV(SCGC5_PORTE) | BV(SCGC5_PORTD) | BV(SCGC5_PORTC) + | BV(SCGC5_PORTB) | BV(SCGC5_PORTA); + + /* Change Clock Dividers */ + SIM_CLKDIV1 = OUTDIV1_VAL << CLKDIV1_OUTDIV1 + | OUTDIV2_VAL << CLKDIV1_OUTDIV2 + | OUTDIV4_VAL << CLKDIV1_OUTDIV4; + + /* Clear latched peripherals and I/O */ + if (IS_BIT_SET(PMC_REGSC, REGSC_ACKISO)) + SET_BIT(PMC_REGSC, REGSC_ACKISO); + + /* + * CLOCKING SETUP + */ + + /* FEI to FBE */ + SET_MASKED(MCG_C2, C2_RANGE0_M | BV(C2_HGO0) | BV(C2_EREFS0), + RANGE0_VAL << C2_RANGE0 | BV(C2_EREFS0)); + + SET_MASKED(MCG_C1, C1_CLKS_M | C1_FRDIV_M | BV(C1_IREFS), + 2 << C1_CLKS | FRDIV_VAL << C1_FRDIV); + + WAIT_BIT_SET(MCG_S, S_OSCINIT0); + WAIT_BIT_UNSET(MCG_S, S_IREFST); + do { } while (GET_BITS(MCG_S, S_CLKST) != 2); + + /* Enable Clock Monitor */ + SET_BIT(MCG_C6, C6_CME0); + + + /* FBE to PBE */ + SET_MASKED(MCG_C5, C5_PRDIV0_M, PRDIV0_VAL << C5_PRDIV0); + SET_MASKED(MCG_C6, BV(C6_PLLS) | C6_VDIV0_M, BV(C6_PLLS) | VDIV0_VAL << C6_VDIV0); + + WAIT_BIT_SET(MCG_S, S_PLLST); + WAIT_BIT_SET(MCG_S, S_LOCK0); + + /* PBE to PEE */ + SET_MASKED(MCG_C1, C1_CLKS_M, 0); + + do { } while (GET_BITS(MCG_S, S_CLKST) != 3); + + /* Set PLL as the clock to use for things which can take PLL or FLL */ + SET_BIT(SIM_SOPT2, SOPT2_PLLFLLSEL); + SET_MASKED(SIM_SOPT2, SOPT2_CLKOUTSEL_M, 4 << SOPT2_CLKOUTSEL); + + + usb_setup(); + + /* Enable interrupts for setup */ + STI(); +} diff --git a/uart/uart.c b/uart/uart.c new file mode 100644 index 0000000..031cf74 --- /dev/null +++ b/uart/uart.c @@ -0,0 +1,5 @@ +#include "uart.h" + +void uart_setup(void) +{ +} diff --git a/uart/uart.h b/uart/uart.h new file mode 100644 index 0000000..984d704 --- /dev/null +++ b/uart/uart.h @@ -0,0 +1,6 @@ +#ifndef UART_UART_H +#define UART_UART_H + +void uart_setup(void); + +#endif /* UART_UART_H */ diff --git a/usb/bdt.h b/usb/bdt.h new file mode 100644 index 0000000..5f0a123 --- /dev/null +++ b/usb/bdt.h @@ -0,0 +1,14 @@ +#ifndef USB_BDT_H +#define USB_BDT_H + +#include + +extern struct usb0_bd usb_bdt[4 * 16]; + +#define BDT_ENDPT(n, tx, odd) (usb_bdt[(n) << 2 | (tx & 1) << 1 | (odd & 1)]) +#define BDT_RX 0 +#define BDT_TX 1 +#define BDT_EVEN 0 +#define BDT_ODD 1 + +#endif /* USB_BDT_H */ diff --git a/usb/ds_conf.xxd b/usb/ds_conf.xxd new file mode 100644 index 0000000..89c6e16 --- /dev/null +++ b/usb/ds_conf.xxd @@ -0,0 +1,34 @@ +09 1 Length - 9 +02 1 Descriptor Type - 2 (Configuration) +22 2 Total Length - 32 +00 +01 1 Number of Interfaces - 1 +01 1 Configuration Value - 1 +00 1 Configuration String - 0 +c0 1 Attributes - none +32 1 Maximum Current - 100mA +09 1 Length - 9 +04 1 Descriptor Type - 4 (Interface) +00 1 Interface Number - 0 +00 1 Alternate Setting - 0 +01 1 Number of Endpoints - 1 +03 1 Interface Class - 3 (HID) +01 1 Interface Sub Class - 1 (Boot) +02 1 Interface Protocol - 1 (Keyboard) +00 1 Interface String - 0 +09 1 Length (HID Descriptor) - 9 +21 1 Descriptor Type - 33 (HID) +11 2 HID Class Spec Version - 1.1 +01 +00 1 Country Code - N/A +01 1 Number of Descriptors - 1 +22 1 Descriptor Type - 34 (REPORT) +34 2 Descriptor Length - 52 +00 +07 1 Length - 7 +05 1 Descriptor Type - 5 (Endpoint) +81 1 Endpoint Address - 1 IN +03 1 Attributes - Interrupt; Data Endpoint +08 2 Maximum packet size - 8 +00 +40 1 Interval - 60 Frames diff --git a/usb/ds_dev.xxd b/usb/ds_dev.xxd new file mode 100644 index 0000000..306da63 --- /dev/null +++ b/usb/ds_dev.xxd @@ -0,0 +1,18 @@ +12 1 Length - 18 +01 1 Descriptor type - 1 +00 2 USB Release - 2.0 +02 +ff 1 Device Class - Interface Specific +00 1 Device Sub Class - Interface Specific +00 1 Device Protocol - Interface Specific +40 1 Max Packet Size - 64 +c0 2 VID (0x16c0) +16 +dc 2 PID (0x047c) +05 +01 2 Device Release BCD - 0.01 +00 +01 1 Manufacturer String - 1 +00 1 Product String - 0 +00 1 Serial Number String - 0 +01 1 Number of Configurations - 1 diff --git a/usb/ds_lang.xxd b/usb/ds_lang.xxd new file mode 100644 index 0000000..e6e334c --- /dev/null +++ b/usb/ds_lang.xxd @@ -0,0 +1,4 @@ +04 1 Length - 4 +03 1 Type - 3 (Language) +09 2 LANGID - EN US +04 diff --git a/usb/ds_str1.xxd b/usb/ds_str1.xxd new file mode 100644 index 0000000..1aea777 --- /dev/null +++ b/usb/ds_str1.xxd @@ -0,0 +1,22 @@ +16 1 Length - 22 +03 1 Type - 3 (String) +74 20 - the-tk.com +00 +68 +00 +65 +00 +2d +00 +74 +00 +6b +00 +2e +00 +63 +00 +6f +00 +6d +00 diff --git a/usb/endpt0.c b/usb/endpt0.c new file mode 100644 index 0000000..a60e1a4 --- /dev/null +++ b/usb/endpt0.c @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include + +#include + +#include "bdt.h" +#include "endpt0.h" + +#include "ds_conf.xxh" +#include "ds_dev.xxh" +#include "ds_lang.xxh" +#include "ds_str1.xxh" + +#define MAX_PACKET 64 +static unsigned char buf[2][MAX_PACKET]; +static bool odd; +static bool data01; + +static volatile unsigned int nextaddr; + +static const void *tx_data; +static size_t tx_size; + +struct tok_setup { + uint8_t reqtyp; + uint8_t req; + uint16_t value; + uint16_t index; + uint16_t length; +}; + +/* read_setup: parse a SETUP token's data */ +static void read_setup(struct tok_setup *setup, const void *_data) +{ + const unsigned char *data = _data; + + setup->reqtyp = data[0]; + setup->req = data[1]; + setup->value = le16toh(&data[2]); + setup->index = le16toh(&data[4]); + setup->length = le16toh(&data[6]); +} + +/* TODO: Make this a shared thing across all USB endpoints */ + +/* puttx: place data in the current buffer descriptor */ +static bool puttx(const void *data, size_t size) +{ + if (GET_BIT(BDT_ENDPT(0, BDT_TX, odd).desc, BD_OWN)) + return false; + + BDT_ENDPT(0, BDT_TX, odd).addr = (void *)data; + BDT_ENDPT(0, BDT_TX, odd).desc = USB0_BD_INIT(size, data01); + odd = !odd; + data01 = !data01; + + return true; +} + +/* pushtx: attempt to push rest of the current transmission into a BD */ +static bool pushtx(void) +{ + size_t size = tx_size; + + if (tx_data == NULL) + return false; + + if (size > MAX_PACKET) + size = MAX_PACKET; + + if (!puttx(tx_data, size)) + return false; + + tx_data = (const char *)tx_data + size; + tx_size -= size; + + if (tx_size == 0 && size < MAX_PACKET) + tx_data = NULL; + + return true; +} + +/* quetx: enqueue a transmission */ +static void quetx(const void *data, size_t size) +{ + tx_data = data; + tx_size = size; + + while (pushtx()) + ; +} + +/* usb_endpt0_disable: Disable endpoint 0 (not valid) */ +void usb_endpt0_disable(void) +{ +} + +/* usb_endpt0_enable: Enable and reset endpoint 0 */ +void usb_endpt0_enable(void) +{ + BDT_ENDPT(0, BDT_RX, BDT_EVEN).addr = buf[0]; + BDT_ENDPT(0, BDT_RX, BDT_EVEN).desc = USB0_BD_INIT(sizeof buf[0], 0); + + BDT_ENDPT(0, BDT_RX, BDT_ODD).addr = buf[1]; + BDT_ENDPT(0, BDT_RX, BDT_ODD).desc = USB0_BD_INIT(sizeof buf[1], 0); + + BDT_ENDPT(0, BDT_TX, BDT_EVEN).addr = NULL; + BDT_ENDPT(0, BDT_TX, BDT_EVEN).desc = 0; + + BDT_ENDPT(0, BDT_TX, BDT_ODD).addr = NULL; + BDT_ENDPT(0, BDT_TX, BDT_ODD).desc = 0; + + USB0_ENDPT(0) = BV(ENDPT_EPRXEN) | BV(ENDPT_EPTXEN) | BV(ENDPT_EPHSHK); + nextaddr = 0; + tx_data = NULL; + odd = 0; + data01 = 0; +} + +/* trunc: truncate size_t to a limit TODO: MOVE THIS */ +static inline size_t trunc(size_t val, size_t max) +{ + if (val > max) + return max; + return val; +} + +/* tok_setup: process a setup token */ +static void tok_setup(struct tok_setup *setup) +{ + switch (setup->reqtyp << 8 | setup->req) { + case 0x0005: /* SET ADDRESS */ + nextaddr = setup->value; + puttx(NULL, 0); + break; + case 0x0009: /* SET CONFIGURATION */ + puttx(NULL, 0); + break; + case 0x8006: /* GET DESCRIPTOR */ + switch (setup->value) { + case 0x0100: /* DEVICE */ + quetx(usb_ds_dev, trunc(usb_ds_dev_len, setup->length)); + return; + case 0x0200: /* CONFIGURATION */ + quetx(usb_ds_conf, trunc(usb_ds_conf_len, setup->length)); + return; + case 0x0300: /* STRING 0 */ + quetx(usb_ds_lang, trunc(usb_ds_lang_len, setup->length)); + return; + case 0x0301: /* STRING 1 */ + quetx(usb_ds_str1, trunc(usb_ds_str1_len, setup->length)); + return; + } + /* fall through */ + default: + SET_BIT(USB0_ENDPT(0), ENDPT_EPSTALL); + break; + } +} + +void usb_endpt0_token(uint8_t state) +{ + struct usb0_bd *bd; + struct tok_setup setup; + + bd = &BDT_ENDPT(0, GET_BIT(state, STAT_TX), GET_BIT(state, STAT_ODD)); + + + switch (GET_BITS(bd->desc, BD_TOK_PID)) { + case BD_TOK_PID_OUT: + bd->desc = USB0_BD_INIT(sizeof buf[0], 1); + break; + case BD_TOK_PID_IN: + pushtx(); + if (nextaddr) { + USB0_ADDR = nextaddr; + nextaddr = 0; + } + break; + case BD_TOK_PID_SETUP: + read_setup(&setup, bd->addr); + bd->desc = USB0_BD_INIT(sizeof buf[0], 1); + + BDT_ENDPT(0, BDT_TX, BDT_EVEN).desc = 0; + BDT_ENDPT(0, BDT_TX, BDT_ODD).desc = 0; + tx_data = NULL; + + data01 = 1; + + tok_setup(&setup); + + break; + } + + USB0_CTL = BV(CTL_USBENSOFEN); +} diff --git a/usb/endpt0.h b/usb/endpt0.h new file mode 100644 index 0000000..4ba89ed --- /dev/null +++ b/usb/endpt0.h @@ -0,0 +1,10 @@ +#ifndef USB_ENDPT0_H +#define USB_ENDPT0_H + +#include + +void usb_endpt0_disable(void); +void usb_endpt0_enable(void); +void usb_endpt0_token(uint8_t state); + +#endif /* USB_ENDPT0_H */ diff --git a/usb/endpt1.c b/usb/endpt1.c new file mode 100644 index 0000000..b29c3bb --- /dev/null +++ b/usb/endpt1.c @@ -0,0 +1,36 @@ +#include +#include + +#include "bdt.h" +#include "endpt1.h" + +#define MAX_PACKET 64 + +static unsigned char buf[2][MAX_PACKET]; + +void usb_endpt1_enable(void) +{ +} + +void usb_endpt1_disable(void) +{ +} + +void usb_endpt1_token(uint8_t state) +{ + struct usb0_bd *bd; + + bd = &BDT_ENDPT(1, GET_BIT(state, STAT_TX), GET_BIT(state, STAT_ODD)); + + switch (GET_BITS(bd->desc, BD_TOK_PID)) { + case BD_TOK_PID_OUT: + bd->desc = USB0_BD_INIT(sizeof buf[0], 1); + /* should never happen */ + break; + case BD_TOK_PID_IN: + /*pushtx();*/ + break; + } + + /*USB0_CTL = BV(CTL_USBENSOFEN);*/ +} diff --git a/usb/endpt1.h b/usb/endpt1.h new file mode 100644 index 0000000..9be7522 --- /dev/null +++ b/usb/endpt1.h @@ -0,0 +1,8 @@ +#ifndef USB_ENDPT1_H +#define USB_ENDPT1_H + +void usb_endpt1_enable(void); +void usb_endpt1_disable(void); +void usb_endpt1_token(uint8_t state); + +#endif /* USB_ENDPT1_H */ diff --git a/usb/usb.c b/usb/usb.c new file mode 100644 index 0000000..ebd3179 --- /dev/null +++ b/usb/usb.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include + +#include "usb.h" +#include "bdt.h" +#include "endpt0.h" +#include "endpt1.h" + +#define USBFRAC_VAL 1 /* 72 MHz * 2 = 144 MHz (Top of Fraction) */ +#define USBDIV_VAL 2 /* 144 MHz / 3 = 48 MHz (Bottom of Fraction) */ + +/* TODO: Move this to lib somewhere */ +#define CLRPEND(n) REG_32(0xE000E280 + 4 * (n)) +#define ISR_CLRPEND(i) CLRPEND((i) / 32) = BV((i) % 32); + +#define SETENA(n) REG_32(0xE000E100 + 4 * (n)) +#define ISR_SETENA(i) SETENA((i) / 32) = BV((i) % 32); + + +__attribute__ ((aligned(512))) +struct usb0_bd usb_bdt[16 * 4]; /* TODO: Only use the number of endpoints that are needed */ + +/* usb_setup: Setup function for USB subsystem */ +void usb_setup(void) +{ + /* Clock Setup */ + SET_BIT(SIM_SOPT2, SOPT2_USBSRC); + SET_MASKED(SIM_CLKDIV2, CLKDIV2_USBDIV_M | BV(CLKDIV2_USBFRAC), + USBDIV_VAL << CLKDIV2_USBDIV | USBFRAC_VAL << CLKDIV2_USBFRAC); + SET_BIT(SIM_SCGC4, SCGC4_USBOTG); + + /* Reset USB and wait more than 2 USB clock cycles */ + SET_BIT(USB0_USBTRC0, USBTRC0_USBRESET); + for (int i = 0; i < 5; i++) + ; + + /* 512 bit aligned BDT address */ + USB0_BDTPAGE1 = (uintptr_t)usb_bdt >> 8 & 0xff; + USB0_BDTPAGE2 = (uintptr_t)usb_bdt >> 16 & 0xff; + USB0_BDTPAGE3 = (uintptr_t)usb_bdt >> 24 & 0xff; + + /* Initial Configuration */ + SET_MASKED(USB0_USBCTRL, BV(USBCTRL_SUSP) | BV(USBCTRL_PDE), 0); + SET_BIT(USB0_CONTROL, CONTROL_DPPULLUPNONOTG); + SET_BIT(USB0_INTEN, INTEN_USBRSTEN); + + /* NVIC Enable interrupt */ + ISR_CLRPEND(73); + ISR_SETENA(73); + + /* Enable USB */ + USB0_CTL = BV(CTL_USBENSOFEN); +} + +/* i_usbrst: Handler for USBRST USB interrupt */ +static void i_usbrst(void) +{ + SET_BIT(USB0_CTL, CTL_ODDRST); + + usb_endpt0_enable(); + usb_endpt1_disable(); + + USB0_ADDR = 0; + + SET_BIT(USB0_INTEN, INTEN_TOKDNEEN); +} + +/* i_tokdne: Handler for TOKDNE USB interrupt */ +static void i_tokdne(void) +{ + uint8_t stat = USB0_STAT; + + switch (GET_BITS(stat, STAT_ENDP)) { + case 0: usb_endpt0_token(stat); break; + case 1: usb_endpt1_token(stat); break; + } +} + +/* usb_isr: interrupt service routine for the USB FS SIE */ +void usb_isr(void) +{ + uint8_t stat = USB0_ISTAT; + + if (IS_BIT_SET(stat, ISTAT_TOKDNE)) { + i_tokdne(); + USB0_ISTAT = BV(ISTAT_TOKDNE); + } + if (IS_BIT_SET(stat, ISTAT_USBRST)) { + i_usbrst(); + USB0_ISTAT = BV(ISTAT_USBRST); + } +} diff --git a/usb/usb.h b/usb/usb.h new file mode 100644 index 0000000..64d0585 --- /dev/null +++ b/usb/usb.h @@ -0,0 +1,7 @@ +#ifndef USB_H +#define USB_H + +void usb_setup(void); +void usb_isr(void); + +#endif /* USB_H */ diff --git a/vectors.s b/vectors.s new file mode 100644 index 0000000..1981eb5 --- /dev/null +++ b/vectors.s @@ -0,0 +1,98 @@ +.syntax unified + +.section ".vectors" +// ARM Core System Handler Vectors +.long _estack // 0 ARM: Initial Stack Pointer +.long _start // 1 ARM: Initial Program Counter +.long _halt // 2 ARM: Non-maskable Interrupt (NMI) +.long _halt // 3 ARM: Hard Fault +.long _halt // 4 ARM: MemManage Fault +.long _halt // 5 ARM: Bus Fault +.long _halt // 6 ARM: Usage Fault +.fill 4,4,0 // 7..10 +.long 0 // 11 ARM: Supervisor call (SVCall) +.long 0 // 12 ARM: Debug Monitor +.long 0 // 13 - +.long 0 // 14 ARM: Pendable request for system service (PendableSrvReq) +.long 0 // 15 ARM: System tick timer (SysTick) + +// Non-Core Vectors +.long 0 // 16 DMA: DMA channel 0 transfer complete +.long 0 // 17 DMA: DMA channel 1 transfer complete +.long 0 // 18 DMA: DMA channel 2 transfer complete +.long 0 // 19 DMA: DMA channel 3 transfer complete +.long 0 // 20 DMA: DMA channel 4 transfer complete +.long 0 // 21 DMA: DMA channel 5 transfer complete +.long 0 // 22 DMA: DMA channel 6 transfer complete +.long 0 // 23 DMA: DMA channel 7 transfer complete +.long 0 // 24 DMA: DMA channel 8 transfer complete +.long 0 // 25 DMA: DMA channel 9 transfer complete +.long 0 // 26 DMA: DMA channel 10 transfer complete +.long 0 // 27 DMA: DMA channel 11 transfer complete +.long 0 // 28 DMA: DMA channel 12 transfer complete +.long 0 // 29 DMA: DMA channel 13 transfer complete +.long 0 // 30 DMA: DMA channel 14 transfer complete +.long 0 // 31 DMA: DMA channel 15 transfer complete +.long 0 // 32 DMA: DMA error interrupt channels 0-15 +.long 0 // 33 - +.long 0 // 34 Flash_memory: Command complete +.long 0 // 35 Flash_memory: Read collision +.long 0 // 36 Mode_Controller: Low-voltage detect, low-voltage warning +.long 0 // 37 LLWU: Low Leakage Wakeup +.long 0 // 38 WDOG or EWM: Both watchdog modules share this interrupt. +.long 0 // 39 - +.long 0 // 40 I2C0: - +.long 0 // 41 I2C1: - +.long 0 // 42 SPI0: Single interrupt vector for all sources +.long 0 // 43 SPI1: Single interrupt vector for all sources +.long 0 // 44 - +.long 0 // 45 CAN0: OR'ed Message buffer (0-15) +.long 0 // 46 CAN0: Bus Off +.long 0 // 47 CAN0: Error +.long 0 // 48 CAN0: Transmit Warning +.long 0 // 49 CAN0: Receive Warning +.long 0 // 50 CAN0: Wake Up Transmit +.long 0 // 51 I2S0: Transmit +.long 0 // 52 I2S0: Receive +.fill 7,4,0 // 53..59 - +.long 0 // 60 UART0: Single interrupt vector for UART LON sources +.long 0 // 61 UART0: Single interrupt vector for UART status sources +.long 0 // 62 UART0: Single interrupt vector for UART error sources +.long 0 // 63 UART1: Single interrupt vector for UART status sources +.long 0 // 64 UART1: Single interrupt vector for UART error sources +.long 0 // 65 UART2: Single interrupt vector for UART status sources +.long 0 // 66 UART2: Single interrupt vector for UART error sources +.fill 6,4,0 // 67..72 - +.long 0 // 73 ADC0: - +.long 0 // 74 ADC1: - +.long 0 // 75 CMP0: - +.long 0 // 76 CMP1: - +.long 0 // 77 CMP2: - +.long 0 // 78 FTM0: Single interrupt vector for all sources +.long 0 // 79 FTM1: Single interrupt vector for all sources +.long 0 // 80 FTM2: Single interrupt vector for all sources +.long 0 // 81 CMT: - +.long 0 // 82 RTC: Alarm interrupt +.long 0 // 83 RTC: Seconds interrupt +.long 0 // 84 PIT: Channel 0 +.long 0 // 85 PIT: Channel 1 +.long 0 // 86 PIT: Channel 2 +.long 0 // 87 PIT: Channel 3 +.long 0 // 88 PDB: - +.long usb_isr // 89 USBOTG: - +.long 0 // 90 USB_Charger_Detect: - +.fill 6,4,0 // 91..96 +.long 0 // 97 DAC0: - +.long 0 // 98 - +.long 0 // 99 TSI: Single interrupt vector for all sources +.long 0 // 100 MCG: - +.long 0 // 101 LPT: - +.long 0 // 102 - +.long 0 // 103 Port_control_module: Pin detect (Port A) +.long 0 // 104 Port_control_module: Pin detect (Port B) +.long 0 // 105 Port_control_module: Pin detect (Port C) +.long 0 // 106 Port_control_module: Pin detect (Port D) +.long 0 // 107 Port_control_module: Pin detect (Port E) +.long 0 // 108 - +.long 0 // 109 - +.long 0 // 110 Software: Software interrupt 4 -- cgit v1.2.3-54-g00ecf