diff options
author | Tomasz Kramkowski <tk@the-tk.com> | 2016-10-20 23:43:29 +0100 |
---|---|---|
committer | Tomasz Kramkowski <tk@the-tk.com> | 2016-10-20 23:43:29 +0100 |
commit | c3c5f1e5fe27574220c3e94a79048e066cacc121 (patch) | |
tree | 445096a0365cc45c959091355852c9b63d8a338a | |
download | fmk-c3c5f1e5fe27574220c3e94a79048e066cacc121.tar.gz fmk-c3c5f1e5fe27574220c3e94a79048e066cacc121.tar.xz fmk-c3c5f1e5fe27574220c3e94a79048e066cacc121.zip |
Init commit
-rw-r--r-- | .gitignore | 11 | ||||
-rw-r--r-- | Makefile | 42 | ||||
-rw-r--r-- | asm.h | 7 | ||||
-rw-r--r-- | crt0.s | 32 | ||||
-rw-r--r-- | flashconf.s | 6 | ||||
-rw-r--r-- | fmk.c | 9 | ||||
-rw-r--r-- | layout.ld | 38 | ||||
-rw-r--r-- | lib/le.c | 54 | ||||
-rw-r--r-- | lib/le.h | 12 | ||||
-rw-r--r-- | lib/reg.h | 45 | ||||
-rw-r--r-- | lib/reg/gpio.h | 41 | ||||
-rw-r--r-- | lib/reg/mcg.h | 56 | ||||
-rw-r--r-- | lib/reg/pmc.h | 27 | ||||
-rw-r--r-- | lib/reg/port.h | 42 | ||||
-rw-r--r-- | lib/reg/regdefs.h | 25 | ||||
-rw-r--r-- | lib/reg/sim.h | 70 | ||||
-rw-r--r-- | lib/reg/uart.h | 8 | ||||
-rw-r--r-- | lib/reg/usbotg.h | 202 | ||||
-rw-r--r-- | lib/reg/wdog.h | 37 | ||||
-rw-r--r-- | lib/string.c | 38 | ||||
-rw-r--r-- | lib/string.h | 10 | ||||
-rw-r--r-- | setup.c | 90 | ||||
-rw-r--r-- | uart/uart.c | 5 | ||||
-rw-r--r-- | uart/uart.h | 6 | ||||
-rw-r--r-- | usb/bdt.h | 14 | ||||
-rw-r--r-- | usb/ds_conf.xxd | 34 | ||||
-rw-r--r-- | usb/ds_dev.xxd | 18 | ||||
-rw-r--r-- | usb/ds_lang.xxd | 4 | ||||
-rw-r--r-- | usb/ds_str1.xxd | 22 | ||||
-rw-r--r-- | usb/endpt0.c | 199 | ||||
-rw-r--r-- | usb/endpt0.h | 10 | ||||
-rw-r--r-- | usb/endpt1.c | 36 | ||||
-rw-r--r-- | usb/endpt1.h | 8 | ||||
-rw-r--r-- | usb/usb.c | 94 | ||||
-rw-r--r-- | usb/usb.h | 7 | ||||
-rw-r--r-- | vectors.s | 98 |
36 files changed, 1457 insertions, 0 deletions
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 @@ -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 */ @@ -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 @@ -0,0 +1,9 @@ +#include <reg.h> +#include <stdint.h> + +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 <tk@the-tk.com> + * + * 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 <stdint.h> + +#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 <stdint.h> + +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 <reg/port.h> +#include <reg/sim.h> +//#include <reg/rcm.h> +//#include <reg/smc.h> +#include <reg/pmc.h> +//#include <reg/llwu.h> +//#include <reg/mcm.h> +//#include <reg/axbs.h> +//#include <reg/aips.h> +//#include <reg/dmamux.h> +//#include <reg/dma.h> +//#include <reg/ewm.h> +#include <reg/wdog.h> +#include <reg/mcg.h> +//#include <reg/osc.h> +//#include <reg/rtc.h> +//#include <reg/fmc.h> +//#include <reg/ftfl.h> +/*#include <reg/ezport.h>*/ +//#include <reg/crc.h> +//#include <reg/adc.h> +//#include <reg/cmp.h> +//#include <reg/dac.h> +//#include <reg/vref.h> +//#include <reg/pdb.h> +//#include <reg/ftm.h> +//#include <reg/pit.h> +//#include <reg/lptmr.h> +//#include <reg/cmt.h> +//#include <reg/rtc.h> +//#include <reg/usbotg.h> +//#include <reg/usbdcd.h> +//#include <reg/can.h> +//#include <reg/spi.h> +//#include <reg/i2c.h> +#include <reg/uart.h> +//#include <reg/i2s.h> +#include <reg/gpio.h> +//#include <reg/tsi.h> +//#include <reg/jtagc.h> + +#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 <reg/regdefs.h> + +#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 <reg/regdefs.h> + +#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 <reg/regdefs.h> + +#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 <reg/regdefs.h> + +#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 <stdint.h> + +#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 <reg/regdefs.h> + +#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 <reg/regdefs.h> + +#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 <string.h> +#include <stddef.h> + +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 <stddef.h> + +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 */ @@ -0,0 +1,90 @@ +#include <reg.h> +#include <stddef.h> +#include <string.h> + +#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 <reg/usbotg.h> + +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 <le.h> +#include <reg/usbotg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include <reg/gpio.h> + +#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 <stdint.h> + +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 <reg/usbotg.h> +#include <stdint.h> + +#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 <reg/sim.h> +#include <reg/usbotg.h> +#include <reg/gpio.h> +#include <stddef.h> + +#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 |