80 Commits
0.1 ... 0.2

Author SHA1 Message Date
Harald Welte
0de99cd069 DFU: String descriptors for DFU alt-interfaces
they are only shown in DFU mode for now, until we find a way to export
them over to the runtime.
2017-03-03 01:20:19 +01:00
Harald Welte
ac4f66e5d1 DFU: Set 10ms bwPollTimeout (lowest possible as per spec) 2017-03-03 01:13:34 +01:00
Harald Welte
91fc40240e DFU: make sure to properly initialize g_dfu pointer before using it 2017-03-03 01:05:22 +01:00
Harald Welte
b04f4f0ee8 DFU Runtime: Add missing return after handling USB standard requests
the same as 479e97e338 but this time for
the runtime, not for DFU.
2017-03-03 00:36:39 +01:00
Harald Welte
e8eea29cf6 dfu: fix cosmetic issue in debug message 2017-03-03 00:35:51 +01:00
Harald Welte
d1e963479e DFU: fix transitions between runtime and DFU mode
we now always go through a processor reset to avoid any state that might
be persistent/left-over during the switch.
2017-03-03 00:34:17 +01:00
Harald Welte
db17e83960 cstartup: (re-)enable interrupts before calling main() 2017-03-02 23:19:13 +01:00
Harald Welte
ec9b5fff3f dfu/main.c: Initialize FLASHD driver before using it 2017-03-02 23:18:40 +01:00
Harald Welte
0af4948211 cstartup / USBD: Use correct Makefile conditionals for DFU 2017-03-02 23:18:02 +01:00
Harald Welte
adbe72a5ba Makefile: Define APPLICATION_foo BOARD_bar and ENVIRONMENT_baz #defines
This can help us with conditional code
2017-03-02 23:16:01 +01:00
Harald Welte
e36970cac7 dfu: print Chip ID during boot 2017-03-02 19:24:14 +01:00
Harald Welte
cab66419d6 flashd: Set 6 Wait states as per Errata requiremens for Revision A
It is utterly unacceptable that Atmel is shipping example code in 2011,
which doesn't support parts that are shipped still in 2016.  They would
have had five years to fix their code to implement the chip errata :(
2017-03-02 19:22:50 +01:00
Harald Welte
479e97e338 DFU: Add missing 'return' after handling generic USB control request 2017-03-02 16:53:13 +01:00
Harald Welte
203abf5f6e dfu_desc: Add some string descriptors and fix configuration desc table 2017-03-02 16:52:48 +01:00
Harald Welte
ee9ebb30da stdio: Increase max string size to 512 and don't endless-loop!! 2017-03-02 16:52:08 +01:00
Harald Welte
b2ad7f76a1 dfu_des.c: Cosmetic changes, use named initializers 2017-03-01 22:15:28 +01:00
Harald Welte
0395bd15b3 move PLLB (for USB) initialization to board_lowlevel.c
This way it is present both inside the DFU loader and in the main app.
2017-02-28 01:28:56 +01:00
Harald Welte
c430ac1f2a have local stdio.h file to avoid newlib issues
... we should move to -nostdinc at some point :/
2017-02-28 01:25:12 +01:00
Harald Welte
adba0ce80b fix g_dfu access from both DFU and runtime access
We need to refer to g_dfu as a pointer from all code.  In DFU mode, it
gets assigned to the address of _g_dfu, which is placed by the linker
script at the start of RAM.  In runtime mode, the pointer is statically
defined to point at the start of RAM.  The linker script for the runtime
(dfu environment) is adjusted to save the first 32 bytes for the _g_dfu
structure.
2017-02-28 01:10:32 +01:00
Harald Welte
65cca7cccc ensure g_dfu is linked to start of RAM when building DFU loader 2017-02-28 01:10:27 +01:00
Harald Welte
db30727514 remove obsolete old linker script 2017-02-28 01:10:27 +01:00
Harald Welte
32852bc1d9 DFU: towards a more complete implementation
* we now actually route the EP0 control requests in DFU mode to the
  correct handler (weak linker symbols are tricky)
* we now actually call code to read/write data from/to RAM/FLASH
2017-02-28 01:10:23 +01:00
Harald Welte
edf9c9d322 Makefile: Optimize for size
This gets the dfu image down from 19 to 11 kBytes, with is well within
the 16kbyte limit for the DFU partition.
2017-02-27 23:24:22 +01:00
Harald Welte
37b6e41f84 move last few files from src_board / include_board 2017-02-27 23:20:38 +01:00
Harald Welte
964f509f59 remove pio_capture, we don't use it
As it registers a non-weak exception handler, it consumes memory in
every build
2017-02-27 23:14:16 +01:00
Harald Welte
96e62a4664 stdio.c: fix compiler warning 2017-02-27 23:05:15 +01:00
Harald Welte
045ea3eb7b timer.h: Fix compiler warnings about redefinition 2017-02-27 23:02:26 +01:00
Harald Welte
d09829dcc6 Remove newlib dependency, include own stdio/string/assert 2017-02-27 23:00:26 +01:00
Harald Welte
d52523185f fix some compiler warnings 2017-02-27 22:18:47 +01:00
Harald Welte
d8a003dfd7 Structure build system to build for multiple boards/apps/environments 2017-02-27 22:18:45 +01:00
Harald Welte
a1cd0f31c8 fix compilation of card_emu_tests 2017-02-27 14:29:07 +01:00
Harald Welte
3f5e3ddffc Change directory structure to align with Atmel softpack
This way we can easily check with 'diff' for differences in our code and
Atmel softpack.  Also, this layout is more suitable for building various
different firmware images (e.g. factory-test, dfu-loader, main
application) for a variety of different boards (simtrace, owhw, qmod).
2017-02-27 14:24:11 +01:00
Harald Welte
7ed6f3bc37 WIP: Introduce USB DFU code from my at91lib DFU port 2017-02-27 09:28:34 +01:00
Harald Welte
aa3b867abb WIP: split main from board-speciic parts 2017-02-26 15:59:56 +01:00
Harald Welte
a05ccc9103 build efc.o and flashd.o as part of build process 2017-02-26 15:51:10 +01:00
Harald Welte
e9eaf90d35 import efc.[ch] and flashd.[ch] from SAM3S softpack 2.1 2017-02-26 12:52:01 +01:00
Harald Welte
1d91058eee qmod: Inver initial state of PERST signals
The signals are driving an external NPN transistor, so the default state
must be low at reset to en sure that !PERST on the modem input is
de-asserted by default.
2017-02-10 19:50:24 +01:00
Harald Welte
4a9bce127f qmod: invert WWAN_PERST logic (we use transistors now) 2017-02-10 19:19:52 +01:00
Harald Welte
6732248f71 Add support for board version reading via ADC 2017-02-10 19:19:48 +01:00
Harald Welte
9c78cff10b Extend WWAN modem PERST to 300ms
It seems like a lot of modems have rather long (100ms!) minimum reset
durations.  Makes me wonder if it's an actual reset line or rather juts
some GPIO that they poll/sample every so often.  Then there are other
modems that state the reset *must not* be longer than 1s.  So let's
choose 300ms as a value in-between.
2017-02-04 14:58:49 +01:00
Harald Welte
987f59aa02 Import libosmocore timer infrastructure and use it for PERST
The PERST is thus no longer busy-waiting but starting a timer to release
the PERST after 1ms.
2017-02-04 14:58:45 +01:00
Harald Welte
b41598b602 Introudce an include_libosmocore directory and move (updated) linuxlist there 2017-02-04 12:15:58 +01:00
Harald Welte
7e5c7d5b82 Add debug commands '1' and '2' to generate 1ms reset pulses to modems 2017-02-03 22:59:04 +01:00
Harald Welte
31f817c3ac Add support for controlling PERST of WWAN modems (on qmod) 2017-02-03 22:22:20 +01:00
Harald Welte
83207e0cad Add 'mdelay()' function to busy-wait for given number of milli-seconds 2017-02-03 22:22:17 +01:00
Harald Welte
2819e9c131 wwan_led: Read + report status changes of WWAN LED inputs 2017-02-03 07:49:28 +01:00
Harald Welte
af6147997d qmod: Remove 'U' debug command and directly initialize USB
The hack to manually delay the USB initialization is no longer needed as
finally the USB enumerates.
2017-01-12 18:59:41 +01:00
Harald Welte
fb3f308f2f board_lowlevel: Clean up PLLA configuration
The PLL setting doesn't depend on the 'qmod' board type but on the
combination of the BOARD_MAINOSC and BOARD_MCK #defines.  So let's
remove the '#ifdef qmod' from the equation.

The only 'qmod' specific part is whether or not to use the internal xtal
oscillator or not.
2017-01-12 18:16:23 +01:00
Harald Welte
84ad98585c usb: Cofnigure PLLB according to board.h BOARD_MAINOSC
Actually we don't even need to use PLLB for USB and could simply use
PLLA, but then we don't c are about the extra 2.5mA
2017-01-12 18:06:57 +01:00
Harald Welte
7861132fad qmod: Don't violate PLL minimum output frequency
Table 42-31 ofd DOC6500 states that the minimum output frequency of the
PLL is 60 MHz.   The existing qmod code violated this by configuring the
PLL multiplier output to 12*4 = 48 MHz.  Let's use 12*8 = 96 and then
divide that by two to get to the desired 48 MHz.

This might help to resolve the non-working USB on the qmod so far.
2017-01-12 11:07:04 +01:00
Harald Welte
b871363be7 qmod: cosmetic changes to EEPROM hex array
* move it out of the function so it actually is present in .rodata,
  rather than having a long sequence of stores into a stack buffer
* use 16 bytes per line so it is easier to find + change bits in there
2017-01-11 23:08:35 +01:00
Harald Welte
b30783c83e qmod EEPROM: Dont't mark any ports as non-removable
.. and don't disable any ports during bus-powered operation (which we
don't support anyway).
2017-01-11 23:02:26 +01:00
Harald Welte
ae8a465f36 qmod: Commit missing changes to EEPROM
The firmware we used for testing contained some local changes which were
not committed.  They primarily relate to the port re-ordering feature as
well as the amount of power (0x32 = 100mA) is now used consequently.
2017-01-11 22:59:09 +01:00
Harald Welte
6dfcf70f63 qmod: Start with _HUB_RESET=0 -> HUB_RESET=1 (not in reset)
Booting with the hub reset active would in turn cut our own power
supply as the hub disables all downstream port power in that case.
2017-01-11 22:23:13 +01:00
Harald Welte
f9a182d24d qmod: breal the command loop when 'U' is pressed and proceed to USB init 2017-01-11 22:22:16 +01:00
Harald Welte
afbb747170 qmod: do not automatically clear _HUB_RESET after EEPROM write
we'd rather have explicit control over that
2017-01-11 22:21:28 +01:00
Harald Welte
e07aed6543 qmod: debug menu: Add 'U' command to proceed to USB 2016-12-22 22:32:15 +01:00
Harald Welte
396354cbdb qmod: debug menu: make sure to always print something 2016-12-22 22:29:57 +01:00
Harald Welte
006b16ddc2 quad-modem: Add debug console commands for debugging 2016-12-22 21:29:41 +01:00
Harald Welte
e974fbb9e5 Issue ST12_PRTPWR_OVERRIDE before putting hub in reset
When we reset the hub, the hub will actively drvie the PRTPWR signal of
the SITMRACE12 low, resulting in the SAM3 being shut off.  If we want to
"survive" this, we need to set the OVERRIDE before we go into reset.

Right now, we never release the signal again, keeping ST12 enabled
permanently, which is of course not what we want in general.
2016-10-19 19:36:07 +02:00
Harald Welte
15e026ec34 qmod: Set PIN_PRTPWR_OVERRIDE to output/low 2016-10-11 17:46:09 +02:00
Harald Welte
4e3b9a5140 qmod: attempt to swithc the DN/DP wires of the SAM3 2016-09-05 14:04:43 +02:00
Harald Welte
67415e3385 HACK: Add EEPROM writing at boot of SAM3 on qmod
This is not for production use, but just for hardware verification
2016-09-01 20:57:56 +02:00
Harald Welte
73d697d788 i2c-bitbang: increase speed to ~110kHz 2016-09-01 18:58:41 +02:00
Harald Welte
0aea9fff28 Fix reading SDA in I2C bit-banging code
We need to use pin_sda_in, not pin_sda to read the PIO Input.
2016-09-01 18:39:12 +02:00
Harald Welte
c6ae98c53a i2c_bitbang: Change logic when to use i2c_delay() 2016-09-01 11:57:09 +02:00
Harald Welte
226b40aba4 WIP: bit-banging I2C support for EEPROM access on QMOD
for now, it just continuously reads the EEPROM bytes and dumps them to
the serial console for testing.
2016-08-21 19:33:24 +02:00
Harald Welte
a02b641650 Add support for 'qmod' (quad-modem) board
You can compile the firmware for this new target using 'make
BOARD=qmod'.

The QMOD differs from simtrace+owhw in terms of low-level
initialization, as it has an external 12MHz clock at XIN, thus bypasses
the main oscillator and needs different PLL configuration.
2016-08-21 18:32:12 +02:00
Harald Welte
fd9c041ec8 fix TRACE_ENTRY line termination (LF -> CRLF) 2016-03-20 18:20:14 +01:00
Harald Welte
990f01051f Add HardFault Exception Handler
The HardFault exception handler prints the stacked register as well
as some SCB registers to help debugging even in absence of JTAG.
2016-03-20 18:19:35 +01:00
Harald Welte
e26c943fa1 exceptions: Print name of exception to console 2016-03-20 18:19:18 +01:00
Harald Welte
622b6be774 Fix ADC based VCC detection
* we need to actually return the voltage
* we need to use the correct register name for the CIDR
2016-03-20 18:19:18 +01:00
Harald Welte
3bafe43376 dynamically dispatch USART IRQs
The different modes (configurations) will have different interrupt
handlers, so we need to dispatch them via config_func_ptrs
2016-03-20 18:19:12 +01:00
Harald Welte
dde112e71c print instance/channel number in all trace messages
When debugging issues related to two concurrent SIM card emulations,
it is vital to know to which USART a message relates.
2016-03-20 16:42:11 +01:00
Harald Welte
8ee15dbc2a read SAM3S unique serial number at start and print it 2016-03-20 16:00:39 +01:00
Harald Welte
28772ebcdc ADC: Make errata work-arounds depend on run-time detection of chip version 2016-03-20 15:44:52 +01:00
Harald Welte
1871c25b6d simtrace2-remsim: Instruct SAM3S to simulate card removal on SIGINT
When stopping the program, we inform the card simulator to indicate
a card removal to the GSM phone/modem.
2016-03-20 15:30:46 +01:00
Harald Welte
cf1c19abe0 src_simtrace/main: debug/trace logging improvements 2016-03-20 15:18:18 +01:00
Harald Welte
04e37a8481 firmware/main: Disable the rotor unless TRACE_DEBUG 2016-03-20 15:18:03 +01:00
Harald Welte
5541e8a819 USBD_HAL: Hard-code TRACE_LEVEL_WARNING
we don't want to have USB related messages mess up our console
2016-03-20 15:13:47 +01:00
129 changed files with 7241 additions and 859 deletions

10
.gitignore vendored
View File

@@ -7,11 +7,15 @@ cscope.out
*/__pycache__ */__pycache__
*.E *.E
*.pyc *.pyc
sam3s_example/mains/zwizwa_ccid.c
Baselibc
venv
tags tags
*.hobj *.hobj
*.o *.o
*.a
*.lst
*.map
*.elf
*.size
*.bin
*.p
host/simtrace2-remsim host/simtrace2-remsim
host/simtrace2-remsim-usb2udp host/simtrace2-remsim-usb2udp

View File

@@ -34,49 +34,34 @@
# Chip & board used for compilation # Chip & board used for compilation
# (can be overriden by adding CHIP=chip and BOARD=board to the command-line) # (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
CHIP = sam3s2 CHIP ?= sam3s4
BOARD = simtrace BOARD ?= qmod
# Defines which are the available memory targets for the SAM3S-EK board. # Defines which are the available memory targets for the SAM3S-EK board.
MEMORIES = flash MEMORIES ?= flash dfu
# Trace level used for compilation
# (can be overriden by adding TRACE_LEVEL=#number to the command-line)
# TRACE_LEVEL_DEBUG 5
# TRACE_LEVEL_INFO 4
# TRACE_LEVEL_WARNING 3
# TRACE_LEVEL_ERROR 2
# TRACE_LEVEL_FATAL 1
# TRACE_LEVEL_NO_TRACE 0
TRACE_LEVEL = 4
#FIXME: Remove this variable
NOAUTOCALLBACK=no
DEBUG_PHONE_SNIFF=0
#CFLAGS+=-DUSB_NO_DEBUG=1
# Optimization level, put in comment for debugging
OPTIMIZATION = -O0
# Output file basename # Output file basename
OUTPUT = project APP ?= dfu
# Output directories # Output directories
OUTPUT = $(BOARD)-$(APP)
BIN = bin BIN = bin
OBJ = obj OBJ = obj/$(BOARD)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Tools # Tools
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
AT91LIB_USB_COMMON_CORE_PATH = atmel_softpack_libraries/usb/common/core AT91LIB = ./atmel_softpack_libraries
AT91LIB_USB_CORE_PATH = atmel_softpack_libraries/usb/device/core
AT91LIB_USB_COMMON_CORE_PATH = $(AT91LIB)/usb/common/core
AT91LIB_USB_CORE_PATH = $(AT91LIB)/usb/device/core
AT91LIB_USB_DFU_PATH = $(AT91LIB)/usb/device/dfu
# Tool suffix when cross-compiling # Tool suffix when cross-compiling
CROSS_COMPILE = arm-none-eabi- CROSS_COMPILE = arm-none-eabi-
LIBS = -Wl,--start-group -lgcc -lc -Wl,--end-group LIBS = -Wl,--start-group -lgcc -Wl,--end-group -nostdlib
# Compilation tools # Compilation tools
CC = $(CROSS_COMPILE)gcc CC = $(CROSS_COMPILE)gcc
@@ -90,17 +75,70 @@ NM = $(CROSS_COMPILE)nm
TOP=.. TOP=..
GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarvers) GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarvers)
#-------------------------------------------------------------------------------
# Files
#-------------------------------------------------------------------------------
# Directories where source files can be found
USB_PATHS = $(AT91LIB_USB_CORE_PATH) $(AT91LIB_USB_DFU_PATH) $(AT91LIB_USB_COMMON_CORE_PATH)
VPATH += $(USB_PATHS)
VPATH += $(AT91LIB)/libchip_sam3s/source/ $(AT91LIB)/libchip_sam3s/cmsis
VPATH += libboard/common/source libboard/$(BOARD)/source
VPATH += libcommon/source
VPATH += libosmocore/source
VPATH += apps/$(APP)
# Objects built from C source files
C_OSMOCORE = $(notdir $(wildcard libosmocore/source/*.c))
C_LIBCHIP = $(notdir $(wildcard $(AT91LIB)/libchip_sam3s/source/*.c) $(wildcard $(AT91LIB)/libchip_sam3s/cmsis/*.c))
C_LIBUSB = USBDescriptors.c USBRequests.c USBD.c USBDCallbacks.c USBDDriver.c USBDDriverCallbacks.c
C_LIBUSB_RT = dfu.c dfu_desc.c dfu_runtime.c
C_LIBUSB_DFU = dfu.c dfu_desc.c dfu_driver.c
C_LIBCOMMON = string.c stdio.c fputs.c req_ctx.c ringbuffer.c
C_BOARD = $(notdir $(wildcard libboard/common/source/*.c))
C_BOARD += $(notdir $(wildcard libboard/$(BOARD)/source/*.c))
C_APPLEVEL = $(notdir $(wildcard apps/$(APP)/*.c))
C_FILES = $(C_OSMOCORE) $(C_LIBCHIP) $(C_LIBUSB) $(C_LIBCOMMON) $(C_BOARD) $(C_APPLEVEL)
-include apps/$(APP)/Makefile
C_OBJECTS = $(C_FILES:%.c=%.o)
# Trace level used for compilation
# (can be overriden by adding TRACE_LEVEL=#number to the command-line)
# TRACE_LEVEL_DEBUG 5
# TRACE_LEVEL_INFO 4
# TRACE_LEVEL_WARNING 3
# TRACE_LEVEL_ERROR 2
# TRACE_LEVEL_FATAL 1
# TRACE_LEVEL_NO_TRACE 0
TRACE_LEVEL ?= 4
DEBUG_PHONE_SNIFF?=0
#CFLAGS+=-DUSB_NO_DEBUG=1
# Optimization level, put in comment for debugging
OPTIMIZATION ?= -Os
# Flags # Flags
INCLUDES_USB = -Iatmel_softpack_libraries/usb/include INCLUDES_USB = -I$(AT91LIB)/usb/include -I$(AT91LIB)
INCLUDES = -Iinclude_board -Iinclude_sam3s -Iinclude -Isrc_simtrace INCLUDES = $(INCLUDES_USB)
INCLUDES += -I$(AT91LIB)/libchip_sam3s -I$(AT91LIB)/libchip_sam3s/include
# FIXME: This must be made configurable! INCLUDES += -I$(AT91LIB)/libchip_sam3s/cmsis
#INCLUDES += -Iinclude_board/simtrace INCLUDES += -Ilibboard/common/include -Ilibboard/$(BOARD)/include
INCLUDES += -Iinclude_board/owhw INCLUDES += -Ilibcommon/include
INCLUDES += -Ilibosmocore/include
INCLUDES += -Icmsis INCLUDES += -Isrc_simtrace -Iinclude
INCLUDES += $(INCLUDES_USB)
CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wimplicit-int #-Wformat=2 CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wimplicit-int #-Wformat=2
CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses
@@ -120,9 +158,6 @@ CFLAGS += -Wmissing-noreturn
CFLAGS += -Wno-unused-but-set-variable -Wno-unused-variable CFLAGS += -Wno-unused-but-set-variable -Wno-unused-variable
CFLAGS += -Wno-suggest-attribute=noreturn CFLAGS += -Wno-suggest-attribute=noreturn
# To reduce application size use only integer printf function.
CFLAGS += -Dprintf=iprintf
# -mlong-calls -Wall # -mlong-calls -Wall
#CFLAGS += -save-temps -fverbose-asm #CFLAGS += -save-temps -fverbose-asm
#CFLAGS += -Wa,-a,-ad #CFLAGS += -Wa,-a,-ad
@@ -130,27 +165,12 @@ CFLAGS += -D__ARM
CFLAGS += --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb # -mfix-cortex-m3-ldrd CFLAGS += --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb # -mfix-cortex-m3-ldrd
CFLAGS += -ffunction-sections -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_LEVEL=$(TRACE_LEVEL) -DDEBUG_PHONE_SNIFF=$(DEBUG_PHONE_SNIFF) CFLAGS += -ffunction-sections -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_LEVEL=$(TRACE_LEVEL) -DDEBUG_PHONE_SNIFF=$(DEBUG_PHONE_SNIFF)
CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
CFLAGS += -DBOARD=\"$(BOARD)\" -DBOARD_$(BOARD)
CFLAGS += -DAPPLICATION=\"$(APP)\" -DAPPLICATION_$(APP)
ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -D__ASSEMBLY__ ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -D__ASSEMBLY__
LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=ResetException -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols $(LIB) LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=ResetException -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols $(LIB)
#LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats #LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats
#-------------------------------------------------------------------------------
# Files
#-------------------------------------------------------------------------------
# Directories where source files can be found
USB_PATHS = $(AT91LIB_USB_CORE_PATH) $(AT91LIB_USB_COMMON_CORE_PATH)
VPATH += src_board src_sam3s cmsis $(USB_PATHS) src_simtrace
# Objects built from C source files
C_CMSIS = core_cm3.o
C_LOWLEVEL = board_cstartup_gnu.o board_lowlevel.o syscalls.o exceptions.o
C_LIBLEVEL = spi.o pio.o pmc.o usart.o pio_it.o pio_capture.o uart_console.o iso7816_4.o wdt.o led.o tc.o
C_CCID = cciddriver.o USBD.o USBDDriver.o USBD_HAL.o USBRequests.o USBDCallbacks.o USBDescriptors.o USBDDriverCallbacks.o
C_SIMTRACE = simtrace_iso7816.o usb.o ccid.o sniffer.o mitm.o ringbuffer.o host_communication.o iso7816_fidi.o tc_etu.o req_ctx.o card_emu.o mode_cardemu.o
C_APPLEVEL = main.o
C_OBJECTS = $(C_CMSIS) $(C_LOWLEVEL) $(C_LIBLEVEL) $(C_APPLEVEL) $(C_CCID) $(C_SIMTRACE)
# Append OBJ and BIN directories to output filename # Append OBJ and BIN directories to output filename
OUTPUT := $(BIN)/$(OUTPUT) OUTPUT := $(BIN)/$(OUTPUT)
@@ -169,18 +189,18 @@ C_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(C_OBJECTS))
ASM_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(ASM_OBJECTS)) ASM_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(ASM_OBJECTS))
$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1)) $(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1))
@$(CC) $(LDFLAGS) $(LD_OPTIONAL) -T"$$@.ld" -Wl,-Map,$(OUTPUT)-$$@.map -o $(OUTPUT)-$$@.elf $$^ $(LIBS) @$(CC) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/$$@.ld" -Wl,-Map,$(OUTPUT)-$$@.map -o $(OUTPUT)-$$@.elf $$^ $(LIBS)
@$(NM) $(OUTPUT)-$$@.elf >$(OUTPUT)-$$@.elf.txt @$(NM) $(OUTPUT)-$$@.elf >$(OUTPUT)-$$@.elf.txt
@$(OBJCOPY) -O binary $(OUTPUT)-$$@.elf $(OUTPUT)-$$@.bin @$(OBJCOPY) -O binary $(OUTPUT)-$$@.elf $(OUTPUT)-$$@.bin
@$(SIZE) $$^ $(OUTPUT)-$$@.elf @$(SIZE) $$^ $(OUTPUT)-$$@.elf
$$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN) $$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN)
@echo [COMPILING $$<] @echo [COMPILING $$<]
@$(CC) $(CFLAGS) -D$(1) -Wa,-ahlms=$(BIN)/$$*.lst -c -o $$@ $$< @$(CC) $(CFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -Wa,-ahlms=$(BIN)/$$*.lst -c -o $$@ $$<
$$(ASM_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.S Makefile $(OBJ) $(BIN) $$(ASM_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.S Makefile $(OBJ) $(BIN)
@echo [ASSEMBLING $$@] @echo [ASSEMBLING $$@]
@$(CC) $(ASFLAGS) -D$(1) -c -o $$@ $$< @$(CC) $(ASFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -c -o $$@ $$<
debug_$(1): $(1) debug_$(1): $(1)
$(GDB) -x "$(BOARD_LIB)/resources/gcc/$(BOARD)_$(1).gdb" -ex "reset" -readnow -se $(OUTPUT)-$(1).elf $(GDB) -x "$(BOARD_LIB)/resources/gcc/$(BOARD)_$(1).gdb" -ex "reset" -readnow -se $(OUTPUT)-$(1).elf
@@ -198,6 +218,3 @@ log:
clean: clean:
-rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst -rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst
rmbak:
-rm *~ $(BIN)/*~

33
firmware/README.txt Normal file
View File

@@ -0,0 +1,33 @@
== BOARDS
A board defines a given circuit board, i.e. SIMtrace, OWHW, QMOD
It defines the given hardware model for which the program is to be
compiled.
Current boards supported are:
* simtrace: The good old Osmocom SIMtrace PCB with SAM3 instead of
SAM7, open hardware.
* qmod: A sysmocom-proprietary quad mPCIe carrier board, publicly available
* owhw: An undisclosed sysmocom-internal board, not publicly available
== APPLICATIONS
An application is a specific piece of software with given
functionality.
== ENVIRONMENTS
An environment is a runtime environment, typically defined by a linker
script. The current runtime environments include
* flash: Run natively from start of flash memory
* dfu: Run after a DFU bootloader from an offset after the first 16k
of flash (the first 16k are reserved for the bootloader)
* ram: Run from within the RAM of the chip, downloaded via JTAG/SWD
== Building
A given software build is made for a specific combination of an APP
running in a certain ENVIRONMENT on a given BOARD.

View File

@@ -0,0 +1,3 @@
C_FILES += $(C_LIBUSB_RT)
C_FILES += card_emu.c ccid.c host_communication.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c

View File

@@ -3,12 +3,13 @@
* Headers * Headers
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
#define TRACE_LEVEL 5
#include "board.h" #include "board.h"
#include "simtrace.h" #include "simtrace.h"
#include "utils.h" #include "utils.h"
#include "req_ctx.h" #include "req_ctx.h"
#include "osmocom/core/timer.h"
unsigned int g_unique_id[4];
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Internal variables * Internal variables
@@ -22,6 +23,10 @@ typedef struct {
void (*exit) (void); void (*exit) (void);
/* main loop content for given configuration */ /* main loop content for given configuration */
void (*run) (void); void (*run) (void);
/* Interrupt handler for USART1 */
void (*usart0_irq) (void);
/* Interrupt handler for USART1 */
void (*usart1_irq) (void);
} conf_func; } conf_func;
static const conf_func config_func_ptrs[] = { static const conf_func config_func_ptrs[] = {
@@ -48,6 +53,8 @@ static const conf_func config_func_ptrs[] = {
.init = mode_cardemu_init, .init = mode_cardemu_init,
.exit = mode_cardemu_exit, .exit = mode_cardemu_exit,
.run = mode_cardemu_run, .run = mode_cardemu_run,
.usart0_irq = mode_cardemu_usart0_irq,
.usart1_irq = mode_cardemu_usart1_irq,
}, },
#endif #endif
#ifdef HAVE_MITM #ifdef HAVE_MITM
@@ -81,6 +88,29 @@ void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
simtrace_config = cfgnum; simtrace_config = cfgnum;
} }
void USART1_IrqHandler(void)
{
config_func_ptrs[simtrace_config].usart1_irq();
}
void USART0_IrqHandler(void)
{
config_func_ptrs[simtrace_config].usart0_irq();
}
/* returns '1' in case we should break any endless loop */
static void check_exec_dbg_cmd(void)
{
int ch;
if (!UART_IsRxReady())
return;
ch = UART_GetChar();
board_exec_dbg_cmd(ch);
}
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Main * Main
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
@@ -102,39 +132,55 @@ extern int main(void)
PIO_InitializeInterrupts(0); PIO_InitializeInterrupts(0);
SIMtrace_USB_Initialize(); EEFC_ReadUniqueID(g_unique_id);
printf("\r\n\r\n" printf("\r\n\r\n"
"=============================================================================\r\n" "=============================================================================\r\n"
"SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\r\n" "SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\r\n"
"=============================================================================\r\n"); "=============================================================================\r\n");
TRACE_INFO("USB init...\n\r"); TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\r\n",
g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]);
board_main_top();
TRACE_INFO("USB init...\r\n");
SIMtrace_USB_Initialize();
while (USBD_GetState() < USBD_STATE_CONFIGURED) { while (USBD_GetState() < USBD_STATE_CONFIGURED) {
check_exec_dbg_cmd();
#if 0
if (i >= MAX_USB_ITER * 3) { if (i >= MAX_USB_ITER * 3) {
TRACE_ERROR("Resetting board (USB could " TRACE_ERROR("Resetting board (USB could "
"not be configured)\n"); "not be configured)\r\n");
NVIC_SystemReset(); NVIC_SystemReset();
} }
#endif
i++; i++;
} }
TRACE_DEBUG("calling configure of all configurations...\n\r"); TRACE_INFO("calling configure of all configurations...\r\n");
for (i = 1; i < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]); for (i = 1; i < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]);
++i) { ++i) {
if (config_func_ptrs[i].configure) if (config_func_ptrs[i].configure)
config_func_ptrs[i].configure(); config_func_ptrs[i].configure();
} }
TRACE_DEBUG("calling init of config %u...\n\r", simtrace_config); TRACE_INFO("calling init of config %u...\r\n", simtrace_config);
config_func_ptrs[simtrace_config].init(); config_func_ptrs[simtrace_config].init();
last_simtrace_config = simtrace_config; last_simtrace_config = simtrace_config;
TRACE_DEBUG("entering main loop...\n\r"); TRACE_INFO("entering main loop...\r\n");
while (1) { while (1) {
#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG
const char rotor[] = { '-', '\\', '|', '/' }; const char rotor[] = { '-', '\\', '|', '/' };
putchar('\b'); putchar('\b');
putchar(rotor[i++ % ARRAY_SIZE(rotor)]); putchar(rotor[i++ % ARRAY_SIZE(rotor)]);
#endif
check_exec_dbg_cmd();
osmo_timers_prepare();
osmo_timers_update();
if (USBD_GetState() < USBD_STATE_CONFIGURED) { if (USBD_GetState() < USBD_STATE_CONFIGURED) {
@@ -142,7 +188,7 @@ extern int main(void)
isUsbConnected = 0; isUsbConnected = 0;
} }
} else if (isUsbConnected == 0) { } else if (isUsbConnected == 0) {
TRACE_INFO("USB is now configured\n\r"); TRACE_INFO("USB is now configured\r\n");
LED_Set(LED_NUM_GREEN); LED_Set(LED_NUM_GREEN);
LED_Clear(LED_NUM_RED); LED_Clear(LED_NUM_RED);

View File

View File

@@ -0,0 +1,12 @@
C_FILES += $(C_LIBUSB_DFU)
# Trace level used for compilation
# (can be overriden by adding TRACE_LEVEL=#number to the command-line)
# TRACE_LEVEL_DEBUG 5
# TRACE_LEVEL_INFO 4
# TRACE_LEVEL_WARNING 3
# TRACE_LEVEL_ERROR 2
# TRACE_LEVEL_FATAL 1
# TRACE_LEVEL_NO_TRACE 0
TRACE_LEVEL ?= 3

195
firmware/apps/dfu/main.c Normal file
View File

@@ -0,0 +1,195 @@
#include "board.h"
#include "utils.h"
#include "usb/device/dfu/dfu.h"
#include "usb/common/dfu/usb_dfu.h"
#include "manifest.h"
#define ALTIF_RAM 0
#define ALTIF_FLASH 1
unsigned int g_unique_id[4];
/*----------------------------------------------------------------------------
* Callbacks
*----------------------------------------------------------------------------*/
#define RAM_ADDR(offset) (IRAM_ADDR + BOARD_DFU_RAM_SIZE + offset)
#define FLASH_ADDR(offset) (IFLASH_ADDR + BOARD_DFU_BOOT_SIZE + offset)
#define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE)
#define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE)
/* incoming call-back: Host has transfered 'len' bytes (stored at
* 'data'), which we shall write to 'offset' into the partition
* associated with 'altif'. Guaranted to be les than
* BOARD_DFU_PAGE_SIZE */
int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
uint8_t *data, unsigned int len)
{
uint32_t addr;
int rc;
printf("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len);
switch (altif) {
case ALTIF_RAM:
addr = RAM_ADDR(offset);
if (addr > IRAM_ADDR + IRAM_SIZE) {
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL;
}
memcpy((void *)addr, data, len);
return DFU_RET_ZLP;
case ALTIF_FLASH:
addr = FLASH_ADDR(offset);
if (addr > IFLASH_ADDR + IFLASH_SIZE) {
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL;
}
rc = FLASHD_Write(addr, data, len);
if (rc != 0) {
/* FIXME: set error codes */
return DFU_RET_STALL;
}
return DFU_RET_ZLP;
default:
/* FIXME: set error codes */
TRACE_ERROR("DFU download for unknown AltIf %d\n\r", altif);
return DFU_RET_STALL;
}
}
/* incoming call-back: Host has requested to read back 'req_len' bytes
* starting from 'offset' of the firmware * associated with partition
* 'altif' */
int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
uint8_t *data, unsigned int req_len)
{
uint32_t addr;
printf("upload(altif=%u, offset=%u, len=%u)", altif, offset, req_len);
switch (altif) {
case ALTIF_RAM:
addr = RAM_ADDR(offset);
if (addr > IRAM_ADDR + IRAM_SIZE) {
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return -1;
}
if ((uint8_t *)addr + req_len > IRAM_END)
req_len = IRAM_END - (uint8_t *)addr;
memcpy(data, (void *)addr, req_len);
break;
case ALTIF_FLASH:
addr = FLASH_ADDR(offset);
if (addr > IFLASH_ADDR + IFLASH_SIZE) {
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return -1;
}
if ((uint8_t *)addr + req_len > IFLASH_END)
req_len = IFLASH_END - (uint8_t *)addr;
memcpy(data, (void *)addr, req_len);
break;
default:
TRACE_ERROR("DFU upload for unknown AltIf %d\n\r", altif);
/* FIXME: set error codes */
return -1;
}
printf("=%u\r\n", req_len);
return req_len;
}
/* returns '1' in case we should break any endless loop */
static void check_exec_dbg_cmd(void)
{
int ch;
if (!UART_IsRxReady())
return;
ch = UART_GetChar();
//board_exec_dbg_cmd(ch);
}
/*------------------------------------------------------------------------------
* Main
*------------------------------------------------------------------------------*/
#define MAX_USB_ITER BOARD_MCK/72 // This should be around a second
extern int main(void)
{
uint8_t isUsbConnected = 0;
unsigned int i = 0;
LED_Configure(LED_NUM_RED);
LED_Configure(LED_NUM_GREEN);
LED_Set(LED_NUM_RED);
/* Disable watchdog */
WDT_Disable(WDT);
//req_ctx_init();
PIO_InitializeInterrupts(0);
EEFC_ReadUniqueID(g_unique_id);
printf("\r\n\r\n"
"=============================================================================\r\n"
"DFU bootloader %s for board %s (C) 2010-2017 by Harald Welte\r\n"
"=============================================================================\r\n",
manifest_revision, manifest_board);
TRACE_INFO("Chip ID: 0x%08x (Ext 0x%08x)\r\n", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\r\n",
g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]);
//board_main_top();
TRACE_INFO("USB init...\r\n");
USBDFU_Initialize(&dfu_descriptors);
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
check_exec_dbg_cmd();
#if 1
if (i >= MAX_USB_ITER * 3) {
TRACE_ERROR("Resetting board (USB could "
"not be configured)\r\n");
NVIC_SystemReset();
}
#endif
i++;
}
FLASHD_Initialize(BOARD_MCK, 1);
TRACE_INFO("entering main loop...\r\n");
while (1) {
#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG
const char rotor[] = { '-', '\\', '|', '/' };
putchar('\b');
putchar(rotor[i++ % ARRAY_SIZE(rotor)]);
#endif
check_exec_dbg_cmd();
//osmo_timers_prepare();
//osmo_timers_update();
if (USBD_GetState() < USBD_STATE_CONFIGURED) {
if (isUsbConnected) {
isUsbConnected = 0;
}
} else if (isUsbConnected == 0) {
TRACE_INFO("USB is now configured\r\n");
LED_Set(LED_NUM_GREEN);
LED_Clear(LED_NUM_RED);
isUsbConnected = 1;
}
}
}

View File

View File

@@ -0,0 +1,3 @@
C_FILES += $(C_LIBUSB_RT)
C_FILES += card_emu.c ccid.c host_communication.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c

View File

@@ -0,0 +1,207 @@
// FIXME: Copyright license here
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "board.h"
#include "simtrace.h"
#include "utils.h"
#include "req_ctx.h"
#include "osmocom/core/timer.h"
unsigned int g_unique_id[4];
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
typedef struct {
/* static initialization, called whether or not the usb config is active */
void (*configure) (void);
/* initialization function after the config was selected */
void (*init) (void);
/* de-initialization before selecting new config */
void (*exit) (void);
/* main loop content for given configuration */
void (*run) (void);
/* Interrupt handler for USART1 */
void (*usart0_irq) (void);
/* Interrupt handler for USART1 */
void (*usart1_irq) (void);
} conf_func;
static const conf_func config_func_ptrs[] = {
/* array slot 0 is empty, usb configs start at 1 */
#ifdef HAVE_SNIFFER
[CFG_NUM_SNIFF] = {
.configure = Sniffer_configure,
.init = Sniffer_init,
.exit = Sniffer_exit,
.run = Sniffer_run,
},
#endif
#ifdef HAVE_CCID
[CFG_NUM_CCID] = {
.configure = CCID_configure,
.init = CCID_init,
.exit = CCID_exit,
.run = CCID_run,
},
#endif
#ifdef HAVE_CARDEM
[CFG_NUM_PHONE] = {
.configure = mode_cardemu_configure,
.init = mode_cardemu_init,
.exit = mode_cardemu_exit,
.run = mode_cardemu_run,
.usart0_irq = mode_cardemu_usart0_irq,
.usart1_irq = mode_cardemu_usart1_irq,
},
#endif
#ifdef HAVE_MITM
[CFG_NUM_MITM] = {
.configure = MITM_configure,
.init = MITM_init,
.exit = MITM_exit,
.run = MITM_run,
},
#endif
};
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
#if defined(HAVE_SNIFFER)
static volatile enum confNum simtrace_config = CFG_NUM_SNIFF;
#elif defined(HAVE_CARDEM)
static volatile enum confNum simtrace_config = CFG_NUM_PHONE;
#elif defined(HAVE_CCID)
static volatile enum confNum simtrace_config = CFG_NUM_CCID;
#endif
/*----------------------------------------------------------------------------
* Callbacks
*----------------------------------------------------------------------------*/
void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
{
TRACE_INFO_WP("cfgChanged%d ", cfgnum);
simtrace_config = cfgnum;
}
void USART1_IrqHandler(void)
{
config_func_ptrs[simtrace_config].usart1_irq();
}
void USART0_IrqHandler(void)
{
config_func_ptrs[simtrace_config].usart0_irq();
}
/* returns '1' in case we should break any endless loop */
static void check_exec_dbg_cmd(void)
{
int ch;
if (!UART_IsRxReady())
return;
ch = UART_GetChar();
board_exec_dbg_cmd(ch);
}
/*------------------------------------------------------------------------------
* Main
*------------------------------------------------------------------------------*/
#define MAX_USB_ITER BOARD_MCK/72 // This should be around a second
extern int main(void)
{
uint8_t isUsbConnected = 0;
enum confNum last_simtrace_config = simtrace_config;
unsigned int i = 0;
LED_Configure(LED_NUM_RED);
LED_Configure(LED_NUM_GREEN);
LED_Set(LED_NUM_RED);
/* Disable watchdog */
WDT_Disable(WDT);
req_ctx_init();
PIO_InitializeInterrupts(0);
EEFC_ReadUniqueID(g_unique_id);
printf("\r\n\r\n"
"=============================================================================\r\n"
"SIMtrace2 firmware " GIT_REVISION " (C) 2010-2017 by Harald Welte\r\n"
"=============================================================================\r\n");
TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\r\n",
g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]);
board_main_top();
TRACE_INFO("USB init...\r\n");
SIMtrace_USB_Initialize();
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
check_exec_dbg_cmd();
#if 0
if (i >= MAX_USB_ITER * 3) {
TRACE_ERROR("Resetting board (USB could "
"not be configured)\r\n");
NVIC_SystemReset();
}
#endif
i++;
}
TRACE_INFO("calling configure of all configurations...\r\n");
for (i = 1; i < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]);
++i) {
if (config_func_ptrs[i].configure)
config_func_ptrs[i].configure();
}
TRACE_INFO("calling init of config %u...\r\n", simtrace_config);
config_func_ptrs[simtrace_config].init();
last_simtrace_config = simtrace_config;
TRACE_INFO("entering main loop...\r\n");
while (1) {
#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG
const char rotor[] = { '-', '\\', '|', '/' };
putchar('\b');
putchar(rotor[i++ % ARRAY_SIZE(rotor)]);
#endif
check_exec_dbg_cmd();
osmo_timers_prepare();
osmo_timers_update();
if (USBD_GetState() < USBD_STATE_CONFIGURED) {
if (isUsbConnected) {
isUsbConnected = 0;
}
} else if (isUsbConnected == 0) {
TRACE_INFO("USB is now configured\r\n");
LED_Set(LED_NUM_GREEN);
LED_Clear(LED_NUM_RED);
isUsbConnected = 1;
}
if (last_simtrace_config != simtrace_config) {
TRACE_INFO("USB config chg %u -> %u\r\n",
last_simtrace_config, simtrace_config);
config_func_ptrs[last_simtrace_config].exit();
config_func_ptrs[simtrace_config].init();
last_simtrace_config = simtrace_config;
} else {
config_func_ptrs[simtrace_config].run();
}
}
}

View File

@@ -52,5 +52,8 @@
#include "trace.h" #include "trace.h"
#include "wdt.h" #include "wdt.h"
#include "unique_id.h"
#include "efc.h"
#include "flashd.h"
#endif /* _LIB_SAM3S_ */ #endif /* _LIB_SAM3S_ */

View File

@@ -0,0 +1,113 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \section Purpose
*
* Interface for configuration the Enhanced Embedded Flash Controller (EEFC) peripheral.
*
* \section Usage
*
* -# Enable/disable %flash ready interrupt sources using EFC_EnableFrdyIt()
* and EFC_DisableFrdyIt().
* -# Translates the given address into which EEFC, page and offset values
* for difference density %flash memory using EFC_TranslateAddress().
* -# Computes the address of a %flash access given the EFC, page and offset
* for difference density %flash memory using EFC_ComputeAddress().
* -# Start the executing command with EFC_StartCommand()
* -# Retrieve the current status of the EFC using EFC_GetStatus().
* -# Retrieve the result of the last executed command with EFC_GetResult().
*/
#ifndef _EEFC_
#define _EEFC_
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <stdint.h>
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
/* EFC command */
#define EFC_FCMD_GETD 0x00
#define EFC_FCMD_WP 0x01
#define EFC_FCMD_WPL 0x02
#define EFC_FCMD_EWP 0x03
#define EFC_FCMD_EWPL 0x04
#define EFC_FCMD_EA 0x05
#define EFC_FCMD_SLB 0x08
#define EFC_FCMD_CLB 0x09
#define EFC_FCMD_GLB 0x0A
#define EFC_FCMD_SFB 0x0B
#define EFC_FCMD_CFB 0x0C
#define EFC_FCMD_GFB 0x0D
#define EFC_FCMD_STUI 0x0E /* Start unique ID */
#define EFC_FCMD_SPUI 0x0F /* Stop unique ID */
/* The IAP function entry addreass */
#define CHIP_FLASH_IAP_ADDRESS (0x00800008)
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
extern void EFC_EnableFrdyIt( Efc* efc ) ;
extern void EFC_DisableFrdyIt( Efc* efc ) ;
extern void EFC_SetWaitState( Efc* efc, uint8_t cycles ) ;
extern void EFC_TranslateAddress( Efc** pEfc, uint32_t dwAddress, uint16_t *pwPage, uint16_t *pwOffset ) ;
extern void EFC_ComputeAddress( Efc* efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress ) ;
extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument ) ;
extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP ) ;
extern uint32_t EFC_GetStatus( Efc* efc ) ;
extern uint32_t EFC_GetResult( Efc* efc ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _EEFC_ */

View File

@@ -0,0 +1,79 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* The flash driver provides the unified interface for flash program operations.
*
*/
#ifndef _FLASHD_
#define _FLASHD_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
extern void FLASHD_Initialize( uint32_t dwMCk, uint32_t dwUseIAP ) ;
extern uint32_t FLASHD_Erase( uint32_t dwAddress ) ;
extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize ) ;
extern uint32_t FLASHD_Lock( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) ;
extern uint32_t FLASHD_Unlock( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) ;
extern uint32_t FLASHD_IsLocked( uint32_t dwStart, uint32_t dwEnd ) ;
extern uint32_t FLASHD_SetGPNVM( uint8_t gpnvm ) ;
extern uint32_t FLASHD_ClearGPNVM( uint8_t gpnvm ) ;
extern uint32_t FLASHD_IsGPNVMSet( uint8_t gpnvm ) ;
#define FLASHD_IsSecurityBitSet() FLASHD_IsGPNVMSet( 0 )
#define FLASHD_SetSecurityBit() FLASHD_SetGPNVM( 0 )
extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _FLASHD_ */

View File

@@ -0,0 +1,3 @@
#pragma once
void EEFC_ReadUniqueID(unsigned int *pdwUniqueID);

View File

@@ -45,8 +45,14 @@
* Headers * Headers
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
#ifdef TRACE_LEVEL
#undef TRACE_LEVEL
#endif
#define TRACE_LEVEL TRACE_LEVEL_WARNING
#include "chip.h" #include "chip.h"
#include "USBD_HAL.h" #include "USBD_HAL.h"
#include <usb/device/dfu/dfu.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@@ -1156,6 +1162,22 @@ void USBD_IrqHandler(void)
else if ((status & UDP_ISR_ENDBUSRES) != 0) { else if ((status & UDP_ISR_ENDBUSRES) != 0) {
TRACE_INFO_WP("EoBRes "); TRACE_INFO_WP("EoBRes ");
#if defined(BOARD_USB_DFU)
#if defined(APPLICATION_dfu)
/* if we are currently in the DFU bootloader, and we are beyond
* the MANIFEST stage, we shall switch to the normal
* application */
if (g_dfu->past_manifest)
USBDFU_SwitchToApp();
#else
/* if we are currently in the main application, and we are in
* appDETACH state, switch into the DFU bootloader */
if (g_dfu->state == DFU_STATE_appDETACH)
DFURT_SwitchToDFU();
#endif /* APPLICATION_dfu */
#endif /* BOARD_USB_DFU */
/* Flush and enable the Suspend interrupt */ /* Flush and enable the Suspend interrupt */
UDP->UDP_ICR = UDP_ICR_WAKEUP | UDP_ICR_RXRSM | UDP_ICR_RXSUSP; UDP->UDP_ICR = UDP_ICR_WAKEUP | UDP_ICR_RXRSM | UDP_ICR_RXSUSP;
UDP->UDP_IER = UDP_IER_RXSUSP; UDP->UDP_IER = UDP_IER_RXSUSP;

View File

@@ -0,0 +1,290 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup efc_module Working with EEFC
* The EEFC driver provides the interface to configure and use the EEFC
* peripheral.
*
* The user needs to set the number of wait states depending on the frequency used.\n
* Configure number of cycles for flash read/write operations in the FWS field of EEFC_FMR.
*
* It offers a function to send flash command to EEFC and waits for the
* flash to be ready.
*
* To send flash command, the user could do in either of following way:
* <ul>
* <li>Write a correct key, command and argument in EEFC_FCR. </li>
* <li>Or, Use IAP (In Application Programming) function which is executed from
* ROM directly, this allows flash programming to be done by code running in flash.</li>
* <li>Once the command is achieved, it can be detected even by polling EEFC_FSR or interrupt.
* </ul>
*
* The command argument could be a page number,GPNVM number or nothing, it depends on
* the command itself. Some useful functions in this driver could help user tranlate physical
* flash address into a page number and vice verse.
*
* For more accurate information, please look at the EEFC section of the
* Datasheet.
*
* Related files :\n
* \ref efc.c\n
* \ref efc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Enhanced Embedded Flash Controller (EEFC).
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include "efc.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Enables the flash ready interrupt source on the EEFC peripheral.
*
* \param efc Pointer to a Efc instance
*/
extern void EFC_EnableFrdyIt( Efc* efc )
{
efc->EEFC_FMR |= EEFC_FMR_FRDY ;
}
/**
* \brief Disables the flash ready interrupt source on the EEFC peripheral.
*
* \param efc Pointer to a Efc instance
*/
extern void EFC_DisableFrdyIt( Efc* efc )
{
efc->EEFC_FMR &= ~((uint32_t)EEFC_FMR_FRDY) ;
}
/**
* \brief Set read/write wait state on the EEFC perpherial.
*
* \param efc Pointer to a Efc instance
* \param cycles the number of wait states in cycle.
*/
extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles )
{
uint32_t dwValue ;
dwValue = efc->EEFC_FMR ;
dwValue &= ~((uint32_t)EEFC_FMR_FWS_Msk) ;
dwValue |= EEFC_FMR_FWS(ucCycles);
efc->EEFC_FMR = dwValue ;
}
/**
* \brief Returns the current status of the EEFC.
*
* \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE).
*
* \param efc Pointer to a Efc instance
*/
extern uint32_t EFC_GetStatus( Efc* efc )
{
return efc->EEFC_FSR ;
}
/**
* \brief Returns the result of the last executed command.
*
* \param efc Pointer to a Efc instance
*/
extern uint32_t EFC_GetResult( Efc* efc )
{
return efc->EEFC_FRR ;
}
/**
* \brief Translates the given address page and offset values.
* \note The resulting values are stored in the provided variables if they are not null.
*
* \param efc Pointer to a Efc instance
* \param address Address to translate.
* \param pPage First page accessed.
* \param pOffset Byte offset in first page.
*/
extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset )
{
Efc *pEfc ;
uint16_t wPage ;
uint16_t wOffset ;
assert( dwAddress >= IFLASH_ADDR ) ;
assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
pEfc = EFC ;
wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE;
wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE;
TRACE_DEBUG( "Translated 0x%08X to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ;
/* Store values */
if ( pEfc )
{
*ppEfc = pEfc ;
}
if ( pwPage )
{
*pwPage = wPage ;
}
if ( pwOffset )
{
*pwOffset = wOffset ;
}
}
/**
* \brief Computes the address of a flash access given the page and offset.
*
* \param efc Pointer to a Efc instance
* \param page Page number.
* \param offset Byte offset inside page.
* \param pAddress Computed address (optional).
*/
extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress )
{
uint32_t dwAddress ;
assert( efc ) ;
assert( wPage <= IFLASH_NB_OF_PAGES ) ;
assert( wOffset < IFLASH_PAGE_SIZE ) ;
/* Compute address */
dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ;
/* Store result */
if ( pdwAddress != NULL )
{
*pdwAddress = dwAddress ;
}
}
/**
* \brief Starts the executing the given command on the EEFC and returns as soon as the command is started.
*
* \note It does NOT set the FMCN field automatically.
* \param efc Pointer to a Efc instance
* \param command Command to execute.
* \param argument Command argument (should be 0 if not used).
*/
extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument )
{
/* Check command & argument */
switch ( dwCommand )
{
case EFC_FCMD_WP:
case EFC_FCMD_WPL:
case EFC_FCMD_EWP:
case EFC_FCMD_EWPL:
case EFC_FCMD_SLB:
case EFC_FCMD_CLB:
assert( dwArgument < IFLASH_NB_OF_PAGES ) ;
break ;
case EFC_FCMD_SFB:
case EFC_FCMD_CFB:
assert( dwArgument < 2 ) ;
break;
case EFC_FCMD_GETD:
case EFC_FCMD_EA:
case EFC_FCMD_GLB:
case EFC_FCMD_GFB:
case EFC_FCMD_STUI:
assert( dwArgument == 0 ) ;
break;
default: assert( 0 ) ;
}
/* Start command Embedded flash */
assert( (efc->EEFC_FSR & EEFC_FMR_FRDY) == EEFC_FMR_FRDY ) ;
efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
}
/**
* \brief Performs the given command and wait until its completion (or an error).
*
* \param efc Pointer to a Efc instance
* \param command Command to perform.
* \param argument Optional command argument.
*
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP )
{
if ( dwUseIAP != 0 )
{
/* Pointer on IAP function in ROM */
static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ;
IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ;
IAP_PerformCommand( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ;
return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ;
}
else
{
uint32_t dwStatus ;
efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
do
{
dwStatus = efc->EEFC_FSR ;
}
while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ;
return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ;
}
}

View File

@@ -52,6 +52,7 @@
*/ */
void IrqHandlerNotUsed( void ) void IrqHandlerNotUsed( void )
{ {
printf("NotUsed\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -60,15 +61,50 @@ void IrqHandlerNotUsed( void )
*/ */
WEAK void NMI_Handler( void ) WEAK void NMI_Handler( void )
{ {
printf("NMI\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
/** /**
* \brief Default HardFault interrupt handler. * \brief Default HardFault interrupt handler.
*/ */
struct hardfault_args {
unsigned long r0;
unsigned long r1;
unsigned long r2;
unsigned long r3;
unsigned long r12;
unsigned long lr;
unsigned long pc;
unsigned long psr;
};
void hard_fault_handler_c(struct hardfault_args *args)
{
printf("HardFault\r\n");
printf("R0=%08x, R1=%08x, R2=%08x, R3=%08x, R12=%08x\r\n",
args->r0, args->r1, args->r2, args->r3, args->r12);
printf("LR[R14]=%08x, PC[R15]=%08x, PSR=%08x\r\n",
args->lr, args->pc, args->psr);
printf("BFAR=%08x, CFSR=%08x, HFSR=%08x\r\n",
SCB->BFAR, SCB->CFSR, SCB->HFSR);
printf("DFSR=%08x, AFSR=%08x, SHCSR=%08x\r\n",
SCB->DFSR, SCB->CFSR, SCB->SHCSR);
while ( 1 ) ;
}
__attribute__((naked))
WEAK void HardFault_Handler( void ) WEAK void HardFault_Handler( void )
{ {
while ( 1 ) ; __asm volatile(
".syntax unified \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
//" ldr r1, [r0, #24] \n"
" b hard_fault_handler_c\n"
".syntax divided \n");
} }
/** /**
@@ -76,6 +112,7 @@ WEAK void HardFault_Handler( void )
*/ */
WEAK void MemManage_Handler( void ) WEAK void MemManage_Handler( void )
{ {
printf("MemManage\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -84,6 +121,7 @@ WEAK void MemManage_Handler( void )
*/ */
WEAK void BusFault_Handler( void ) WEAK void BusFault_Handler( void )
{ {
printf("BusFault\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -92,6 +130,7 @@ WEAK void BusFault_Handler( void )
*/ */
WEAK void UsageFault_Handler( void ) WEAK void UsageFault_Handler( void )
{ {
printf("UsageFault\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -100,6 +139,7 @@ WEAK void UsageFault_Handler( void )
*/ */
WEAK void SVC_Handler( void ) WEAK void SVC_Handler( void )
{ {
printf("SVC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -108,6 +148,7 @@ WEAK void SVC_Handler( void )
*/ */
WEAK void DebugMon_Handler( void ) WEAK void DebugMon_Handler( void )
{ {
printf("DebugMon\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -116,6 +157,7 @@ WEAK void DebugMon_Handler( void )
*/ */
WEAK void PendSV_Handler( void ) WEAK void PendSV_Handler( void )
{ {
printf("PendSV\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -124,6 +166,7 @@ WEAK void PendSV_Handler( void )
*/ */
WEAK void SysTick_Handler( void ) WEAK void SysTick_Handler( void )
{ {
printf("SysTick\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -132,6 +175,7 @@ WEAK void SysTick_Handler( void )
*/ */
WEAK void SUPC_IrqHandler( void ) WEAK void SUPC_IrqHandler( void )
{ {
printf("SUPC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -140,6 +184,7 @@ WEAK void SUPC_IrqHandler( void )
*/ */
WEAK void RSTC_IrqHandler( void ) WEAK void RSTC_IrqHandler( void )
{ {
printf("RSTC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -148,6 +193,7 @@ WEAK void RSTC_IrqHandler( void )
*/ */
WEAK void RTC_IrqHandler( void ) WEAK void RTC_IrqHandler( void )
{ {
printf("RTC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -156,6 +202,7 @@ WEAK void RTC_IrqHandler( void )
*/ */
WEAK void RTT_IrqHandler( void ) WEAK void RTT_IrqHandler( void )
{ {
printf("RTT\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -164,6 +211,7 @@ WEAK void RTT_IrqHandler( void )
*/ */
WEAK void WDT_IrqHandler( void ) WEAK void WDT_IrqHandler( void )
{ {
printf("WDT\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -172,6 +220,7 @@ WEAK void WDT_IrqHandler( void )
*/ */
WEAK void PMC_IrqHandler( void ) WEAK void PMC_IrqHandler( void )
{ {
printf("PMC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -180,6 +229,7 @@ WEAK void PMC_IrqHandler( void )
*/ */
WEAK void EEFC_IrqHandler( void ) WEAK void EEFC_IrqHandler( void )
{ {
printf("EEFC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -188,6 +238,7 @@ WEAK void EEFC_IrqHandler( void )
*/ */
WEAK void UART0_IrqHandler( void ) WEAK void UART0_IrqHandler( void )
{ {
printf("UART0\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -196,6 +247,7 @@ WEAK void UART0_IrqHandler( void )
*/ */
WEAK void UART1_IrqHandler( void ) WEAK void UART1_IrqHandler( void )
{ {
printf("UART1\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -204,6 +256,7 @@ WEAK void UART1_IrqHandler( void )
*/ */
WEAK void SMC_IrqHandler( void ) WEAK void SMC_IrqHandler( void )
{ {
printf("SMC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -212,6 +265,7 @@ WEAK void SMC_IrqHandler( void )
*/ */
WEAK void PIOA_IrqHandler( void ) WEAK void PIOA_IrqHandler( void )
{ {
printf("PIOA\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -220,6 +274,7 @@ WEAK void PIOA_IrqHandler( void )
*/ */
WEAK void PIOB_IrqHandler( void ) WEAK void PIOB_IrqHandler( void )
{ {
printf("PIOB\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -228,6 +283,7 @@ WEAK void PIOB_IrqHandler( void )
*/ */
WEAK void PIOC_IrqHandler( void ) WEAK void PIOC_IrqHandler( void )
{ {
printf("PIOC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -236,6 +292,7 @@ WEAK void PIOC_IrqHandler( void )
*/ */
WEAK void USART0_IrqHandler( void ) WEAK void USART0_IrqHandler( void )
{ {
printf("USART0\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -244,6 +301,7 @@ WEAK void USART0_IrqHandler( void )
*/ */
WEAK void USART1_IrqHandler( void ) WEAK void USART1_IrqHandler( void )
{ {
printf("USART1\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -252,6 +310,7 @@ WEAK void USART1_IrqHandler( void )
*/ */
WEAK void MCI_IrqHandler( void ) WEAK void MCI_IrqHandler( void )
{ {
printf("MCI\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -260,6 +319,7 @@ WEAK void MCI_IrqHandler( void )
*/ */
WEAK void TWI0_IrqHandler( void ) WEAK void TWI0_IrqHandler( void )
{ {
printf("TWI0\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -268,6 +328,7 @@ WEAK void TWI0_IrqHandler( void )
*/ */
WEAK void TWI1_IrqHandler( void ) WEAK void TWI1_IrqHandler( void )
{ {
printf("TWI1\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -276,6 +337,7 @@ WEAK void TWI1_IrqHandler( void )
*/ */
WEAK void SPI_IrqHandler( void ) WEAK void SPI_IrqHandler( void )
{ {
printf("SPI\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -284,6 +346,7 @@ WEAK void SPI_IrqHandler( void )
*/ */
WEAK void SSC_IrqHandler( void ) WEAK void SSC_IrqHandler( void )
{ {
printf("SSC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -292,6 +355,7 @@ WEAK void SSC_IrqHandler( void )
*/ */
WEAK void TC0_IrqHandler( void ) WEAK void TC0_IrqHandler( void )
{ {
printf("TC0\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -300,6 +364,7 @@ WEAK void TC0_IrqHandler( void )
*/ */
WEAK void TC1_IrqHandler( void ) WEAK void TC1_IrqHandler( void )
{ {
printf("TC1\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -308,6 +373,7 @@ WEAK void TC1_IrqHandler( void )
*/ */
WEAK void TC2_IrqHandler( void ) WEAK void TC2_IrqHandler( void )
{ {
printf("TC2\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -316,6 +382,7 @@ WEAK void TC2_IrqHandler( void )
*/ */
WEAK void TC3_IrqHandler( void ) WEAK void TC3_IrqHandler( void )
{ {
printf("TC3\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -324,6 +391,7 @@ WEAK void TC3_IrqHandler( void )
*/ */
WEAK void TC4_IrqHandler( void ) WEAK void TC4_IrqHandler( void )
{ {
printf("TC4\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -332,6 +400,7 @@ WEAK void TC4_IrqHandler( void )
*/ */
WEAK void TC5_IrqHandler( void ) WEAK void TC5_IrqHandler( void )
{ {
printf("TC5\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -340,6 +409,7 @@ WEAK void TC5_IrqHandler( void )
*/ */
WEAK void ADC_IrqHandler( void ) WEAK void ADC_IrqHandler( void )
{ {
printf("ADC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -348,6 +418,7 @@ WEAK void ADC_IrqHandler( void )
*/ */
WEAK void DAC_IrqHandler( void ) WEAK void DAC_IrqHandler( void )
{ {
printf("DAC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -356,6 +427,7 @@ WEAK void DAC_IrqHandler( void )
*/ */
WEAK void PWM_IrqHandler( void ) WEAK void PWM_IrqHandler( void )
{ {
printf("PWM\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -364,6 +436,7 @@ WEAK void PWM_IrqHandler( void )
*/ */
WEAK void CRCCU_IrqHandler( void ) WEAK void CRCCU_IrqHandler( void )
{ {
printf("CRCCU\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -372,6 +445,7 @@ WEAK void CRCCU_IrqHandler( void )
*/ */
WEAK void ACC_IrqHandler( void ) WEAK void ACC_IrqHandler( void )
{ {
printf("ACC\r\n");
while ( 1 ) ; while ( 1 ) ;
} }
@@ -380,5 +454,6 @@ WEAK void ACC_IrqHandler( void )
*/ */
WEAK void USBD_IrqHandler( void ) WEAK void USBD_IrqHandler( void )
{ {
printf("USBD\r\n");
while ( 1 ) ; while ( 1 ) ;
} }

View File

@@ -0,0 +1,517 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup flashd_module Flash Memory Interface
* The flash driver manages the programming, erasing, locking and unlocking sequences
* with dedicated commands.
*
* To implement flash programing operation, the user has to follow these few steps :
* <ul>
* <li>Configue flash wait states to initializes the flash. </li>
* <li>Checks whether a region to be programmed is locked. </li>
* <li>Unlocks the user region to be programmed if the region have locked before.</li>
* <li>Erases the user page before program (optional).</li>
* <li>Writes the user page from the page buffer.</li>
* <li>Locks the region of programmed area if any.</li>
* </ul>
*
* Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption.
* A check of this validity and padding for 32-bit alignment should be done in write algorithm.
* Lock/unlock range associated with the user address range is automatically translated.
*
* This security bit can be enabled through the command "Set General Purpose NVM Bit 0".
*
* A 128-bit factory programmed unique ID could be read to serve several purposes.
*
* The driver accesses the flash memory by calling the lowlevel module provided in \ref efc_module.
* For more accurate information, please look at the EEFC section of the Datasheet.
*
* Related files :\n
* \ref flashd.c\n
* \ref flashd.h.\n
* \ref efc.c\n
* \ref efc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* The flash driver provides the unified interface for flash program operations.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include "flashd.h"
#include "efc.h"
#include <string.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
//static NO_INIT uint8_t _aucPageBuffer[IFLASH_PAGE_SIZE] ;
static NO_INIT uint32_t _adwPageBuffer[IFLASH_PAGE_SIZE/4] ;
static uint8_t* _aucPageBuffer = (uint8_t*)_adwPageBuffer;
static NO_INIT uint32_t _dwUseIAP ;
/*----------------------------------------------------------------------------
* Local macros
*----------------------------------------------------------------------------*/
#define min( a, b ) (((a) < (b)) ? (a) : (b))
/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/
/**
* \brief Computes the lock range associated with the given address range.
*
* \param dwStart Start address of lock range.
* \param dwEnd End address of lock range.
* \param pdwActualStart Actual start address of lock range.
* \param pdwActualEnd Actual end address of lock range.
*/
static void ComputeLockRange( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd )
{
Efc* pStartEfc ;
Efc* pEndEfc ;
uint16_t wStartPage ;
uint16_t wEndPage ;
uint16_t wNumPagesInRegion ;
uint16_t wActualStartPage ;
uint16_t wActualEndPage ;
// Convert start and end address in page numbers
EFC_TranslateAddress( &pStartEfc, dwStart, &wStartPage, 0 ) ;
EFC_TranslateAddress( &pEndEfc, dwEnd, &wEndPage, 0 ) ;
// Find out the first page of the first region to lock
wNumPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ;
wActualStartPage = wStartPage - (wStartPage % wNumPagesInRegion) ;
wActualEndPage = wEndPage ;
if ( (wEndPage % wNumPagesInRegion) != 0 )
{
wActualEndPage += wNumPagesInRegion - (wEndPage % wNumPagesInRegion) ;
}
// Store actual page numbers
EFC_ComputeAddress( pStartEfc, wActualStartPage, 0, pdwActualStart ) ;
EFC_ComputeAddress( pEndEfc, wActualEndPage, 0, pdwActualEnd ) ;
TRACE_DEBUG( "Actual lock range is 0x%06X - 0x%06X\n\r", *pdwActualStart, *pdwActualEnd ) ;
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Initializes the flash driver.
*
* \param mck Master clock frequency in Hz.
*/
extern void FLASHD_Initialize( uint32_t dwMCk, uint32_t dwUseIAP )
{
EFC_DisableFrdyIt( EFC ) ;
#if 1
/* See Revision A errata 46.1.1.3 */
EFC_SetWaitState(EFC, 6);
#else
if ( (dwMCk/1000000) >= 64 )
{
EFC_SetWaitState( EFC, 2 ) ;
}
else
{
if ( (dwMCk/1000000) >= 50 )
{
EFC_SetWaitState( EFC, 1 ) ;
}
else
{
EFC_SetWaitState( EFC, 0 ) ;
}
}
#endif
_dwUseIAP=dwUseIAP ;
}
/**
* \brief Erases the entire flash.
*
* \param address Flash start address.
* \return 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_Erase( uint32_t dwAddress )
{
Efc* pEfc ;
uint16_t wPage ;
uint16_t wOffset ;
uint32_t dwError ;
assert( (dwAddress >=IFLASH_ADDR) || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)) ) ;
// Translate write address
EFC_TranslateAddress( &pEfc, dwAddress, &wPage, &wOffset ) ;
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_EA, 0, _dwUseIAP ) ;
return dwError ;
}
/**
* \brief Writes a data buffer in the internal flash
*
* \note This function works in polling mode, and thus only returns when the
* data has been effectively written.
* \param address Write address.
* \param pBuffer Data buffer.
* \param size Size of data buffer in bytes.
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize )
{
Efc* pEfc ;
uint16_t page ;
uint16_t offset ;
uint32_t writeSize ;
uint32_t pageAddress ;
uint16_t padding ;
uint32_t dwError ;
uint32_t sizeTmp ;
uint32_t *pAlignedDestination ;
uint32_t *pAlignedSource ;
assert( pvBuffer ) ;
assert( dwAddress >=IFLASH_ADDR ) ;
assert( (dwAddress + dwSize) <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
/* Translate write address */
EFC_TranslateAddress( &pEfc, dwAddress, &page, &offset ) ;
/* Write all pages */
while ( dwSize > 0 )
{
/* Copy data in temporary buffer to avoid alignment problems */
writeSize = min((uint32_t)IFLASH_PAGE_SIZE - offset, dwSize ) ;
EFC_ComputeAddress(pEfc, page, 0, &pageAddress ) ;
padding = IFLASH_PAGE_SIZE - offset - writeSize ;
/* Pre-buffer data */
memcpy( _aucPageBuffer, (void *) pageAddress, offset);
/* Buffer data */
memcpy( _aucPageBuffer + offset, pvBuffer, writeSize);
/* Post-buffer data */
memcpy( _aucPageBuffer + offset + writeSize, (void *) (pageAddress + offset + writeSize), padding);
/* Write page
* Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption
*/
pAlignedDestination = (uint32_t*)pageAddress ;
pAlignedSource = (uint32_t*)_adwPageBuffer ;
sizeTmp = IFLASH_PAGE_SIZE ;
while ( sizeTmp >= 4 )
{
*pAlignedDestination++ = *pAlignedSource++;
sizeTmp -= 4;
}
/* Send writing command */
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_EWP, page, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
/* Progression */
dwAddress += IFLASH_PAGE_SIZE ;
pvBuffer = (void *)((uint32_t) pvBuffer + writeSize) ;
dwSize -= writeSize ;
page++;
offset = 0;
}
return 0 ;
}
/**
* \brief Locks all the regions in the given address range. The actual lock range is
* reported through two output parameters.
*
* \param start Start address of lock range.
* \param end End address of lock range.
* \param pActualStart Start address of the actual lock range (optional).
* \param pActualEnd End address of the actual lock range (optional).
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t FLASHD_Lock( uint32_t start, uint32_t end, uint32_t *pActualStart, uint32_t *pActualEnd )
{
Efc *pEfc ;
uint32_t actualStart, actualEnd ;
uint16_t startPage, endPage ;
uint32_t dwError ;
uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
/* Compute actual lock range and store it */
ComputeLockRange( start, end, &actualStart, &actualEnd ) ;
if ( pActualStart != NULL )
{
*pActualStart = actualStart ;
}
if ( pActualEnd != NULL )
{
*pActualEnd = actualEnd;
}
/* Compute page numbers */
EFC_TranslateAddress( &pEfc, actualStart, &startPage, 0 ) ;
EFC_TranslateAddress( 0, actualEnd, &endPage, 0 ) ;
/* Lock all pages */
while ( startPage < endPage )
{
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_SLB, startPage, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
startPage += numPagesInRegion;
}
return 0 ;
}
/**
* \brief Unlocks all the regions in the given address range. The actual unlock range is
* reported through two output parameters.
* \param start Start address of unlock range.
* \param end End address of unlock range.
* \param pActualStart Start address of the actual unlock range (optional).
* \param pActualEnd End address of the actual unlock range (optional).
* \return 0 if successful, otherwise returns an error code.
*/
extern uint32_t FLASHD_Unlock( uint32_t start, uint32_t end, uint32_t *pActualStart, uint32_t *pActualEnd )
{
Efc* pEfc ;
uint32_t actualStart, actualEnd ;
uint16_t startPage, endPage ;
uint32_t dwError ;
uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
// Compute actual unlock range and store it
ComputeLockRange(start, end, &actualStart, &actualEnd);
if ( pActualStart != NULL )
{
*pActualStart = actualStart ;
}
if ( pActualEnd != NULL )
{
*pActualEnd = actualEnd ;
}
// Compute page numbers
EFC_TranslateAddress( &pEfc, actualStart, &startPage, 0 ) ;
EFC_TranslateAddress( 0, actualEnd, &endPage, 0 ) ;
// Unlock all pages
while ( startPage < endPage )
{
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_CLB, startPage, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
startPage += numPagesInRegion ;
}
return 0 ;
}
/**
* \brief Returns the number of locked regions inside the given address range.
*
* \param start Start address of range
* \param end End address of range.
*/
extern uint32_t FLASHD_IsLocked( uint32_t start, uint32_t end )
{
Efc *pEfc ;
uint16_t startPage, endPage ;
uint8_t startRegion, endRegion ;
uint32_t numPagesInRegion ;
uint32_t status ;
uint32_t dwError ;
uint32_t numLockedRegions = 0 ;
assert( end >= start ) ;
assert( (start >=IFLASH_ADDR) && (end <= IFLASH_ADDR + IFLASH_SIZE) ) ;
// Compute page numbers
EFC_TranslateAddress( &pEfc, start, &startPage, 0 ) ;
EFC_TranslateAddress( 0, end, &endPage, 0 ) ;
// Compute region numbers
numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ;
startRegion = startPage / numPagesInRegion ;
endRegion = endPage / numPagesInRegion ;
if ((endPage % numPagesInRegion) != 0)
{
endRegion++ ;
}
// Retrieve lock status
dwError = EFC_PerformCommand( pEfc, EFC_FCMD_GLB, 0, _dwUseIAP ) ;
assert( !dwError ) ;
status = EFC_GetResult( pEfc ) ;
// Check status of each involved region
while ( startRegion < endRegion )
{
if ( (status & (1 << startRegion)) != 0 )
{
numLockedRegions++ ;
}
startRegion++ ;
}
return numLockedRegions ;
}
/**
* \brief Check if the given GPNVM bit is set or not.
*
* \param gpnvm GPNVM bit index.
* \returns 1 if the given GPNVM bit is currently set; otherwise returns 0.
*/
extern uint32_t FLASHD_IsGPNVMSet( uint8_t ucGPNVM )
{
uint32_t dwError ;
uint32_t dwStatus ;
assert( ucGPNVM < 2 ) ;
/* Get GPNVMs status */
dwError = EFC_PerformCommand( EFC, EFC_FCMD_GFB, 0, _dwUseIAP ) ;
assert( !dwError ) ;
dwStatus = EFC_GetResult( EFC ) ;
/* Check if GPNVM is set */
if ( (dwStatus & (1 << ucGPNVM)) != 0 )
{
return 1 ;
}
else
{
return 0 ;
}
}
/**
* \brief Sets the selected GPNVM bit.
*
* \param gpnvm GPNVM bit index.
* \returns 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_SetGPNVM( uint8_t ucGPNVM )
{
assert( ucGPNVM < 2 ) ;
if ( !FLASHD_IsGPNVMSet( ucGPNVM ) )
{
return EFC_PerformCommand( EFC, EFC_FCMD_SFB, ucGPNVM, _dwUseIAP ) ;
}
else
{
return 0 ;
}
}
/**
* \brief Clears the selected GPNVM bit.
*
* \param gpnvm GPNVM bit index.
* \returns 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_ClearGPNVM( uint8_t ucGPNVM )
{
assert( ucGPNVM < 2 ) ;
if ( FLASHD_IsGPNVMSet( ucGPNVM ) )
{
return EFC_PerformCommand( EFC, EFC_FCMD_CFB, ucGPNVM, _dwUseIAP ) ;
}
else
{
return 0 ;
}
}
/**
* \brief Read the unique ID.
*
* \param uniqueID pointer on a 4bytes char containing the unique ID value.
* \returns 0 if successful; otherwise returns an error code.
*/
extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID )
{
uint32_t dwError ;
assert( pdwUniqueID != NULL ) ;
pdwUniqueID[0] = 0 ;
pdwUniqueID[1] = 0 ;
pdwUniqueID[2] = 0 ;
pdwUniqueID[3] = 0 ;
EFC_StartCommand( EFC, EFC_FCMD_STUI, 0 ) ;
pdwUniqueID[0] = *(uint32_t*) IFLASH_ADDR;
pdwUniqueID[1] = *(uint32_t*)(IFLASH_ADDR + 4) ;
pdwUniqueID[2] = *(uint32_t*)(IFLASH_ADDR + 8) ;
pdwUniqueID[3] = *(uint32_t*)(IFLASH_ADDR + 12) ;
dwError = EFC_PerformCommand( EFC, EFC_FCMD_SPUI, 0, _dwUseIAP ) ;
if ( dwError )
{
return dwError ;
}
return 0 ;
}

View File

@@ -83,9 +83,9 @@ static uint32_t _dwNumSources = 0;
* \brief Stub, to handling all PIO Capture interrupts, if not defined. * \brief Stub, to handling all PIO Capture interrupts, if not defined.
*/ */
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
//extern WEAK void PIO_CaptureHandler( void ) extern WEAK void PIO_CaptureHandler( void )
//{ {
//} }
/** /**
* \brief Handles all interrupts on the given PIO controller. * \brief Handles all interrupts on the given PIO controller.

View File

@@ -0,0 +1,43 @@
#include "chip.h"
#define EFC_FCMD_STUI 0x0E
#define EFC_FCMD_SPUI 0x0F
__attribute__ ((section(".ramfunc")))
void EEFC_ReadUniqueID(unsigned int *pdwUniqueID)
{
unsigned int status;
/* Errata / Workaround: Set bit 16 of EEFC Flash Mode Register
* to 1 */
EFC->EEFC_FMR |= (1 << 16);
/* Send the Start Read unique Identifier command (STUI) by
* writing the Flash Command Register with the STUI command. */
EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
/* Wait for the FRDY bit to fall */
do {
status = EFC->EEFC_FSR;
} while ((status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY);
/* The Unique Identifier is located in the first 128 bits of the
* Flash memory mapping. So, at the address 0x400000-0x400003.
* */
pdwUniqueID[0] = *(uint32_t *) IFLASH_ADDR;
pdwUniqueID[1] = *(uint32_t *) (IFLASH_ADDR + 4);
pdwUniqueID[2] = *(uint32_t *) (IFLASH_ADDR + 8);
pdwUniqueID[3] = *(uint32_t *) (IFLASH_ADDR + 12);
/* To stop the Unique Identifier mode, the user needs to send
* the Stop Read unique Identifier command (SPUI) by writing the
* Flash Command Register with the SPUI command. */
EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI;
/* When the Stop read Unique Unique Identifier command (SPUI)
* has been performed, the FRDY bit in the Flash Programming
* Status Register (EEFC_FSR) rises. */
do {
status = EFC->EEFC_FSR;
} while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
}

View File

@@ -0,0 +1,81 @@
#ifndef _USB_DFU_H
#define _USB_DFU_H
/* USB Device Firmware Update Implementation for OpenPCD
* (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
*
* Protocol definitions for USB DFU
*
* This ought to be compliant to the USB DFU Spec 1.0 as available from
* http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
*
*/
#include <stdint.h>
#include <usb/include/USBRequests.h>
#define USB_DT_DFU 0x21
struct usb_dfu_func_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bmAttributes;
#define USB_DFU_CAN_DOWNLOAD (1 << 0)
#define USB_DFU_CAN_UPLOAD (1 << 1)
#define USB_DFU_MANIFEST_TOL (1 << 2)
#define USB_DFU_WILL_DETACH (1 << 3)
uint16_t wDetachTimeOut;
uint16_t wTransferSize;
uint16_t bcdDFUVersion;
} __attribute__ ((packed));
#define USB_DT_DFU_SIZE 9
/* DFU class-specific requests (Section 3, DFU Rev 1.1) */
#define USB_REQ_DFU_DETACH 0x00
#define USB_REQ_DFU_DNLOAD 0x01
#define USB_REQ_DFU_UPLOAD 0x02
#define USB_REQ_DFU_GETSTATUS 0x03
#define USB_REQ_DFU_CLRSTATUS 0x04
#define USB_REQ_DFU_GETSTATE 0x05
#define USB_REQ_DFU_ABORT 0x06
struct dfu_status {
uint8_t bStatus;
uint8_t bwPollTimeout[3];
uint8_t bState;
uint8_t iString;
} __attribute__((packed));
#define DFU_STATUS_OK 0x00
#define DFU_STATUS_errTARGET 0x01
#define DFU_STATUS_errFILE 0x02
#define DFU_STATUS_errWRITE 0x03
#define DFU_STATUS_errERASE 0x04
#define DFU_STATUS_errCHECK_ERASED 0x05
#define DFU_STATUS_errPROG 0x06
#define DFU_STATUS_errVERIFY 0x07
#define DFU_STATUS_errADDRESS 0x08
#define DFU_STATUS_errNOTDONE 0x09
#define DFU_STATUS_errFIRMWARE 0x0a
#define DFU_STATUS_errVENDOR 0x0b
#define DFU_STATUS_errUSBR 0x0c
#define DFU_STATUS_errPOR 0x0d
#define DFU_STATUS_errUNKNOWN 0x0e
#define DFU_STATUS_errSTALLEDPKT 0x0f
enum dfu_state {
DFU_STATE_appIDLE = 0,
DFU_STATE_appDETACH = 1,
DFU_STATE_dfuIDLE = 2,
DFU_STATE_dfuDNLOAD_SYNC = 3,
DFU_STATE_dfuDNBUSY = 4,
DFU_STATE_dfuDNLOAD_IDLE = 5,
DFU_STATE_dfuMANIFEST_SYNC = 6,
DFU_STATE_dfuMANIFEST = 7,
DFU_STATE_dfuMANIFEST_WAIT_RST = 8,
DFU_STATE_dfuUPLOAD_IDLE = 9,
DFU_STATE_dfuERROR = 10,
};
#endif /* _USB_DFU_H */

View File

@@ -0,0 +1,49 @@
#include <usb/include/USBDescriptors.h>
#include <usb/device/dfu/dfu.h>
/* String 1 "SimTrace DFU Interface - Application Partition" */
const struct USBStringDescriptor USBDFU_string1 = {
.hdr = {
.bLength = sizeof(USBGenericDescriptor) + 46 * sizeof(unsigned short),
.bDescriptorType = USBGenericDescriptor_STRING,
},
.wData = { 0x0053, 0x0069, 0x006d, 0x0054, 0x0072, 0x0061,
0x0063, 0x0065, 0x0020, 0x0044, 0x0046, 0x0055,
0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072,
0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d,
0x0020, 0x0041, 0x0070, 0x0070, 0x006c, 0x0069,
0x0063, 0x0061, 0x0074, 0x0069, 0x006f, 0x006e,
0x0020, 0x0050, 0x0061, 0x0072, 0x0074, 0x0069,
0x0074, 0x0069, 0x006f, 0x006e, },
};
/* String 2 "SimTrace DFU Interface - Bootloader Partition" */
const struct USBStringDescriptor USBDFU_string2 = {
.hdr = {
.bLength = sizeof(USBGenericDescriptor) + 45 * sizeof(unsigned short),
.bDescriptorType = USBGenericDescriptor_STRING,
},
.wData = { 0x0053, 0x0069, 0x006d, 0x0054, 0x0072, 0x0061,
0x0063, 0x0065, 0x0020, 0x0044, 0x0046, 0x0055,
0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072,
0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d,
0x0020, 0x0042, 0x006f, 0x006f, 0x0074, 0x006c,
0x006f, 0x0061, 0x0064, 0x0065, 0x0072, 0x0020,
0x0050, 0x0061, 0x0072, 0x0074, 0x0069, 0x0074,
0x0069, 0x006f, 0x006e, },
};
/* String 3 "SimTrace DFU Interface - RAM" */
const struct USBStringDescriptor USBDFU_string3 = {
.hdr = {
.bLength = sizeof(USBGenericDescriptor) + 28 * sizeof(unsigned short),
.bDescriptorType = USBGenericDescriptor_STRING,
},
.wData = { 0x0053, 0x0069, 0x006d, 0x0054, 0x0072, 0x0061,
0x0063, 0x0065, 0x0020, 0x0044, 0x0046, 0x0055,
0x0020, 0x0049, 0x006e, 0x0074, 0x0065, 0x0072,
0x0066, 0x0061, 0x0063, 0x0065, 0x0020, 0x002d,
0x0020, 0x0052, 0x0041, 0x004d, },
};

View File

@@ -0,0 +1,131 @@
#ifndef _USB_DEV_DFU_H
#define _USB_DEV_DFU_H
#include <stdint.h>
#include <board.h>
#include <usb/include/USBDescriptors.h>
#include <usb/include/USBDDriver.h>
#if 0
/* This is valid for CCID */
#define CONFIG_DFU_NUM_APP_IF 1
#define CONFIG_DFU_NUM_APP_STR 4
#else
/* This is valid for CDC-Serial */
#define CONFIG_DFU_NUM_APP_IF 2
#define CONFIG_DFU_NUM_APP_STR 2
#endif
struct USBStringDescriptor {
USBGenericDescriptor hdr;
unsigned short wData[];
} __attribute__((packed));
#ifdef BOARD_USB_DFU
#include <usb/common/dfu/usb_dfu.h>
/* for board-specific config */
#include <board.h>
struct dfu_desc {
USBConfigurationDescriptor ucfg;
USBInterfaceDescriptor uif[BOARD_DFU_NUM_IF];
struct usb_dfu_func_descriptor func_dfu;
} __attribute__ ((packed));
/* USB DFU functional descriptor */
#define DFU_FUNC_DESC { \
.bLength = USB_DT_DFU_SIZE, \
.bDescriptorType = USB_DT_DFU, \
.bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD, \
.wDetachTimeOut = 0xff00, \
.wTransferSize = BOARD_DFU_PAGE_SIZE, \
.bcdDFUVersion = 0x0100, \
}
/* Number of DFU interface during runtime mode */
#define DFURT_NUM_IF 1
/* to be used by the runtime as part of its USB descriptor structure
* declaration */
#define DFURT_IF_DESCRIPTOR_STRUCT \
USBInterfaceDescriptor dfu_rt; \
struct usb_dfu_func_descriptor func_dfu;
/* to be used by the runtime as part of its USB Dsecriptor structure
* definition */
#define DFURT_IF_DESCRIPTOR(dfuIF, dfuSTR) \
.dfu_rt = { \
.bLength = sizeof(USBInterfaceDescriptor), \
.bDescriptorType = USBGenericDescriptor_INTERFACE, \
.bInterfaceNumber = dfuIF, \
.bAlternateSetting = 0, \
.bNumEndpoints = 0, \
.bInterfaceClass = 0xFE, \
.bInterfaceSubClass = 0x01, \
.bInterfaceProtocol = 0x01, \
.iInterface = dfuSTR, \
}, \
.func_dfu = DFU_FUNC_DESC \
/* provided by dfu_desc.c */
extern const struct dfu_desc dfu_cfg_descriptor;
extern const USBDDriverDescriptors dfu_descriptors;
#else /* BOARD_USB_DFU */
/* no DFU bootloader is being used */
#define DFURT_NUM_IF 0
#define DFURT_IF_DESCRIPTOR_STRUCT(a, b)
#define DFURT_IF_DESCRIPTOR
#endif /* BOARD_USB_DFU */
/* magic value we use during boot to detect if we should start in DFU
* mode or runtime mode */
#define USB_DFU_MAGIC 0xDFDFDFDF
/* The API between the core DFU handler and the board/soc specific code */
struct dfudata {
uint32_t magic;
uint8_t status;
uint32_t state;
int past_manifest;
unsigned int total_bytes;
};
/* RAM address for this magic value above */
extern struct dfudata _g_dfu;
extern struct dfudata *g_dfu;
void set_usb_serial_str(const uint8_t *serial_usbstr);
void DFURT_SwitchToDFU(void);
/* call-backs from DFU USB function driver to the board/SOC */
extern int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
uint8_t *data, unsigned int len);
extern int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
uint8_t *data, unsigned int req_len);
/* function to be called at end of EP0 handler during runtime */
void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request);
/* function to be called at end of EP0 handler during DFU mode */
void USBDFU_DFU_RequestHandler(const USBGenericRequest *request);
/* initialization of USB DFU driver (in DFU mode */
void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors);
/* USBD tells us to switch from DFU mode to application mode */
void USBDFU_SwitchToApp(void);
/* Return values to be used by USBDFU_handle_{dn,up}load */
#define DFU_RET_NOTHING 0
#define DFU_RET_ZLP 1
#define DFU_RET_STALL 2
#endif

View File

@@ -0,0 +1,214 @@
/* DFU related USB Descriptors */
/* (C) 2006-2017 Harald Welte <hwelte@hmw-consulting.de> */
#include <unistd.h>
#include "board.h"
#include "utils.h"
#include <usb/include/USBDescriptors.h>
#include <usb/include/USBDDriver.h>
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
enum {
STR_MANUF = 1,
STR_PROD,
STR_CONFIG,
_STR_FIRST_ALT,
STR_SERIAL = (_STR_FIRST_ALT+BOARD_DFU_NUM_IF),
};
static const USBDeviceDescriptor fsDevice = {
.bLength = sizeof(USBDeviceDescriptor),
.bDescriptorType = USBGenericDescriptor_DEVICE,
.bcdUSB = USBDeviceDescriptor_USB2_00,
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
.idVendor = BOARD_USB_VENDOR,
.idProduct = BOARD_USB_PRODUCT,
.bcdDevice = BOARD_USB_RELEASE,
.iManufacturer = STR_MANUF,
.iProduct = STR_PROD,
#ifdef BOARD_USB_SERIAL
.iSerialNumber = STR_SERIAL,
#else
.iSerialNumber = 0,
#endif
.bNumConfigurations = 1,
};
/* Alternate Interface Descriptor, we use one per partition/memory type */
#define DFU_IF(ALT) \
{ \
.bLength = sizeof(USBInterfaceDescriptor), \
.bDescriptorType = USBGenericDescriptor_INTERFACE, \
.bInterfaceNumber = 0, \
.bAlternateSetting = ALT, \
.bNumEndpoints = 0, \
.bInterfaceClass = 0xfe, \
.bInterfaceSubClass = 1, \
.iInterface = (_STR_FIRST_ALT+ALT), \
.bInterfaceProtocol = 2, \
}
/* overall descriptor for the DFU configuration, including all
* descriptors for alternate interfaces */
const struct dfu_desc dfu_cfg_descriptor = {
.ucfg = {
.bLength = sizeof(USBConfigurationDescriptor),
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
.wTotalLength = sizeof(struct dfu_desc),
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = STR_CONFIG,
.bmAttributes = BOARD_USB_BMATTRIBUTES,
.bMaxPower = 100,
},
.uif[0] = DFU_IF(0),
#if BOARD_DFU_NUM_IF > 1
.uif[1] = DFU_IF(1),
#endif
#if BOARD_DFU_NUM_IF > 2
.uif[2] = DFU_IF(2),
#endif
#if BOARD_DFU_NUM_IF > 3
.uif[3] = DFU_IF(3),
#endif
#if BOARD_DFU_NUM_IF > 4
.uif[4] = DFU_IF(4),
#endif
.func_dfu = DFU_FUNC_DESC
};
#if 0
#include "usb_strings.h"
static const unsigned char *usb_strings[] = {
USB_STRINGS_GENERATED
#ifdef BOARD_USB_SERIAL
NULL
#endif
};
void set_usb_serial_str(const uint8_t *serial_usbstr)
{
usb_strings[STR_SERIAL] = serial_usbstr;
}
#else
static const unsigned char langDesc[] = {
USBStringDescriptor_LENGTH(1),
USBGenericDescriptor_STRING,
USBStringDescriptor_ENGLISH_US
};
static const unsigned char manufStringDescriptor[] = {
USBStringDescriptor_LENGTH(24),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('s'),
USBStringDescriptor_UNICODE('y'),
USBStringDescriptor_UNICODE('s'),
USBStringDescriptor_UNICODE('m'),
USBStringDescriptor_UNICODE('o'),
USBStringDescriptor_UNICODE('c'),
USBStringDescriptor_UNICODE('o'),
USBStringDescriptor_UNICODE('m'),
USBStringDescriptor_UNICODE(' '),
USBStringDescriptor_UNICODE('-'),
USBStringDescriptor_UNICODE(' '),
USBStringDescriptor_UNICODE('s'),
USBStringDescriptor_UNICODE('.'),
USBStringDescriptor_UNICODE('f'),
USBStringDescriptor_UNICODE('.'),
USBStringDescriptor_UNICODE('m'),
USBStringDescriptor_UNICODE('.'),
USBStringDescriptor_UNICODE('c'),
USBStringDescriptor_UNICODE('.'),
USBStringDescriptor_UNICODE(' '),
USBStringDescriptor_UNICODE('G'),
USBStringDescriptor_UNICODE('m'),
USBStringDescriptor_UNICODE('b'),
USBStringDescriptor_UNICODE('H'),
};
static const unsigned char productStringDescriptor[] = {
USBStringDescriptor_LENGTH(10),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('S'),
USBStringDescriptor_UNICODE('I'),
USBStringDescriptor_UNICODE('M'),
USBStringDescriptor_UNICODE('t'),
USBStringDescriptor_UNICODE('r'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('c'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE(' '),
USBStringDescriptor_UNICODE('2'),
};
static const unsigned char configStringDescriptor[] = {
USBStringDescriptor_LENGTH(3),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('D'),
USBStringDescriptor_UNICODE('F'),
USBStringDescriptor_UNICODE('U'),
};
static const unsigned char altRamStringDescriptor[] = {
USBStringDescriptor_LENGTH(3),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('R'),
USBStringDescriptor_UNICODE('A'),
USBStringDescriptor_UNICODE('M'),
};
static const unsigned char altAppStringDescriptor[] = {
USBStringDescriptor_LENGTH(11),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('F'),
USBStringDescriptor_UNICODE('l'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('s'),
USBStringDescriptor_UNICODE('h'),
USBStringDescriptor_UNICODE(' '),
USBStringDescriptor_UNICODE('('),
USBStringDescriptor_UNICODE('A'),
USBStringDescriptor_UNICODE('p'),
USBStringDescriptor_UNICODE('p'),
USBStringDescriptor_UNICODE(')'),
};
/** List of string descriptors used by the device */
static const unsigned char *usb_strings[] = {
langDesc,
[STR_MANUF] = manufStringDescriptor,
[STR_PROD] = productStringDescriptor,
[STR_CONFIG] = configStringDescriptor,
[_STR_FIRST_ALT] = altRamStringDescriptor,
[_STR_FIRST_ALT+1] = altAppStringDescriptor,
};
#endif
static const USBConfigurationDescriptor *conf_desc_arr[] = {
&dfu_cfg_descriptor.ucfg,
};
const USBDDriverDescriptors dfu_descriptors = {
.pFsDevice = &fsDevice,
.pFsConfiguration = (const USBConfigurationDescriptor **)&conf_desc_arr,
/* DFU only supports FS for now */
.pFsQualifier = NULL,
.pFsOtherSpeed = NULL,
.pHsDevice = NULL,
.pHsConfiguration = NULL,
.pHsQualifier = NULL,
.pHsOtherSpeed = NULL,
.pStrings = usb_strings,
.numStrings = ARRAY_SIZE(usb_strings),
};

View File

@@ -0,0 +1,478 @@
/* USB Device Firmware Update Implementation for OpenPCD, OpenPICC SIMtrace
* (C) 2006-2017 by Harald Welte <hwelte@hmw-consulting.de>
*
* This ought to be compliant to the USB DFU Spec 1.0 as available from
* http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <unistd.h>
#include <board.h>
#include <core_cm3.h>
#include "trace.h"
#include <usb/include/USBDescriptors.h>
#include <usb/include/USBRequests.h>
#include <usb/include/USBD.h>
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
/* FIXME: this was used for a special ELF section which then got called
* by DFU code and Application code, across flash partitions */
#define __dfudata __attribute__ ((section (".dfudata")))
#define __dfufunc
/// Standard device driver instance.
static USBDDriver usbdDriver;
static unsigned char if_altsettings[1];
__dfudata struct dfudata _g_dfu = {
.state = DFU_STATE_appIDLE,
.past_manifest = 0,
.total_bytes = 0,
};
struct dfudata *g_dfu = &_g_dfu;
WEAK void dfu_drv_updstatus(void)
{
TRACE_INFO("DFU: updstatus()\n\r");
/* we transition immediately from MANIFEST_SYNC to MANIFEST,
* as the flash-writing is not asynchronous in this
* implementation */
if (g_dfu->state == DFU_STATE_dfuMANIFEST_SYNC)
g_dfu->state = DFU_STATE_dfuMANIFEST;
}
static __dfufunc void handle_getstatus(void)
{
/* has to be static as USBD_Write is async ? */
static struct dfu_status dstat;
static const uint8_t poll_timeout_10ms[] = { 10, 0, 0 };
dfu_drv_updstatus();
/* send status response */
dstat.bStatus = g_dfu->status;
dstat.bState = g_dfu->state;
dstat.iString = 0;
memcpy(&dstat.bwPollTimeout, poll_timeout_10ms, sizeof(dstat.bwPollTimeout));
TRACE_DEBUG("handle_getstatus(%u, %u)\n\r", dstat.bStatus, dstat.bState);
USBD_Write(0, (char *)&dstat, sizeof(dstat), NULL, 0);
}
static void __dfufunc handle_getstate(void)
{
uint8_t u8 = g_dfu->state;
TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu->state);
USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0);
}
static void TerminateCtrlInWithNull(void *pArg,
unsigned char status,
unsigned long int transferred,
unsigned long int remaining)
{
USBD_Write(0, // Endpoint #0
0, // No data buffer
0, // No data buffer
(TransferCallback) 0,
(void *) 0);
}
static uint8_t dfu_buf[BOARD_DFU_PAGE_SIZE];
/* download of a single page has completed */
static void dnload_cb(void *arg, unsigned char status, unsigned long int transferred,
unsigned long int remaining)
{
int rc;
TRACE_DEBUG("COMPLETE\n\r");
if (status != USBD_STATUS_SUCCESS) {
TRACE_ERROR("USBD download callback status %d\n\r", status);
USBD_Stall(0);
return;
}
rc = USBDFU_handle_dnload(if_altsettings[0], g_dfu->total_bytes, dfu_buf, transferred);
switch (rc) {
case DFU_RET_ZLP:
g_dfu->total_bytes += transferred;
g_dfu->state = DFU_STATE_dfuDNLOAD_IDLE;
TerminateCtrlInWithNull(0,0,0,0);
break;
case DFU_RET_STALL:
g_dfu->state = DFU_STATE_dfuERROR;
USBD_Stall(0);
break;
case DFU_RET_NOTHING:
break;
}
}
static int handle_dnload(uint16_t val, uint16_t len, int first)
{
int rc;
if (len > BOARD_DFU_PAGE_SIZE) {
TRACE_ERROR("DFU length exceeds flash page size\n\r");
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL;
}
if (len & 0x03) {
TRACE_ERROR("DFU length not four-byte-aligned\n\r");
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL;
}
if (first)
g_dfu->total_bytes = 0;
if (len == 0) {
TRACE_DEBUG("zero-size write -> MANIFEST_SYNC\n\r");
g_dfu->state = DFU_STATE_dfuMANIFEST_SYNC;
return DFU_RET_ZLP;
}
/* else: actually read data */
rc = USBD_Read(0, dfu_buf, len, &dnload_cb, 0);
if (rc == USBD_STATUS_SUCCESS)
return DFU_RET_NOTHING;
else
return DFU_RET_STALL;
}
/* upload of a single page has completed */
static void upload_cb(void *arg, unsigned char status, unsigned long int transferred,
unsigned long int remaining)
{
int rc;
TRACE_DEBUG("COMPLETE\n\r");
if (status != USBD_STATUS_SUCCESS) {
TRACE_ERROR("USBD upload callback status %d\n\r", status);
USBD_Stall(0);
return;
}
g_dfu->total_bytes += transferred;
}
static int handle_upload(uint16_t val, uint16_t len, int first)
{
int rc;
if (first)
g_dfu->total_bytes = 0;
if (len > BOARD_DFU_PAGE_SIZE) {
TRACE_ERROR("DFU length exceeds flash page size\n\r");
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL;
}
rc = USBDFU_handle_upload(if_altsettings[0], g_dfu->total_bytes, dfu_buf, len);
if (rc < 0) {
TRACE_ERROR("application handle_upload() returned %d\n\r", rc);
return DFU_RET_STALL;
}
if (USBD_Write(0, dfu_buf, rc, &upload_cb, 0) == USBD_STATUS_SUCCESS)
return rc;
return DFU_RET_STALL;
}
/* this function gets daisy-chained into processing EP0 requests */
void USBDFU_DFU_RequestHandler(const USBGenericRequest *request)
{
uint8_t req = USBGenericRequest_GetRequest(request);
uint16_t len = USBGenericRequest_GetLength(request);
uint16_t val = USBGenericRequest_GetValue(request);
int rc, ret;
TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r",
USBGenericRequest_GetType(request),
USBGenericRequest_GetRecipient(request),
val, len);
/* check for GET_DESCRIPTOR on DFU */
if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD &&
USBGenericRequest_GetRecipient(request) == USBGenericRequest_DEVICE &&
USBGenericRequest_GetRequest(request) == USBGenericRequest_GETDESCRIPTOR &&
USBGetDescriptorRequest_GetDescriptorType(request) == USB_DT_DFU) {
uint16_t length = sizeof(struct usb_dfu_func_descriptor);
const USBDeviceDescriptor *pDevice;
int terminateWithNull;
if (USBD_IsHighSpeed())
pDevice = usbdDriver.pDescriptors->pHsDevice;
else
pDevice = usbdDriver.pDescriptors->pFsDevice;
terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
USBD_Write(0, &dfu_cfg_descriptor.func_dfu, length,
terminateWithNull ? TerminateCtrlInWithNull : 0, 0);
return;
}
/* forward all non-DFU specific messages to core handler*/
if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS ||
USBGenericRequest_GetRecipient(request) != USBGenericRequest_INTERFACE) {
TRACE_DEBUG("std_ho_usbd ");
USBDDriver_RequestHandler(&usbdDriver, request);
return;
}
switch (g_dfu->state) {
case DFU_STATE_appIDLE:
case DFU_STATE_appDETACH:
TRACE_ERROR("Invalid DFU State reached in DFU mode\r\n");
ret = DFU_RET_STALL;
break;
case DFU_STATE_dfuIDLE:
switch (req) {
case USB_REQ_DFU_DNLOAD:
if (len == 0) {
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
goto out;
}
g_dfu->state = DFU_STATE_dfuDNLOAD_SYNC;
ret = handle_dnload(val, len, 1);
break;
case USB_REQ_DFU_UPLOAD:
g_dfu->state = DFU_STATE_dfuUPLOAD_IDLE;
handle_upload(val, len, 1);
break;
case USB_REQ_DFU_ABORT:
/* no zlp? */
ret = DFU_RET_ZLP;
break;
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
goto out;
break;
}
break;
case DFU_STATE_dfuDNLOAD_SYNC:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
/* FIXME: state transition depending on block completeness */
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
goto out;
}
break;
case DFU_STATE_dfuDNBUSY:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
/* FIXME: only accept getstatus if bwPollTimeout
* has elapsed */
handle_getstatus();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
goto out;
}
break;
case DFU_STATE_dfuDNLOAD_IDLE:
switch (req) {
case USB_REQ_DFU_DNLOAD:
g_dfu->state = DFU_STATE_dfuDNLOAD_SYNC;
ret = handle_dnload(val, len, 0);
break;
case USB_REQ_DFU_ABORT:
g_dfu->state = DFU_STATE_dfuIDLE;
ret = DFU_RET_ZLP;
break;
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
break;
}
break;
case DFU_STATE_dfuMANIFEST_SYNC:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
break;
}
break;
case DFU_STATE_dfuMANIFEST:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
/* we don't want to change to WAIT_RST, as it
* would mean that we can not support another
* DFU transaction before doing the actual
* reset. Instead, we switch to idle and note
* that we've already been through MANIFST in
* the global variable 'past_manifest'.
*/
//g_dfu->state = DFU_STATE_dfuMANIFEST_WAIT_RST;
g_dfu->state = DFU_STATE_dfuIDLE;
g_dfu->past_manifest = 1;
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
break;
}
break;
case DFU_STATE_dfuMANIFEST_WAIT_RST:
/* we should never go here */
break;
case DFU_STATE_dfuUPLOAD_IDLE:
switch (req) {
case USB_REQ_DFU_UPLOAD:
/* state transition if less data then requested */
rc = handle_upload(val, len, 0);
if (rc >= 0 && rc < len)
g_dfu->state = DFU_STATE_dfuIDLE;
break;
case USB_REQ_DFU_ABORT:
g_dfu->state = DFU_STATE_dfuIDLE;
/* no zlp? */
ret = DFU_RET_ZLP;
break;
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
break;
}
break;
case DFU_STATE_dfuERROR:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
case USB_REQ_DFU_CLRSTATUS:
g_dfu->state = DFU_STATE_dfuIDLE;
g_dfu->status = DFU_STATUS_OK;
/* no zlp? */
ret = DFU_RET_ZLP;
break;
default:
g_dfu->state = DFU_STATE_dfuERROR;
ret = DFU_RET_STALL;
break;
}
break;
}
out:
switch (ret) {
case DFU_RET_NOTHING:
break;
case DFU_RET_ZLP:
USBD_Write(0, 0, 0, 0, 0);
break;
case DFU_RET_STALL:
USBD_Stall(0);
break;
}
}
/* we assume the caller has enabled the required clock/PLL for USB */
void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors)
{
/* We already start in DFU idle mode */
g_dfu->state = DFU_STATE_dfuIDLE;
USBDDriver_Initialize(&usbdDriver, pDescriptors, if_altsettings);
USBD_Init();
USBD_Connect();
//USBD_ConfigureSpeed(1);
NVIC_EnableIRQ(UDP_IRQn);
}
void USBDFU_SwitchToApp(void)
{
/* make sure the MAGIC is not set to enter DFU again */
g_dfu->magic = 0;
printf("switching to app\r\n");
/* disconnect from USB to ensure re-enumeration */
USBD_Disconnect();
/* disable any interrupts during transition */
__disable_irq();
/* Tell the hybrid to execute FTL JUMP! */
NVIC_SystemReset();
}
void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
{
USBDFU_DFU_RequestHandler(request);
}

View File

@@ -0,0 +1,200 @@
/* DFU related functions that are active at runtime, i.e. during the
* normal operation of the device firmware, *not* during DFU update mode
* (C) 2006 Harald Welte <hwelte@hmw-consulting.de>
*
* This ought to be compliant to the USB DFU Spec 1.0 as available from
* http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <board.h>
#include <core_cm3.h>
#include <usb/include/USBD.h>
#include <usb/device/dfu/dfu.h>
#include "trace.h"
#include <usb/include/USBDescriptors.h>
#include <usb/include/USBRequests.h>
#include <usb/include/USBD.h>
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
struct dfudata *g_dfu = (struct dfudata *) IRAM_ADDR;
/* FIXME: this was used for a special ELF section which then got called
* by DFU code and Application code, across flash partitions */
#define __dfufunc
static __dfufunc void handle_getstatus(void)
{
/* has to be static as USBD_Write is async ? */
static struct dfu_status dstat;
static const uint8_t poll_timeout_10ms[] = { 10, 0, 0 };
/* send status response */
dstat.bStatus = g_dfu->status;
dstat.bState = g_dfu->state;
dstat.iString = 0;
memcpy(&dstat.bwPollTimeout, poll_timeout_10ms, sizeof(dstat.bwPollTimeout));
TRACE_DEBUG("handle_getstatus(%u, %u)\n\r", dstat.bStatus, dstat.bState);
USBD_Write(0, (char *)&dstat, sizeof(dstat), NULL, 0);
}
static void __dfufunc handle_getstate(void)
{
uint8_t u8 = g_dfu->state;
TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu->state);
USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0);
}
static void TerminateCtrlInWithNull(void *pArg,
unsigned char status,
unsigned long int transferred,
unsigned long int remaining)
{
USBD_Write(0, // Endpoint #0
0, // No data buffer
0, // No data buffer
(TransferCallback) 0,
(void *) 0);
}
/* this function gets daisy-chained into processing EP0 requests */
void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request)
{
USBDDriver *usbdDriver = USBD_GetDriver();
uint8_t req = USBGenericRequest_GetRequest(request);
uint16_t len = USBGenericRequest_GetLength(request);
uint16_t val = USBGenericRequest_GetValue(request);
int rc, ret;
TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r",
USBGenericRequest_GetType(request),
USBGenericRequest_GetRecipient(request),
val, len);
/* check for GET_DESCRIPTOR on DFU */
if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD &&
USBGenericRequest_GetRecipient(request) == USBGenericRequest_DEVICE &&
USBGenericRequest_GetRequest(request) == USBGenericRequest_GETDESCRIPTOR &&
USBGetDescriptorRequest_GetDescriptorType(request) == USB_DT_DFU) {
uint16_t length = sizeof(struct usb_dfu_func_descriptor);
const USBDeviceDescriptor *pDevice;
int terminateWithNull;
if (USBD_IsHighSpeed())
pDevice = usbdDriver->pDescriptors->pHsDevice;
else
pDevice = usbdDriver->pDescriptors->pFsDevice;
terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
USBD_Write(0, &dfu_cfg_descriptor.func_dfu, length,
terminateWithNull ? TerminateCtrlInWithNull : 0, 0);
return;
}
/* forward all non-DFU specific messages to core handler*/
if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS ||
USBGenericRequest_GetRecipient(request) != USBGenericRequest_INTERFACE) {
TRACE_DEBUG("std_ho_usbd ");
USBDDriver_RequestHandler(usbdDriver, request);
return;
}
switch (g_dfu->state) {
case DFU_STATE_appIDLE:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
case USB_REQ_DFU_DETACH:
/* we switch it DETACH state, send a ZLP and
* return. The next USB reset in this state
* will then trigger DFURT_SwitchToDFU() below */
TRACE_DEBUG("\r\n====dfu_detach\n\r");
g_dfu->state = DFU_STATE_appDETACH;
ret = DFU_RET_ZLP;
goto out;
break;
default:
ret = DFU_RET_STALL;
}
break;
case DFU_STATE_appDETACH:
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
default:
g_dfu->state = DFU_STATE_appIDLE;
ret = DFU_RET_STALL;
goto out;
break;
}
/* FIXME: implement timer to return to appIDLE */
break;
default:
TRACE_ERROR("Invalid DFU State reached in Runtime Mode\r\n");
ret = DFU_RET_STALL;
break;
}
out:
switch (ret) {
case DFU_RET_NOTHING:
break;
case DFU_RET_ZLP:
USBD_Write(0, 0, 0, 0, 0);
break;
case DFU_RET_STALL:
USBD_Stall(0);
break;
}
}
void DFURT_SwitchToDFU(void)
{
/* store the magic value that the DFU loader can detect and
* activate itself, rather than boot into the application */
g_dfu->magic = USB_DFU_MAGIC;
/* Disconnect the USB by remoting the pull-up */
USBD_Disconnect();
__disable_irq();
/* reset the processor, we will start execution with the
* ResetVector of the bootloader */
NVIC_SystemReset();
}
void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
{
/* FIXME: integration with CCID control point reqeusts */
USBDFU_Runtime_RequestHandler(request);
}

View File

@@ -24,6 +24,7 @@
#include "stdlib.h" #include "stdlib.h"
#include "string.h" #include "string.h"
#include "inttypes.h" #include "inttypes.h"
#include "syscalls.h"
#define MIN(a, b) ((a < b) ? a : b) #define MIN(a, b) ((a < b) ? a : b)
@@ -36,7 +37,6 @@
/** Core definition */ /** Core definition */
#define cortexm3 #define cortexm3
#define BOARD_MAINOSC 18432000
#define BOARD_MCK 48000000 #define BOARD_MCK 48000000
#define LED_RED PIO_PA17 #define LED_RED PIO_PA17
@@ -64,7 +64,7 @@
/** UART0 */ /** UART0 */
/** Console baudrate always using 115200. */ /** Console baudrate always using 115200. */
#define CONSOLE_BAUDRATE 230400 #define CONSOLE_BAUDRATE 115200
/** Usart Hw interface used by the console (UART0). */ /** Usart Hw interface used by the console (UART0). */
#define CONSOLE_USART UART0 #define CONSOLE_USART UART0
/** Usart Hw ID used by the console (UART0). */ /** Usart Hw ID used by the console (UART0). */
@@ -107,4 +107,16 @@
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP #define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
//#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_RWAKEUP //#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_RWAKEUP
#define BOARD_USB_VENDOR SIMTRACE_VENDOR_ID
#define BOARD_USB_PRODUCT SIMTRACE_PRODUCT_ID
#define BOARD_USB_RELEASE 0
#define BOARD_USB_DFU
#define BOARD_DFU_BOOT_SIZE (16 * 1024)
#define BOARD_DFU_RAM_SIZE (2 * 1024)
#define BOARD_DFU_PAGE_SIZE 512
#define BOARD_DFU_NUM_IF 2
extern void board_exec_dbg_cmd(int ch);
extern void board_main_top(void);
#endif #endif

View File

@@ -0,0 +1,3 @@
#pragma once
int get_board_version_adc(void);

View File

@@ -0,0 +1,10 @@
#ifndef _MANIFEST_H
#define _MANIFEST_H
extern const char *manifest_application;
extern const char *manifest_revision;
extern const char *manifest_board;
extern const char *manifest_environment;
#endif /* !_MANIFEST_H */

View File

@@ -0,0 +1,142 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal FLASH on the ATSAM3S1
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00010000 /* Flash, 64K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 /* sram, 16K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
/* we must make sure the .dfudata is linked to start of RAM */
*(.dfudata .dfudata.*);
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,140 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the ATSAM3S1
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00010000 /* Flash, 64K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 /* sram, 16K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > ram
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > ram
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,91 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the AT91SAM3S1
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(entry)
/* Memory Spaces Definitions */
MEMORY
{
romcodesram (W!RX) : ORIGIN = 0x20000000, LENGTH = 0x0800
sram (W!RX) : ORIGIN = 0x20000800, LENGTH = 0x00003800 /* sram, 16K - sizeof(romcodesram) */
}
/* Entry point */
/*ENTRY (ResetException)*/
SECTIONS
{
/* startup code in the .isr_vector */
.text :
{
. = ALIGN(4);
_stext = .;
KEEP(*(.isr_vector .isr_vector.*))
*(.mailbox)
*(.text .text.*)
*(.rodata .rodata.*)
*(.glue_7)
*(.glue_7t)
*(.gcc_except_table)
*(.rodata .rodata*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
_etext = .;
} > sram
/* data */
.data :
{
. = ALIGN(4);
_sidata = .;
_sdata = .;
*(.data)
*(.data.*)
. = ALIGN(4);
_edata = .;
} > sram
.bss (NOLOAD) : {
_szero = .;
*(.bss)
. = ALIGN(4);
_ezero = .;
} >sram
/* Stack in SRAM */
_sstack = 0x20003FFC;
}
end = .;

View File

@@ -0,0 +1,142 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal FLASH on the ATSAM3S2
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00020000 /* flash, 128K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* sram, 32K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
/* we must make sure the .dfudata is linked to start of RAM */
*(.dfudata .dfudata.*);
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,140 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the ATSAM3S2
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT ("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00020000 /* flash, 128K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* sram, 32K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > ram
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > ram
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,91 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the AT91SAM3S2
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(entry)
/* Memory Spaces Definitions */
MEMORY
{
romcodesram (W!RX) : ORIGIN = 0x20000000, LENGTH = 0x0800
sram (W!RX) : ORIGIN = 0x20000800, LENGTH = 0x00007800 /* sram, 32K - sizeof(romcodesram) */
}
/* Entry point */
/*ENTRY (ResetException)*/
SECTIONS
{
/* startup code in the .isr_vector */
.text :
{
. = ALIGN(4);
_stext = .;
KEEP(*(.isr_vector .isr_vector.*))
*(.mailbox)
*(.text .text.*)
*(.rodata .rodata.*)
*(.glue_7)
*(.glue_7t)
*(.gcc_except_table)
*(.rodata .rodata*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
_etext = .;
} > sram
/* data */
.data :
{
. = ALIGN(4);
_sidata = .;
_sdata = .;
*(.data)
*(.data.*)
. = ALIGN(4);
_edata = .;
} > sram
.bss (NOLOAD) : {
_szero = .;
*(.bss)
. = ALIGN(4);
_ezero = .;
} >sram
/* Stack in SRAM */
_sstack = 0x20007FFC;
}
end = .;

View File

@@ -0,0 +1,142 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal FLASH on the ATSAM3S4
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
/* reserve the first 16k (= 0x4000) for the DFU bootloader */
rom (rx) : ORIGIN = 0x00404000, LENGTH = 0x0003c000 /* flash, 256K */
/* reserve the first 32 (= 0x20) bytes for the _g_dfu struct */
ram (rwx) : ORIGIN = 0x20000020, LENGTH = 0x0000bfe0 /* sram, 48K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
. = ALIGN(4);
_end = . ;
}

View File

@@ -34,15 +34,12 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm) OUTPUT_ARCH(arm)
SEARCH_DIR(.) SEARCH_DIR(.)
ENTRY(main)
/* Memory Spaces Definitions */ /* Memory Spaces Definitions */
MEMORY MEMORY
{ {
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00020000 /* flash, 256K */ rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00040000 /* flash, 256K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* sram, 48K */ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000 /* sram, 48K */
/* rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00040000 /* flash, 256K */
/*ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000 /* sram, 48K */
} }
/* Section Definitions */ /* Section Definitions */
@@ -112,6 +109,8 @@ SECTIONS
{ {
. = ALIGN(4); . = ALIGN(4);
_srelocate = .; _srelocate = .;
/* we must make sure the .dfudata is linked to start of RAM */
*(.dfudata .dfudata.*);
*(.ramfunc .ramfunc.*); *(.ramfunc .ramfunc.*);
*(.data .data.*); *(.data .data.*);
. = ALIGN(4); . = ALIGN(4);

View File

@@ -0,0 +1,140 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the ATSAM3S4
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00040000 /* flash, 256K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000 /* sram, 48K */
}
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > ram
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack .stack.*)
} > ram
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > ram
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_end = . ;
}

View File

@@ -0,0 +1,91 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the AT91SAM3S4
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(entry)
/* Memory Spaces Definitions */
MEMORY
{
romcodesram (W!RX) : ORIGIN = 0x20000000, LENGTH = 0x01000
sram (W!RX) : ORIGIN = 0x20001000, LENGTH = 0x0000B000 /* sram, 48K - sizeof(romcodesram) */
}
/* Entry point */
/*ENTRY (ResetException)*/
SECTIONS
{
/* startup code in the .isr_vector */
.text :
{
. = ALIGN(4);
_stext = .;
KEEP(*(.isr_vector .isr_vector.*))
*(.mailbox)
*(.text .text.*)
*(.rodata .rodata.*)
*(.glue_7)
*(.glue_7t)
*(.gcc_except_table)
*(.rodata .rodata*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
_etext = .;
} > sram
/* data */
.data :
{
. = ALIGN(4);
_sidata = .;
_sdata = .;
*(.data)
*(.data.*)
. = ALIGN(4);
_edata = .;
} > sram
.bss (NOLOAD) : {
_szero = .;
*(.bss)
. = ALIGN(4);
_ezero = .;
} >sram
/* Stack in SRAM */
_sstack = 0x2000BFFC;
}
end = .;

View File

@@ -0,0 +1,31 @@
#*******************************************************
#
# Connect to J-Link and debug application in flash.
#
# define 'reset' command
define reset
# Connect to the J-Link gdb server
target remote localhost:2331
# Reset the chip to get to a known state
monitor reset
# Select flash device
monitor flash device = AT91SAM3S4C
# Enable flash download and flash breakpoints
monitor flash download = 1
# Load the program
load
# Reset peripheral (RSTC_CR)
set *0x400e1400 = 0xA5000004
# Initializing PC and stack pointer
mon reg sp=(0x400000)
set *0x400004 = *0x400004 & 0xFFFFFFFE
mon reg pc=(0x400004)
info reg
# end of 'reset' command
end

View File

@@ -0,0 +1,27 @@
#*************************************************
#
# Connect to J-Link and debug application in sram on SAM3S
#
# Note:
# First, users should modify Step1 and Step2 according to their project,
# then do Step3.
# Step1: Connect to the J-Link gdb server
define reset
target remote localhost:2331
monitor reset
# Step2: Load file(eg. getting-started project)
load
# Step3: Reset peripheral (RSTC_CR)
set *0x400e1400 = 0xA5000004
# Step4: Initializing PC and stack pointer
# Modify pc value to even before writing pc register
mon reg sp=(0x20000000)
set *0x20000004 = *0x20000004 & 0xFFFFFFFE
mon reg pc=(0x20000004)
info reg
end

View File

@@ -0,0 +1,27 @@
#*************************************************
#
# Connect to J-Link and debug application in sram on SAM3S
#
# Note:
# First, users should modify Step1 and Step2 according to their project,
# then do Step3.
# Step1: Connect to the J-Link gdb server
define reset
target remote localhost:2331
monitor reset
# Step2: Load file(eg. getting-started project)
load
# Step3: Reset peripheral (RSTC_CR)
set *0x400e1400 = 0xA5000004
# Step4: Initializing PC and stack pointer
# Modify pc value to even before writing pc register
mon reg sp=(0x20000000)
set *0x20000004 = *0x20000004 & 0xFFFFFFFE
mon reg pc=(0x20000004)
info reg
end

View File

@@ -61,7 +61,6 @@ extern uint32_t _ezero;
extern int main( void ) ; extern int main( void ) ;
/** \endcond */ /** \endcond */
void ResetException( void ) ; void ResetException( void ) ;
extern void __libc_init_array( void ) ;
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Exception Table * Exception Table
@@ -125,6 +124,23 @@ IntFunc exception_table[] = {
IrqHandlerNotUsed /* 35 not used */ IrqHandlerNotUsed /* 35 not used */
}; };
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
#include "usb/device/dfu/dfu.h"
static void BootIntoApp(void)
{
unsigned int *pSrc;
void (*appReset)(void);
pSrc = (unsigned int *) ((unsigned char *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE);
SCB->VTOR = ((unsigned int)(pSrc)) | (0x0 << 7);
appReset = pSrc[1];
g_dfu->state = DFU_STATE_appIDLE;
appReset();
}
#endif
/** /**
* \brief This is the code that gets called on processor reset. * \brief This is the code that gets called on processor reset.
* To initialize the device, and call the main() routine. * To initialize the device, and call the main() routine.
@@ -136,6 +152,18 @@ void ResetException( void )
/* Low level Initialize */ /* Low level Initialize */
LowLevelInit() ; LowLevelInit() ;
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
/* we are before the text segment has been relocated, so g_dfu is
* not initialized yet */
g_dfu = &_g_dfu;
if (g_dfu->magic != USB_DFU_MAGIC) {
BootIntoApp();
/* Infinite loop */
while ( 1 ) ;
}
#endif
/* Initialize the relocate segment */ /* Initialize the relocate segment */
pSrc = &_etext ; pSrc = &_etext ;
pDest = &_srelocate ; pDest = &_srelocate ;
@@ -163,8 +191,8 @@ void ResetException( void )
SCB->VTOR |= 1 << SCB_VTOR_TBLBASE_Pos ; SCB->VTOR |= 1 << SCB_VTOR_TBLBASE_Pos ;
} }
/* Initialize the C library */ /* App should have disabled interrupts during the transition */
__libc_init_array() ; __enable_irq();
/* Branch to main function */ /* Branch to main function */
main() ; main() ;

View File

@@ -43,31 +43,69 @@
* Local definitions * Local definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/* Clock settings at 48MHz for 18 MHz crystal */ #define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)
#if (BOARD_MCK == 48000000) #if (BOARD_MCK == 48000000)
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8)) #if (BOARD_MAINOSC == 18432000)
/* Clock settings at 48MHz for 18 MHz crystal */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(0xc) \ | CKGR_PLLAR_MULA(13-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(0x5)) | CKGR_PLLAR_DIVA(5))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK) #elif (BOARD_MAINOSC == 12000000)
/* QMod has 12 MHz clock, so multply by 8 (96 MHz) and divide by 2 */
/* Clock settings at 64MHz for 18 MHz crystal */
#elif (BOARD_MCK == 64000000)
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(0x06) \ | CKGR_PLLAR_MULA(8-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(0x2)) | CKGR_PLLAR_DIVA(2))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)
#else #else
#error "No settings for current BOARD_MCK." #error "Please define PLLA config for your MAINOSC frequency"
#endif /* MAINOSC */
#elif (BOARD_MCK == 64000000)
#if (BOARD_MAINOSC == 18432000)
/* Clock settings at 64MHz for 18 MHz crystal: 64.512 MHz */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(7-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2))
#elif (BOARD_MAINOSC == 12000000)
/* QMod has 12 MHz clock, so multply by 10 / div by 2: 60 MHz */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(10-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2))
#error "Please define PLLA config for your MAINOSC frequency"
#endif /* MAINOSC */
#else
#error "No PLL settings for current BOARD_MCK."
#endif
#if (BOARD_MAINOSC == 12000000)
#define PLLB_CFG (CKGR_PLLBR_DIVB(2)|CKGR_PLLBR_MULB(8-1)|CKGR_PLLBR_PLLBCOUNT_Msk)
#elif (BOARD_MAINOSC == 18432000)
#define PLLB_CFG (CKGR_PLLBR_DIVB(5)|CKGR_PLLBR_MULB(13-1)|CKGR_PLLBR_PLLBCOUNT_Msk)
#else
#error "Please configure PLLB for your MAINOSC freq"
#endif #endif
/* Define clock timeout */ /* Define clock timeout */
#define CLOCK_TIMEOUT 0xFFFFFFFF #define CLOCK_TIMEOUT 0xFFFFFFFF
/**
* \brief Configure 48MHz Clock for USB
*/
static void _ConfigureUsbClock(void)
{
/* Enable PLLB for USB */
PMC->CKGR_PLLBR = PLLB_CFG;
while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0) ;
/* USB Clock uses PLLB */
PMC->PMC_USB = PMC_USB_USBDIV(0) /* /1 (no divider) */
| PMC_USB_USBS; /* PLLB */
}
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
@@ -98,6 +136,7 @@ extern WEAK void LowLevelInit( void )
} }
*/ */
#ifndef qmod
/* Initialize main oscillator */ /* Initialize main oscillator */
if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
{ {
@@ -114,6 +153,13 @@ extern WEAK void LowLevelInit( void )
/* wait for Main XTAL oscillator stabilization */ /* wait for Main XTAL oscillator stabilization */
timeout = 0; timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT)); while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT));
#else
/* QMOD has external 12MHz clock source */
PIOB->PIO_PDR = (1 << 9);
PIOB->PIO_PUDR = (1 << 9);
PIOB->PIO_PPDDR = (1 << 9);
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY| CKGR_MOR_MOSCSEL;
#endif
/* disable the red LED after main clock initialization */ /* disable the red LED after main clock initialization */
PIOA->PIO_SODR = LED_RED; PIOA->PIO_SODR = LED_RED;
@@ -138,4 +184,26 @@ extern WEAK void LowLevelInit( void )
PMC->PMC_MCKR = BOARD_MCKR ; PMC->PMC_MCKR = BOARD_MCKR ;
/* wait for master clock to be ready */ /* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* Configure SysTick for 1ms */
SysTick_Config(BOARD_MCK/1000);
_ConfigureUsbClock();
}
/* SysTick based delay function */
volatile uint32_t jiffies;
/* Interrupt handler for SysTick interrupt */
void SysTick_Handler(void)
{
jiffies++;
}
void mdelay(unsigned int msecs)
{
uint32_t jiffies_start = jiffies;
do {
} while ((jiffies - jiffies_start) < msecs);
} }

View File

@@ -0,0 +1,83 @@
#include "board.h"
#include "boardver_adc.h"
/* FIXME: share this with mode_cardemu.c */
#define UV_PER_LSB ((3300 * 1000) / 4096)
static uint32_t adc2uv(uint16_t adc)
{
uint32_t uv = (uint32_t) adc * UV_PER_LSB;
return uv;
}
/***********************************************************************
* ADC for board version detection
***********************************************************************/
#ifdef PIN_VERSION_DET
static int adc_sam3s_reva_errata = 0;
static const Pin pin_version_det = PIN_VERSION_DET;
/* Warning: Don't call this while other code (like the SIM VCC voltage
* reading) is running. The idea is you call this once during board
* startup and cache the result in a (global) variable if you need it
* later throughout the code */
int get_board_version_adc(void)
{
uint32_t chip_arch = CHIPID->CHIPID_CIDR & CHIPID_CIDR_ARCH_Msk;
uint32_t chip_ver = CHIPID->CHIPID_CIDR & CHIPID_CIDR_VERSION_Msk;
uint16_t sample;
uint32_t uv;
PIO_Configure(&pin_version_det, 1);
PMC_EnablePeripheral(ID_ADC);
ADC->ADC_CR |= ADC_CR_SWRST;
if (chip_ver == 0 &&
(chip_arch == CHIPID_CIDR_ARCH_SAM3SxA ||
chip_arch == CHIPID_CIDR_ARCH_SAM3SxB ||
chip_arch == CHIPID_CIDR_ARCH_SAM3SxC)) {
TRACE_INFO("Enabling Rev.A ADC Errata work-around\r\n");
adc_sam3s_reva_errata = 1;
}
if (adc_sam3s_reva_errata) {
/* Errata Work-Around to clear EOCx flags */
volatile uint32_t foo;
int i;
for (i = 0; i < 16; i++)
foo = ADC->ADC_CDR[i];
}
/* Initialize ADC for AD2, fADC=48/24=2MHz */
ADC->ADC_MR = ADC_MR_TRGEN_DIS | ADC_MR_LOWRES_BITS_12 |
ADC_MR_SLEEP_NORMAL | ADC_MR_FWUP_OFF |
ADC_MR_FREERUN_OFF | ADC_MR_PRESCAL(23) |
ADC_MR_STARTUP_SUT8 | ADC_MR_SETTLING(3) |
ADC_MR_ANACH_NONE | ADC_MR_TRACKTIM(4) |
ADC_MR_TRANSFER(1) | ADC_MR_USEQ_NUM_ORDER;
/* enable AD2 channel only */
ADC->ADC_CHER = ADC_CHER_CH2;
/* Make sure we don't use interrupts as that's what the SIM card
* VCC ADC code is using */
ADC->ADC_IER = 0;
NVIC_DisableIRQ(ADC_IRQn);
ADC->ADC_CR |= ADC_CR_START;
/* busy-wait, actually read the value */
do { } while (!(ADC->ADC_ISR & ADC_ISR_EOC2));
/* convert to voltage */
sample = ADC->ADC_CDR[2];
uv = adc2uv(sample);
TRACE_INFO("VERSION_DET ADC=%u => %u uV\r\n", sample, uv);
/* FIXME: convert to board version based on thresholds */
return 0;
}
#endif /* PIN_VERSION_DET */

View File

@@ -0,0 +1,7 @@
#include "manifest.h"
const char *manifest_application = APPLICATION;
const char *manifest_revision = GIT_VERSION;
const char *manifest_board = BOARD;
const char *manifest_environment = ENVIRONMENT;

View File

@@ -6,6 +6,8 @@
/** Board definition */ /** Board definition */
#define owhw #define owhw
#define BOARD_MAINOSC 18432000
/* USIM 2 interface (USART) */ /* USIM 2 interface (USART) */
#define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} #define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_USIM2_IO {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} #define PIN_USIM2_IO {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}

View File

@@ -19,6 +19,7 @@
#include "chip.h" #include "chip.h"
#include "board.h" #include "board.h"
#include "utils.h"
static const Pin pins_cardsim[] = PINS_CARDSIM; static const Pin pins_cardsim[] = PINS_CARDSIM;

View File

@@ -0,0 +1,66 @@
#pragma once
#include "board_common.h"
/** Name of the board */
#define BOARD_NAME "QMOD"
/** Board definition */
#define qmod
#define BOARD_MAINOSC 12000000
/* USIM 2 interface (USART) */
#define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_USIM2_IO {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PINS_ISO7816_USIM2 PIN_USIM2_CLK, PIN_USIM2_IO
/* USIM 2 interface (TC) */
#define PIN_USIM2_IO_TC {PIO_PA1, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_USIM2_CLK_TC {PIO_PA4, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PINS_TC_USIM2 PIN_USIM2_IO_TC, PIN_USIM2_CLK_TC
/* USIM 1 interface (USART) */
#define PIN_USIM1_IO {PIO_PA22, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_USIM1_CLK {PIO_PA23, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PINS_ISO7816_USIM1 PIN_USIM1_CLK, PIN_USIM1_IO
/* USIM 1 interface (TC) */
#define PIN_USIM1_IO_TC {PIO_PA27, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_USIM1_CLK_TC {PIO_PA29, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PINS_TC_USIM1 PIN_USIM1_IO_TC, PIN_USIM1_CLK_TC
#define PIN_SET_USIM1_PRES {PIO_PA12, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
#define PIN_USIM1_VCC {PIO_PB3, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}
#define PIN_SET_USIM2_PRES {PIO_PA14, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#define PIN_USIM2_nRST {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
#define PIN_USIM2_VCC {PIO_PB2, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}
#define PINS_USIM1 PINS_TC_USIM1, PINS_ISO7816_USIM1, PIN_USIM1_nRST, PIN_SET_USIM1_PRES
#define PINS_USIM2 PINS_TC_USIM2, PINS_ISO7816_USIM2, PIN_USIM2_nRST, PIN_SET_USIM2_PRES
#define PINS_CARDSIM { PIN_SET_USIM1_PRES, PIN_SET_USIM2_PRES }
#define PIN_PRTPWR_OVERRIDE {PIO_PA8, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* inputs reading the WWAN LED level */
#define PIN_WWAN1 {PIO_PA15, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}
#define PIN_WWAN2 {PIO_PA16, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}
#define PINS_WWAN_IN { PIN_WWAN1, PIN_WWAN2 }
/* outputs controlling RESET input of modems */
#define PIN_PERST1 {PIO_PA25, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_PULLUP}
#define PIN_PERST2 {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_PULLUP}
#define PINS_PERST { PIN_PERST1, PIN_PERST2 }
#define PIN_VERSION_DET {PIO_PA19, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_DEFAULT}
#define SIMTRACE_VENDOR_ID 0x1d50
#define SIMTRACE_PRODUCT_ID 0x60e3 /* FIXME */
#define USB_VENDOR_ID SIMTRACE_VENDOR_ID
#define USB_PRODUCT_ID SIMTRACE_PRODUCT_ID
#define CARDEMU_SECOND_UART
#define DETECT_VCC_BY_ADC
#define HAVE_CARDEM

View File

@@ -0,0 +1,5 @@
#pragma once
void i2c_pin_init(void);
int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
int eeprom_read_byte(uint8_t slave, uint8_t addr);

View File

@@ -0,0 +1,4 @@
#pragma once
int wwan_led_active(int wwan);
int wwan_led_init(void);

View File

@@ -0,0 +1,4 @@
#pragma once
int wwan_perst_do_reset(int modem_nr);
int wwan_perst_init(void);

View File

@@ -0,0 +1,201 @@
/* Quad-modem speciic application code */
/* (C) 2016-2016 by Harald Welte <laforge@gnumonks.org> */
#include "board.h"
#include "simtrace.h"
#include "utils.h"
#include "req_ctx.h"
#include "wwan_led.h"
#include "wwan_perst.h"
#include "boardver_adc.h"
#include "osmocom/core/timer.h"
static const Pin pin_hubpwr_override = PIN_PRTPWR_OVERRIDE;
static const Pin pin_hub_rst = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
static const Pin pin_1234_detect = {PIO_PA14, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP};
static const Pin pin_peer_rst = {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
static const Pin pin_peer_erase = {PIO_PA11, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
static int qmod_sam3_is_12(void)
{
if (PIO_Get(&pin_1234_detect) == 0)
return 1;
else
return 0;
}
const unsigned char __eeprom_bin[256] = {
0x23, 0x42, 0x17, 0x25, 0x00, 0x00, 0x9b, 0x20, 0x01, 0x00, 0x00, 0x00, 0x32, 0x32, 0x32, 0x32, /* 0x00 - 0x0f */
0x32, 0x04, 0x09, 0x18, 0x0d, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x6d, 0x00, 0x6f, 0x00, /* 0x10 - 0x1f */
0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x20, 0x00, 0x73, 0x00, 0x2e, 0x00, /* 0x20 - 0x2f */
0x66, 0x00, 0x2e, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x47, 0x00, /* 0x30 - 0x3f */
0x6d, 0x00, 0x62, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 - 0x4f */
0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x75, 0x00, 0x61, 0x00, 0x64, 0x00, 0x20, 0x00, 0x6d, 0x00, /* 0x50 - 0x5f */
0x6f, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x76, 0x00, 0x32, 0x00, 0x00, 0x00, /* 0x60 - 0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x7f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80 - 0x8f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90 - 0x9f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0 - 0xaf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0 - 0xbf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 - 0xcf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 - 0xdf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0 - 0xef */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x56, 0x23, 0x71, 0x04, 0x00, /* 0xf0 - 0xff */
};
#include "i2c.h"
static int write_hub_eeprom(void)
{
const unsigned int __eeprom_bin_len = 256;
int i;
/* wait */
volatile int v;
/* 440ns per cycle here */
for (i = 0; i < 1000000; i++) {
v = 0;
}
TRACE_INFO("Writing EEPROM...\r\n");
/* write the EEPROM once */
for (i = 0; i < 256; i++) {
int rc = eeprom_write_byte(0x50, i, __eeprom_bin[i]);
/* if the result was negative, repeat that write */
if (rc < 0)
i--;
}
/* then pursue re-reading it again and again */
TRACE_INFO("Verifying EEPROM...\r\n");
for (i = 0; i < 256; i++) {
int byte = eeprom_read_byte(0x50, i);
TRACE_INFO("0x%02x: %02x\r\n", i, byte);
if (byte != __eeprom_bin[i])
TRACE_ERROR("Byte %u is wrong, expected 0x%02x, found 0x%02x\r\n",
i, __eeprom_bin[i], byte);
}
/* FIXME: Release PIN_PRTPWR_OVERRIDE after we know the hub is
* again powering us up */
return 0;
}
/* returns '1' in case we should break any endless loop */
void board_exec_dbg_cmd(int ch)
{
uint32_t addr, val;
switch (ch) {
case '?':
printf("\t?\thelp\r\n");
printf("\tE\tprogram EEPROM\r\n");
printf("\tR\treset SAM3\r\n");
printf("\tO\tEnable PRTPWR_OVERRIDE\r\n");
printf("\to\tDisable PRTPWR_OVERRIDE\r\n");
printf("\tH\tRelease HUB RESET (high)\r\n");
printf("\th\tAssert HUB RESET (low)\r\n");
printf("\tw\tWrite single byte in EEPROM\r\n");
printf("\tr\tRead single byte from EEPROM\r\n");
printf("\tX\tRelease peer SAM3 from reset\r\n");
printf("\tx\tAssert peer SAM3 reset\r\n");
printf("\tY\tRelease peer SAM3 ERASE signal\r\n");
printf("\ty\tAssert peer SAM3 ERASE signal\r\n");
printf("\tU\tProceed to USB Initialization\r\n");
printf("\t1\tGenerate 1ms reset pulse on WWAN1\r\n");
printf("\t2\tGenerate 1ms reset pulse on WWAN2\r\n");
break;
case 'E':
write_hub_eeprom();
break;
case 'R':
printf("Asking NVIC to reset us\r\n");
NVIC_SystemReset();
break;
case 'O':
printf("Setting PRTPWR_OVERRIDE\r\n");
PIO_Set(&pin_hubpwr_override);
break;
case 'o':
printf("Clearing PRTPWR_OVERRIDE\r\n");
PIO_Clear(&pin_hubpwr_override);
break;
case 'H':
printf("Clearing _HUB_RESET -> HUB_RESET high (inactive)\r\n");
PIO_Clear(&pin_hub_rst);
break;
case 'h':
/* high level drives transistor -> HUB_RESET low */
printf("Asserting _HUB_RESET -> HUB_RESET low (active)\r\n");
PIO_Set(&pin_hub_rst);
break;
case 'w':
if (PIO_GetOutputDataStatus(&pin_hub_rst) == 0)
printf("WARNING: attempting EEPROM access while HUB not in reset\r\n");
printf("Please enter EEPROM offset:\r\n");
UART_GetIntegerMinMax(&addr, 0, 255);
printf("Please enter EEPROM value:\r\n");
UART_GetIntegerMinMax(&val, 0, 255);
printf("Writing value 0x%02x to EEPROM offset 0x%02x\r\n", val, addr);
eeprom_write_byte(0x50, addr, val);
break;
case 'r':
printf("Please enter EEPROM offset:\r\n");
UART_GetIntegerMinMax(&addr, 0, 255);
printf("EEPROM[0x%02x] = 0x%02x\r\n", addr, eeprom_read_byte(0x50, addr));
break;
case 'X':
printf("Clearing _SIMTRACExx_RST -> SIMTRACExx_RST high (inactive)\r\n");
PIO_Clear(&pin_peer_rst);
break;
case 'x':
printf("Setting _SIMTRACExx_RST -> SIMTRACExx_RST low (active)\r\n");
PIO_Set(&pin_peer_rst);
break;
case 'Y':
printf("Clearing SIMTRACExx_ERASE (inactive)\r\n");
PIO_Clear(&pin_peer_erase);
break;
case 'y':
printf("Seetting SIMTRACExx_ERASE (active)\r\n");
PIO_Set(&pin_peer_erase);
break;
case '1':
printf("Resetting Modem 1 (of this SAM3)\r\n");
wwan_perst_do_reset(1);
break;
case '2':
printf("Resetting Modem 2 (of this SAM3)\r\n");
wwan_perst_do_reset(2);
break;
default:
printf("Unknown command '%c'\r\n", ch);
break;
}
}
void board_main_top(void)
{
wwan_led_init();
wwan_perst_init();
/* set PIN_PRTPWR_OVERRIDE to output-low to avoid the internal
* pull-up on the input to keep SIMTRACE12 alive */
PIO_Configure(&pin_hubpwr_override, 1);
PIO_Configure(&pin_hub_rst, 1);
PIO_Configure(&pin_1234_detect, 1);
PIO_Configure(&pin_peer_rst, 1);
PIO_Configure(&pin_peer_erase, 1);
i2c_pin_init();
if (qmod_sam3_is_12()) {
TRACE_INFO("Detected Quad-Modem ST12\r\n");
} else {
TRACE_INFO("Detected Quad-Modem ST34\r\n");
}
/* Obtain the circuit board version (currently just prints voltage */
get_board_version_adc();
}

View File

@@ -0,0 +1,203 @@
#include "board.h"
#include <stdbool.h>
/* Low-Level I2C Routines */
static const Pin pin_sda = {PIO_PA30, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
static const Pin pin_sda_in = {PIO_PA30, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT };
static const Pin pin_scl = {PIO_PA31, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
static void i2c_delay()
{
volatile int v;
int i;
/* 100 cycles results in SCL peak length of 44us, so it's about
* 440ns per cycle here */
for (i = 0; i < 14; i++) {
v = 0;
}
}
void i2c_pin_init(void)
{
PIO_Configure(&pin_scl, PIO_LISTSIZE(pin_scl));
PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
}
static void set_scl(void)
{
PIO_Set(&pin_scl);
i2c_delay();
}
static void set_sda(void)
{
PIO_Set(&pin_sda);
i2c_delay();
}
static void clear_scl(void)
{
PIO_Clear(&pin_scl);
i2c_delay();
}
static void clear_sda(void)
{
PIO_Clear(&pin_sda);
i2c_delay();
}
static bool read_sda(void)
{
bool ret;
PIO_Configure(&pin_sda_in, PIO_LISTSIZE(pin_sda_in));
if (PIO_Get(&pin_sda_in))
ret = true;
else
ret = false;
PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
return ret;
}
/* Core I2C Routines */
static bool i2c_started = false;
static void i2c_start_cond(void)
{
if (i2c_started) {
set_sda();
set_scl();
}
clear_sda();
i2c_delay();
clear_scl();
i2c_started = true;
}
static void i2c_stop_cond(void)
{
clear_sda();
set_scl();
set_sda();
i2c_delay();
i2c_started = false;
}
static void i2c_write_bit(bool bit)
{
if (bit)
set_sda();
else
clear_sda();
i2c_delay(); // ?
set_scl();
clear_scl();
}
static bool i2c_read_bit(void)
{
bool bit;
set_sda();
set_scl();
bit = read_sda();
clear_scl();
return bit;
}
bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
{
uint8_t bit;
bool nack;
if (send_start)
i2c_start_cond();
for (bit = 0; bit < 8; bit++) {
i2c_write_bit((byte & 0x80) != 0);
byte <<= 1;
}
nack = i2c_read_bit();
if (send_stop)
i2c_stop_cond();
return nack;
}
uint8_t i2c_read_byte(bool nack, bool send_stop)
{
uint8_t byte = 0;
uint8_t bit;
for (bit = 0; bit < 8; bit++) {
byte = (byte << 1) | i2c_read_bit();
}
i2c_write_bit(nack);
if (send_stop)
i2c_stop_cond();
return byte;
}
/* EEPROM related code */
int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
{
bool nack;
/* Write slave address */
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, true, byte);
if (nack)
goto out_stop;
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}
int eeprom_read_byte(uint8_t slave, uint8_t addr)
{
bool nack;
/* dummy write cycle */
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
/* Re-start with read */
nack = i2c_write_byte(true, false, (slave << 1) | 1);
if (nack)
goto out_stop;
return i2c_read_byte(true, true);
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}

View File

@@ -0,0 +1,80 @@
/* Code to read/track the status of the WWAN LEDs of attached modems
*
* Depending on the board this is running on, it might be possible
* for the controller to read the status of the WWAN LED output lines of
* the cellular modem. If the board supports this, it sets the
* PIN_WWAN1 and/or PIN_WWAN2 defines in its board.h file.
*/
#include "board.h"
#include "wwan_led.h"
#ifdef PIN_WWAN1
static const Pin pin_wwan1 = PIN_WWAN1;
static void wwan1_irqhandler(const Pin *pPin)
{
int active = wwan_led_active(1);
TRACE_INFO("WWAN1 LED %u\r\n", active);
/* TODO: notify host via USB */
}
#endif
#ifdef PIN_WWAN2
static const Pin pin_wwan2 = PIN_WWAN2;
static void wwan2_irqhandler(const Pin *pPin)
{
int active = wwan_led_active(2);
TRACE_INFO("WWAN2 LED %u\r\n", active);
/* TODO: notify host via USB */
}
#endif
/* determine if a tiven WWAN led is currently active or not */
int wwan_led_active(int wwan)
{
const Pin *pin;
int active;
switch (wwan) {
#ifdef PIN_WWAN1
case 1:
pin = &pin_wwan1;
break;
#endif
#ifdef PIN_WWAN2
case 2:
pin = &pin_wwan2;
break;
#endif
default:
return -1;
}
active = PIO_Get(&pin_wwan1) ? 0 : 1;
return active;
}
int wwan_led_init(void)
{
int num_leds = 0;
#ifdef PIN_WWAN1
PIO_Configure(&pin_wwan1, 1);
PIO_ConfigureIt(&pin_wwan1, wwan1_irqhandler);
PIO_EnableIt(&pin_wwan1);
num_leds++;
#endif
#ifdef PIN_WWAN2
PIO_Configure(&pin_wwan2, 1);
PIO_ConfigureIt(&pin_wwan2, wwan2_irqhandler);
PIO_EnableIt(&pin_wwan2);
num_leds++;
#endif
return num_leds;
}

View File

@@ -0,0 +1,76 @@
/* Code to control the PERST lines of attached modems
*
* Depending on the board this is running on, it might be possible
* for the controller to set the status of the PERST input line of
* the cellular modem. If the board supports this, it sets the
* PIN_PERST1 and/or PIN_PERST2 defines in its board.h file.
*/
#include "board.h"
#include "wwan_perst.h"
#include "osmocom/core/timer.h"
#define PERST_DURATION_MS 300
#ifdef PIN_PERST1
static const Pin pin_perst1 = PIN_PERST1;
static struct osmo_timer_list perst1_timer;
#endif
#ifdef PIN_PERST2
static const Pin pin_perst2 = PIN_PERST2;
static struct osmo_timer_list perst2_timer;
#endif
static void perst_tmr_cb(void *data)
{
const Pin *pin = data;
/* release the (low-active) reset */
PIO_Clear(pin);
}
int wwan_perst_do_reset(int modem_nr)
{
const Pin *pin;
struct osmo_timer_list *tmr;
switch (modem_nr) {
#ifdef PIN_PERST1
case 1:
pin = &pin_perst1;
tmr = &perst1_timer;
break;
#endif
#ifdef PIN_PERST2
case 2:
pin = &pin_perst2;
tmr = &perst2_timer;
break;
#endif
default:
return -1;
}
PIO_Set(pin);
osmo_timer_schedule(tmr, PERST_DURATION_MS/1000, (PERST_DURATION_MS%1000)*1000);
return 0;
}
int wwan_perst_init(void)
{
int num_perst = 0;
#ifdef PIN_PERST1
PIO_Configure(&pin_perst1, 1);
perst1_timer.cb = perst_tmr_cb;
perst1_timer.data = (void *) &pin_perst1;
num_perst++;
#endif
#ifdef PIN_PERST2
PIO_Configure(&pin_perst2, 1);
perst2_timer.cb = perst_tmr_cb;
perst2_timer.data = (void *) &pin_perst2;
num_perst++;
#endif
return num_perst;
}

View File

@@ -6,6 +6,8 @@
/** Board definition */ /** Board definition */
#define simtrace #define simtrace
#define BOARD_MAINOSC 18432000
/** Phone (SIM card emulator)/CCID Reader/MITM configuration **/ /** Phone (SIM card emulator)/CCID Reader/MITM configuration **/
/* Normally the communication lines between phone and SIM card are disconnected */ /* Normally the communication lines between phone and SIM card are disconnected */
// Disconnect SIM card I/O, VPP line from the phone lines // Disconnect SIM card I/O, VPP line from the phone lines

View File

@@ -0,0 +1,115 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// Definition of the ASSERT() and SANITY_CHECK() macros, which are used for
/// runtime condition & parameter verifying.
///
/// !Usage
///
/// -# Use ASSERT() in your code to check the value of function parameters,
/// return values, etc. *Warning:* the ASSERT() condition must not have
/// any side-effect; otherwise, the program may not work properly
/// anymore when assertions are disabled.
/// -# Use SANITY_CHECK() to perform checks with a default error message
/// (outputs the file and line number where the error occured). This
/// reduces memory overhead caused by assertion error strings.
/// -# Initialize the dbgu to see failed assertions at run-time.
/// -# Assertions can be entirely disabled by defining the NOASSERT symbol
/// at compilation time.
//------------------------------------------------------------------------------
#ifndef ASSERT_H
#define ASSERT_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <stdio.h>
#include "trace.h"
#define assert ASSERT
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#if defined(NOASSERT)
#define ASSERT(...)
#define SANITY_CHECK(...)
#else
#if (TRACE_LEVEL == 0)
/// Checks that the given condition is true,
/// otherwise stops the program execution.
/// \param condition Condition to verify.
#define ASSERT(condition) { \
if (!(condition)) { \
while (1); \
} \
}
/// Performs the same duty as the ASSERT() macro
/// \param condition Condition to verify.
#define SANITY_CHECK(condition) ASSERT(condition, ...)
#else
/// Checks that the given condition is true, otherwise displays an error
/// message and stops the program execution.
/// \param condition Condition to verify.
#define ASSERT(condition) { \
if (!(condition)) { \
printf("-F- ASSERT: %s %s:%d\r\n", #condition, __BASE_FILE__, __LINE__); \
while (1); \
} \
}
#define SANITY_ERROR "Sanity check failed at %s:%d\n\r"
/// Performs the same duty as the ASSERT() macro, except a default error
/// message is output if the condition is false.
/// \param condition Condition to verify.
#define SANITY_CHECK(condition) ASSERT(condition, SANITY_ERROR, __FILE__, __LINE__)
#endif
#endif
#endif //#ifndef ASSERT_H

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "linuxlist.h" #include "osmocom/core/linuxlist.h"
static inline void llist_add_tail_irqsafe(struct llist_head *_new, static inline void llist_add_tail_irqsafe(struct llist_head *_new,
struct llist_head *head) struct llist_head *head)

View File

@@ -5,7 +5,7 @@
#define MAX_HDRSIZE sizeof(struct openpcd_hdr) #define MAX_HDRSIZE sizeof(struct openpcd_hdr)
#include <stdint.h> #include <stdint.h>
#include "linuxlist.h" #include "osmocom/core/linuxlist.h"
#define __ramfunc #define __ramfunc

View File

@@ -106,6 +106,9 @@ extern void CCID_run( void );
extern void mode_cardemu_run(void); extern void mode_cardemu_run(void);
extern void MITM_run( void ); extern void MITM_run( void );
extern void mode_cardemu_usart0_irq(void);
extern void mode_cardemu_usart1_irq(void);
/* Timer helper function */ /* Timer helper function */
void Timer_Init( void ); void Timer_Init( void );
void TC0_Counter_Reset( void ); void TC0_Counter_Reset( void );

View File

@@ -0,0 +1,32 @@
#pragma once
#include <stddef.h>
#include <stdarg.h>
#ifndef EOF
#define EOF (-1)
#endif
struct File;
typedef struct File FILE;
extern FILE* const stdin;
extern FILE* const stdout;
extern FILE* const stderr;
signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap);
signed int snprintf(char *pString, size_t length, const char *pFormat, ...);
signed int vsprintf(char *pString, const char *pFormat, va_list ap);
signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap);
signed int vprintf(const char *pFormat, va_list ap);
signed int fprintf(FILE *pStream, const char *pFormat, ...);
signed int printf(const char *pFormat, ...);
signed int sprintf(char *pStr, const char *pFormat, ...);
signed int puts(const char *pStr);
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
#define putc(c, stream) fputc(c, stream)
#define putchar(c) fputc(c, stdout)

View File

@@ -50,8 +50,6 @@
extern caddr_t _sbrk ( int incr ) ; extern caddr_t _sbrk ( int incr ) ;
extern int link( char *old, char *new ) ;
extern int _close( int file ) ; extern int _close( int file ) ;
extern int _fstat( int file, struct stat *st ) ; extern int _fstat( int file, struct stat *st ) ;
@@ -63,3 +61,5 @@ extern int _lseek( int file, int ptr, int dir ) ;
extern int _read(int file, char *ptr, int len) ; extern int _read(int file, char *ptr, int len) ;
extern int _write( int file, char *ptr, int len ) ; extern int _write( int file, char *ptr, int len ) ;
extern void mdelay(unsigned int msecs);

Some files were not shown because too many files have changed in this diff Show More