klipper update

This commit is contained in:
Rainboooom
2023-06-15 11:41:08 +08:00
parent 845d13acb1
commit dffff1ae35
1921 changed files with 1625400 additions and 0 deletions

6
lib/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
*.o
bossac/bin/
bossac/obj/
hidflash/hid-flash
hub-ctrl/hub-ctrl
rp2040_flash/rp2040_flash

134
lib/README Normal file
View File

@@ -0,0 +1,134 @@
This directory contains external library code.
The cmsis directory contains code from:
https://github.com/ARM-software/CMSIS_5
version 5.7.0 (a65b7c9a3e6502127fdb80eb288d8cbdf251a6f4). Contents
taken from the CMSIS/Core/Include/ directory.
The sam3x directory contains code from the
Atmel.SAM3X_DFP.1.0.50.atpack zip file found at:
http://packs.download.atmel.com/
version 1.0.50 (extracted on 20180725).
The sam4e directory contains code from the
Atmel.SAM4E_DFP.1.1.57.atpack zip file found at:
http://packs.download.atmel.com/
version 1.1.57 (extracted on 20180806). It has been modified to fix
some AFEC register RW accesses. See sam4e.patch for the modifications.
The sam4s directory contains code from the
Atmel.SAM4S_DFP.1.0.56.atpack zip file found at:
http://packs.download.atmel.com/
version 1.0.56 (extracted on 20181220).
The samd21 directory contains code from the
Atmel.SAMD21_DFP.1.3.304.atpack zip file found at:
http://packs.download.atmel.com/
version 1.3.304 (extracted on 20180725).
The samd51 directory contains code from the
Atmel.SAMD51_DFP.1.1.96.atpack zip file found at:
http://packs.download.atmel.com/
version 1.1.96 (extracted on 20190110).
The same70b directory contains code from the
Atmel.SAME70_DFP.2.4.166.atpack zip file found at:
http://packs.download.atmel.com/
version 2.4.166 (extracted on 20210809).
The lpc176x directory contains code from the mbed project:
https://github.com/ARMmbed/mbed-os
version mbed-os-5.8.3 (c05d72c3c005fbb7e92c3994c32bda45218ae7fe).
Contents taken from the targets/TARGET_NXP/TARGET_LPC176X/ directory.
It has been modified to set the appropriate clock speeds on the
LPC1768 and LPC1769. See lpc176x.patch for the modifications.
The stm32f0 directory contains code from:
https://github.com/STMicroelectronics/STM32CubeF0
version v1.10.1 (d0c380d668c67dcdd4e44f656be27045ce4006a6). Contents
taken from the Drivers/CMSIS/Device/ST/STM32F0xx/ directory.
The stm32f1 directory contains code from:
https://github.com/STMicroelectronics/STM32CubeF1
version v1.8.0 (441b2cbdc25aa50437a59c4bffe22b88e78942c9). Contents
taken from the Drivers/CMSIS/Device/ST/STM32F1xx/ directory.
The stm32f2 directory contains code from:
https://github.com/STMicroelectronics/STM32CubeF2
version v1.9.0 (42fc8bf966c04ef814bb0620dcd3e036e038b4a2). Contents
taken from the Drivers/CMSIS/Device/ST/STM32F2xx/ directory.
The stm32f4 directory contains code from:
https://github.com/STMicroelectronics/STM32CubeF4
version v1.24.1 (b5abca20c9676b04f8d2885a668a9b653ee65705). Contents
taken from the Drivers/CMSIS/Device/ST/STM32F4xx/ directory.
The stm32g0 directory contains code from:
https://github.com/STMicroelectronics/STM32CubeG0
version v1.4.1 (5cb06333a6a43cefbe145f10a5aa98d3cc4cffee). Contents
taken from the Drivers/CMSIS/Device/ST/STM32G0xx/ directory.
The stm32h7 directory contains code from:
https://github.com/STMicroelectronics/STM32CubeH7
version v1.7.0 (79196b09acfb720589f58e93ccf956401b18a191). Contents
taken from the Drivers/CMSIS/Device/ST/STM32H7xx/ directory.
The rp2040 directory contains code from the pico sdk:
https://github.com/raspberrypi/pico-sdk.git
version 1.2.0 (bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7). It has been
modified so that it can build outside of the pico sdk. See
rp2040.patch for the modifications.
The rp2040_flash directory contains a light-weight bootsel flash tool.
It uses C part of the the `picoboot_connection` directory found in:
https://github.com/raspberrypi/picotool.git
version v1.1.0 (55fd880c3dc029b961fc1a0967a6cfdc0af02721).
The hub-ctrl directory contains code from:
https://github.com/codazoda/hub-ctrl.c/
revision 42095e522859059e8a5f4ec05c1e3def01a870a9.
The bossac directory contains code from:
https://github.com/shumatech/BOSSA
version 1.9 (b176eeef918fc810045c832348590595120187b4).
The hidflash directory contains code from:
https://github.com/Serasidis/STM32_HID_Bootloader
version 2.2.2 (2ab7927a27b7b78ef730782ea5f9b5d2c8f34671). It has been
modified to work with Klipper - see hidflash/README for the
details. See changes.diff for the modifications.
The pru_rpmsg directory contains code from:
https://github.com/dinuxbg/pru-gcc-examples
revision 425a42d82006cf0aa24be27b483d2f6a41607489. The code is taken
from the repo's hc-sr04-range-sensor directory. It has been modified
so that the IEP definitions compile correctly. See pru_rpmsg.patch for
the modifications.
The fast-hash directory contains code from:
https://github.com/ztanml/fast-hash
revision ae3bb53c199fe75619e940b5b6a3584ede99c5fc
The kconfiglib directory contains code from:
https://github.com/ulfalizer/Kconfiglib.git
version v14.1.0 (061e71f7d78cb057762d88de088055361863deff). It has
been modified to always emit symbols and to simplify the "menuconfig"
screens. See kconfiglib.patch for the modifications.
The fatfs directory contains code from:
http://elm-chan.org/fsw/ff/00index_e.html
version R0.14a (extracted 20210116). The configuration (ffconf.h)
has been modfied to enable the US code page (437) and enable label
support. The file "diskio.c" in the original archive is not included
as it is only serves as an example for how to implement the media api
callbacks.
The canboot directory contains code from:
https://github.com/Arksine/CanBoot
revision 870200826561b150137913d42fd7edc6515229ff. The Python module,
flash_can.py, is taken from the repo's scripts directory. It may be
used to upload firmware to devices flashed with the CanBoot bootloader.
The can2040 directory contains code from:
https://github.com/KevinOConnor/can2040
revision 9ca095c939a48391de60dd353f0cd91999bb9257.

24
lib/bossac/LICENSE Normal file
View File

@@ -0,0 +1,24 @@
Copyright (c) 2011-2016, ShumaTech
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 following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.

347
lib/bossac/Makefile Normal file
View File

@@ -0,0 +1,347 @@
.DEFAULT_GOAL := all
#
# Version
#
VERSION=1.9
WXVERSION=3.0
#
# Source files
#
COMMON_SRCS=Samba.cpp Flash.cpp D5xNvmFlash.cpp D2xNvmFlash.cpp EfcFlash.cpp EefcFlash.cpp Applet.cpp WordCopyApplet.cpp Flasher.cpp Device.cpp
APPLET_SRCS=WordCopyArm.asm
BOSSA_SRCS=BossaForm.cpp BossaWindow.cpp BossaAbout.cpp BossaApp.cpp BossaBitmaps.cpp BossaInfo.cpp BossaThread.cpp BossaProgress.cpp
BOSSA_BMPS=BossaLogo.bmp BossaIcon.bmp ShumaTechLogo.bmp
BOSSAC_SRCS=bossac.cpp CmdOpts.cpp
BOSSASH_SRCS=bossash.cpp Shell.cpp Command.cpp
#
# Build directories
#
BINDIR=bin
OBJDIR=obj
SRCDIR=src
RESDIR=res
INSTALLDIR=install
#
# Determine OS
#
OS:=$(shell uname -s | cut -c -7)
#
# Windows rules
#
ifeq ($(OS),MINGW32)
# Use wxWindows development branch to work around font scaling issues on Windows
WXVERSION=3.1
EXE=.exe
COMMON_SRCS+=WinSerialPort.cpp WinPortFactory.cpp
COMMON_LDFLAGS=-Wl,--enable-auto-import -static -static-libstdc++ -static-libgcc
COMMON_LIBS=-ltermcap -Wl,--as-needed -lsetupapi
BOSSA_RC=BossaRes.rc
WIXDIR="C:\Program Files (x86)\WiX Toolset v3.10\bin"
CODE_SIGN=$(INSTALLDIR)\\code_sign.p12
TIMESTAMP=http://timestamp.comodoca.com/authenticode
SIGNTOOL="C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe"
INF2CAT="C:\Program Files (x86)\Windows Kits\10\bin\x86\Inf2Cat.exe"
define bossa_msi
$(OBJDIR)\\bossa-$(1)-$(VERSION).wixobj: $(INSTALLDIR)\\bossa.wxs
$(WIXDIR)\\candle.exe -dVersion=$(VERSION) -arch $(1) -out $$@ -ext $(WIXDIR)\\WixUIExtension.dll -ext $(WIXDIR)\\WixDifxAppExtension.dll $$<
$(BINDIR)\\bossa-$(1)-$(VERSION).msi: $(OBJDIR)\\bossa-$(1)-$(VERSION).wixobj
$(WIXDIR)\\light.exe -cultures:null -out $$@ -pdbout $(OBJDIR)\\bossa.wixpdb -sice:ICE57 -ext $(WIXDIR)\\WixUIExtension.dll -ext $(WIXDIR)\\WixDifxAppExtension.dll $(WIXDIR)\\difxapp_$(1).wixlib $$<
$$(Q)read -p "Password:" -rs PASSWORD; \
cmd /C '$(SIGNTOOL) sign /v /fd sha256 /f $(CODE_SIGN) -t $(TIMESTAMP) /p '$$$$PASSWORD' $$@'
endef
$(eval $(call bossa_msi,x86))
$(eval $(call bossa_msi,x64))
$(INSTALLDIR)\\bossa.cat: $(INSTALLDIR)\\bossa.inf
export TMP=$$(mktemp -d); \
cp $< $$TMP; \
cmd /C '$(INF2CAT) /v /driver:'$$(cygpath -w $$TMP)' /os:XP_X86,Vista_X86,Vista_X64,7_X86,7_X64,8_X86,8_X64,6_3_X86,6_3_X64,10_x86,10_x64'; \
mv $$TMP/bossa.cat $@; \
rm -rf $$TMP; \
read -p "Password:" -rs PASSWORD; \
cmd /C '$(SIGNTOOL) sign /v /fd sha256 /f $(CODE_SIGN) -t $(TIMESTAMP) /p '$$PASSWORD' $@'
bossa.cat: $(INSTALLDIR)\\bossa.cat
install32: $(BINDIR)\\bossa-x86-$(VERSION).msi
install64: $(BINDIR)\\bossa-x64-$(VERSION).msi
.PHONY: install
install: strip install32 install64
endif
#
# Linux rules
#
ifeq ($(OS),Linux)
COMMON_SRCS+=PosixSerialPort.cpp LinuxPortFactory.cpp
COMMON_LIBS=-Wl,--as-needed
COMMON_CXXFLAGS=-std=c++11
WX_LIBS+=-lX11
MACHINE:=$(shell uname -m)
install: strip
tar cvzf $(BINDIR)/bossa-$(MACHINE)-$(VERSION).tgz -C $(BINDIR) bossa$(EXE) bossac$(EXE) bossash$(EXE)
endif
#
# OS X rules
#
ifeq ($(OS),Darwin)
COMMON_SRCS+=PosixSerialPort.cpp OSXPortFactory.cpp
COMMON_CXXFLAGS=-arch x86_64 -mmacosx-version-min=10.9
COMMON_LDFLAGS=-arch x86_64 -mmacosx-version-min=10.9
APP=BOSSA.app
DMG=bossa-$(VERSION).dmg
VOLUME=BOSSA
BACKGROUND=$(INSTALLDIR)/background.png
.PHONY: install
app:
mkdir -p $(BINDIR)/$(APP)/Contents/MacOS
mkdir -p $(BINDIR)/$(APP)/Contents/Resources
cp -f $(INSTALLDIR)/Info.plist $(BINDIR)/$(APP)/Contents
echo -n "APPL????" > $(BINDIR)/$(APP)/Contents/PkgInfo
ln -f $(BINDIR)/bossa $(BINDIR)/$(APP)/Contents/MacOS/bossa
cp -f $(RESDIR)/BossaIcon.icns $(BINDIR)/$(APP)/Contents/Resources
install: strip app
hdiutil create -ov -megabytes 5 -fs HFS+ -volname $(VOLUME) $(BINDIR)/$(DMG)
hdiutil attach -noautoopen $(BINDIR)/$(DMG)
cp -R $(BINDIR)/$(APP) /Volumes/$(VOLUME)/
cp $(BINDIR)/bossac$(EXE) /Volumes/$(VOLUME)/
cp $(BINDIR)/bossash$(EXE) /Volumes/$(VOLUME)/
ln -s /Applications /Volumes/$(VOLUME)/Applications
ln -s /usr/local/bin /Volumes/$(VOLUME)/bin
mkdir /Volumes/$(VOLUME)/.background
cp $(BACKGROUND) /Volumes/$(VOLUME)/.background
osascript < $(INSTALLDIR)/dmgwin.osa
hdiutil detach /Volumes/$(VOLUME)/
hdiutil convert -format UDBZ -o $(BINDIR)/tmp$(DMG) $(BINDIR)/$(DMG)
mv -f $(BINDIR)/tmp$(DMG) $(BINDIR)/$(DMG)
endif
#
# OpenBSD rules
# (This is likely to work without changes, but not tested, on other BSDs)
#
ifeq ($(OS),OpenBSD)
COMMON_SRCS+=PosixSerialPort.cpp BSDPortFactory.cpp
# This is only needed for bossash, but we can't add it to BOSSASH_LIBS here
# because that one is redefined later.
COMMON_LIBS+=-ltermcap
# As of 5.7, OpenBSD packages WxWidgets 2.8
# bossa builds, runs, and appears to play nicely with this version,
# but fails to do anything useful on systems that don't have hardware
# serial ports because of USB detection problems.
# (The SAM's USB programming port doesn't get recognized as a ucom
# device, and a USB serial adaptor attached to the UART gets detected
# by bossa as a USB interface and doesn't fall back to the serial
# programming protocol.)
WXVERSION=2.8
endif
ifeq (${OS},FreeBSD)
# This is only needed for bossash, but we can't add it to BOSSASH_LIBS here
# because that one is redefined later.
COMMON_SRCS+=PosixSerialPort.cpp BSDPortFactory.cpp
endif
#
# Object files
#
COMMON_OBJS=$(foreach src,$(COMMON_SRCS),$(OBJDIR)/$(src:%.cpp=%.o))
APPLET_OBJS=$(foreach src,$(APPLET_SRCS),$(OBJDIR)/$(src:%.asm=%.o))
BOSSA_OBJS=$(APPLET_OBJS) $(COMMON_OBJS) $(foreach src,$(BOSSA_SRCS),$(OBJDIR)/$(src:%.cpp=%.o))
ifdef BOSSA_RC
BOSSA_OBJS+=$(OBJDIR)/$(BOSSA_RC:%.rc=%.o)
endif
BOSSAC_OBJS=$(APPLET_OBJS) $(COMMON_OBJS) $(foreach src,$(BOSSAC_SRCS),$(OBJDIR)/$(src:%.cpp=%.o))
BOSSASH_OBJS=$(APPLET_OBJS) $(COMMON_OBJS) $(foreach src,$(BOSSASH_SRCS),$(OBJDIR)/$(src:%.cpp=%.o))
#
# Dependencies
#
DEPENDS=$(COMMON_SRCS:%.cpp=$(OBJDIR)/%.d)
DEPENDS+=$(APPLET_SRCS:%.asm=$(OBJDIR)/%.d)
DEPENDS+=$(BOSSA_SRCS:%.cpp=$(OBJDIR)/%.d)
DEPENDS+=$(BOSSAC_SRCS:%.cpp=$(OBJDIR)/%.d)
DEPENDS+=$(BOSSASH_SRCS:%.cpp=$(OBJDIR)/%.d)
#
# Tools
#
Q?=@
CXX?=g++
ARM=arm-none-eabi-
ARMAS=$(ARM)as
ARMOBJCOPY=$(ARM)objcopy
#
# CXX Flags
#
# COMMON_CXXFLAGS+=-Wall -Werror -MT $@ -MD -MP -MF $(@:%.o=%.d) -DVERSION=\"$(VERSION)\" -g -O2
COMMON_CXXFLAGS+=-Wall -MT $@ -MD -MP -MF $(@:%.o=%.d) -DVERSION=\"$(VERSION)\" -g -O2 $(CXXFLAGS)
WX_CXXFLAGS:=$(shell wx-config --cxxflags --version=$(WXVERSION)) -DWX_PRECOMP -Wno-ctor-dtor-privacy -O2 -fno-strict-aliasing
BOSSA_CXXFLAGS=$(COMMON_CXXFLAGS) $(WX_CXXFLAGS)
BOSSAC_CXXFLAGS=$(COMMON_CXXFLAGS)
BOSSASH_CXXFLAGS=$(COMMON_CXXFLAGS)
#
# LD Flags
#
COMMON_LDFLAGS+=-g $(LDFLAGS)
BOSSA_LDFLAGS=$(COMMON_LDFLAGS)
BOSSAC_LDFLAGS=$(COMMON_LDFLAGS)
BOSSASH_LDFLAGS=$(COMMON_LDFLAGS)
#
# Libs
#
COMMON_LIBS+=
WX_LIBS:=$(shell wx-config --libs --version=$(WXVERSION)) $(WX_LIBS)
BOSSA_LIBS=$(COMMON_LIBS) $(WX_LIBS)
BOSSAC_LIBS=$(COMMON_LIBS)
BOSSASH_LIBS=-lreadline $(COMMON_LIBS)
#
# Main targets
#
all: $(BINDIR)/bossa$(EXE) $(BINDIR)/bossac$(EXE) $(BINDIR)/bossash$(EXE)
#
# Common rules
#
define common_obj
$(OBJDIR)/$(1:%.cpp=%.o): $(SRCDIR)/$(1)
@echo CPP COMMON $$<
$$(Q)$$(CXX) $$(COMMON_CXXFLAGS) -c -o $$@ $$<
endef
$(foreach src,$(COMMON_SRCS),$(eval $(call common_obj,$(src))))
#
# Applet rules
#
define applet_obj
$(SRCDIR)/$(1:%.asm=%.cpp): $(SRCDIR)/$(1)
@echo APPLET $(1:%.asm=%)
$$(Q)$$(ARMAS) -o $$(@:$(SRCDIR)/%.cpp=$(OBJDIR)/%.obj) $$<
$$(Q)$$(ARMOBJCOPY) -O binary $$(@:$(SRCDIR)/%.cpp=$(OBJDIR)/%.obj) $$(@:$(SRCDIR)/%.cpp=$(OBJDIR)/%.bin)
$$(Q)./appletgen $(1:%.asm=%) $(SRCDIR) $(OBJDIR)
$(OBJDIR)/$(1:%.asm=%.o): $(SRCDIR)/$(1:%.asm=%.cpp)
@echo CPP APPLET $$<
$$(Q)$$(CXX) $$(COMMON_CXXFLAGS) -c -o $$(@) $$(<:%.asm=%.cpp)
endef
$(foreach src,$(APPLET_SRCS),$(eval $(call applet_obj,$(src))))
#
# BOSSA rules
#
define bossa_obj
$(OBJDIR)/$(1:%.cpp=%.o): $(SRCDIR)/$(1)
@echo CPP BOSSA $$<
$$(Q)$$(CXX) $$(BOSSA_CXXFLAGS) -c -o $$@ $$<
endef
$(foreach src,$(BOSSA_SRCS),$(eval $(call bossa_obj,$(src))))
#
# Resource rules
#
ifeq ($(OS),MINGW32)
$(OBJDIR)/$(BOSSA_RC:%.rc=%.o): $(RESDIR)/$(BOSSA_RC)
@echo RC $<
$(Q)`wx-config --rescomp --version=$(WXVERSION)` -o $@ $<
endif
#
# BOSSAC rules
#
define bossac_obj
$(OBJDIR)/$(1:%.cpp=%.o): $(SRCDIR)/$(1)
@echo CPP BOSSAC $$<
$$(Q)$$(CXX) $$(BOSSAC_CXXFLAGS) -c -o $$@ $$<
endef
$(foreach src,$(BOSSAC_SRCS),$(eval $(call bossac_obj,$(src))))
#
# BOSSASH rules
#
define bossash_obj
$(OBJDIR)/$(1:%.cpp=%.o): $(SRCDIR)/$(1)
@echo CPP BOSSASH $$<
$$(Q)$$(CXX) $$(BOSSASH_CXXFLAGS) -c -o $$@ $$<
endef
$(foreach src,$(BOSSASH_SRCS),$(eval $(call bossash_obj,$(src))))
#
# BMP rules
#
define bossa_bmp
$(SRCDIR)/$(1:%.bmp=%.cpp): $(RESDIR)/$(1)
@echo BIN2C $$<
$(Q)bin2c $$< $$@
endef
$(foreach bmp,$(BOSSA_BMPS),$(eval $(call bossa_bmp,$(bmp))))
#
# Directory rules
#
$(OBJDIR):
@mkdir $@
$(BINDIR):
@mkdir $@
#
# Target rules
#
$(BOSSA_OBJS): | $(OBJDIR)
$(BINDIR)/bossa$(EXE): $(foreach bmp,$(BOSSA_BMPS),$(SRCDIR)/$(bmp:%.bmp=%.cpp)) $(BOSSA_OBJS) | $(BINDIR)
@echo LD $@
$(Q)$(CXX) $(BOSSA_LDFLAGS) -o $@ $(BOSSA_OBJS) $(BOSSA_LIBS)
$(BOSSAC_OBJS): | $(OBJDIR)
$(BINDIR)/bossac$(EXE): $(BOSSAC_OBJS) | $(BINDIR)
@echo LD $@
$(Q)$(CXX) $(BOSSAC_LDFLAGS) -o $@ $(BOSSAC_OBJS) $(BOSSAC_LIBS)
$(BOSSASH_OBJS): | $(OBJDIR)
$(BINDIR)/bossash$(EXE): $(BOSSASH_OBJS) | $(BINDIR)
@echo LD $@
$(Q)$(CXX) $(BOSSASH_LDFLAGS) -o $@ $(BOSSASH_OBJS) $(BOSSASH_LIBS)
strip-bossa: $(BINDIR)/bossa$(EXE)
@echo STRIP $^
$(Q)strip $^
strip-bossac: $(BINDIR)/bossac$(EXE)
@echo STRIP $^
$(Q)strip $^
strip-bossash: $(BINDIR)/bossash$(EXE)
@echo STRIP $^
$(Q)strip $^
strip: strip-bossa strip-bossac strip-bossash
clean:
@echo CLEAN
$(Q)rm -rf $(BINDIR) $(OBJDIR)
#
# Include dependencies
#
-include $(DEPENDS)

64
lib/bossac/src/Applet.cpp Normal file
View File

@@ -0,0 +1,64 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include "Applet.h"
Applet::Applet(Samba& samba,
uint32_t addr,
uint8_t* code,
uint32_t size,
uint32_t start,
uint32_t stack,
uint32_t reset) :
_samba(samba), _addr(addr), _size(size), _start(start), _stack(stack), _reset(reset)
{
_samba.write(addr, code, size);
}
void
Applet::setStack(uint32_t stack)
{
_samba.writeWord(_stack, stack);
}
void
Applet::run()
{
// Add one to the start address for Thumb mode
_samba.go(_start + 1);
}
void
Applet::runv()
{
// Add one to the start address for Thumb mode
_samba.writeWord(_reset, _start + 1);
// The stack is the first reset vector
_samba.go(_stack);
}

65
lib/bossac/src/Applet.h Normal file
View File

@@ -0,0 +1,65 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _APPLET_H
#define _APPLET_H
#include <stdint.h>
#include "Samba.h"
class Applet
{
public:
Applet(Samba& samba,
uint32_t addr,
uint8_t* code,
uint32_t size,
uint32_t start,
uint32_t stack,
uint32_t reset);
virtual ~Applet() {}
virtual uint32_t size() { return _size; }
virtual uint32_t addr() { return _addr; }
virtual void setStack(uint32_t stack);
virtual void run(); // To be used for Thumb-1 based devices (ARM7TDMI, ARM9)
virtual void runv(); // To be used for Thumb-2 based devices (Cortex-Mx)
protected:
Samba& _samba;
uint32_t _addr; // Address in device SRAM where will be placed the applet
uint32_t _size; // Applet size
uint32_t _start; //
uint32_t _stack; // Applet stack address in device SRAM
uint32_t _reset;
};
#endif // _APPLET_H

159
lib/bossac/src/CmdOpts.cpp Normal file
View File

@@ -0,0 +1,159 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <assert.h>
#include "CmdOpts.h"
CmdOpts::CmdOpts(int argc, char* argv[], int numOpts, Option* opts) :
_argc(argc), _argv(argv), _numOpts(numOpts), _opts(opts)
{
}
CmdOpts::~CmdOpts()
{
}
void
CmdOpts::usage(FILE* out)
{
int optIdx;
char name[40];
const char* start;
const char* end;
for (optIdx = 0; optIdx < _numOpts; optIdx++)
{
if (_opts[optIdx].arg.has == ArgOptional)
snprintf(name, sizeof(name), " -%c, --%s[=%s]",
_opts[optIdx].letter,
_opts[optIdx].name,
_opts[optIdx].arg.name);
else if (_opts[optIdx].arg.has == ArgRequired)
snprintf(name, sizeof(name), " -%c, --%s=%s",
_opts[optIdx].letter,
_opts[optIdx].name,
_opts[optIdx].arg.name);
else
snprintf(name, sizeof(name), " -%c, --%s",
_opts[optIdx].letter,
_opts[optIdx].name);
fprintf(out, "%-23s ", name);
start = _opts[optIdx].help;
while ((end = strchr(start, '\n')))
{
fwrite(start, end - start + 1, 1, out);
fprintf(out, "%24s", "");
start = end + 1;
}
fprintf(out, "%s\n", start);
}
}
int
CmdOpts::parse()
{
struct option long_opts[_numOpts + 1];
char optstring[_numOpts * 3 + 1];
char* optPtr = optstring;
int optIdx;
int rc;
for (optIdx = 0; optIdx < _numOpts; optIdx++)
{
*_opts[optIdx].present = false;
*optPtr++ = _opts[optIdx].letter;
long_opts[optIdx].name = _opts[optIdx].name;
switch (_opts[optIdx].arg.has)
{
default:
case ArgNone:
long_opts[optIdx].has_arg = no_argument;
break;
case ArgOptional:
long_opts[optIdx].has_arg = optional_argument;
*optPtr++ = ':';
*optPtr++ = ':';
break;
case ArgRequired:
long_opts[optIdx].has_arg = required_argument;
*optPtr++ = ':';
break;
}
long_opts[optIdx].flag = NULL;
long_opts[optIdx].val = 0;
}
memset(&long_opts[_numOpts], 0, sizeof(long_opts[_numOpts]));
*optPtr = '\0';
optIdx = 0;
while ((rc = getopt_long(_argc, _argv, optstring, long_opts, &optIdx)) != -1)
{
if (rc == '?')
return -1;
if (rc != 0)
optIdx = find(rc);
assert(optIdx >= 0 && optIdx < _numOpts);
*_opts[optIdx].present = true;
if (_opts[optIdx].arg.has != ArgNone && optarg)
{
switch (_opts[optIdx].arg.type)
{
case ArgInt:
*_opts[optIdx].arg.value.intPtr = strtol(optarg, NULL, 0);
break;
default:
case ArgString:
*_opts[optIdx].arg.value.strPtr = optarg;
break;
}
}
}
return optind;
}
int
CmdOpts::find(char letter)
{
int optIdx;
for (optIdx = 0; optIdx < _numOpts; optIdx++)
if (_opts[optIdx].letter == letter)
break;
return optIdx;
}

88
lib/bossac/src/CmdOpts.h Normal file
View File

@@ -0,0 +1,88 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _OPTION_H
#define _OPTION_H
#include <string>
#include <stdio.h>
typedef enum
{
ArgNone,
ArgOptional,
ArgRequired
} ArgHas;
typedef enum
{
ArgInt,
ArgString
} ArgType;
typedef struct
{
ArgHas has;
ArgType type;
const char* name;
union
{
void* voidPtr;
int* intPtr;
std::string* strPtr;
} value;
} OptArg;
typedef struct
{
char letter;
const char* name;
bool* present;
OptArg arg;
const char* help;
} Option;
class CmdOpts
{
public:
CmdOpts(int argc, char* argv[], int numOpts, Option* opts);
virtual ~CmdOpts();
void usage(FILE* out);
int parse();
private:
int _argc;
char** _argv;
int _numOpts;
Option* _opts;
int find(char letter);
};
#endif // _OPTION_H

View File

@@ -0,0 +1,347 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2018, ShumaTech
//
// 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 3 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, see <http://www.gnu.org/licenses/>.
///////////////////////////////////////////////////////////////////////////////
#include "D2xNvmFlash.h"
// CMDEX field should be 0xA5 to allow execution of any command.
#define CMDEX_KEY 0xa500
// NVM ready bit mask
#define NVM_INT_STATUS_READY_MASK 0x1
// NVM status mask
#define NVM_CTRL_STATUS_MASK 0xFFEB
#define NVM_REG_BASE 0x41004000
#define NVM_REG_CTRLA 0x00
#define NVM_REG_CTRLB 0x04
#define NVM_REG_INTFLAG 0x14
#define NVM_REG_STATUS 0x18
#define NVM_REG_ADDR 0x1c
#define NVM_REG_LOCK 0x20
#define NVM_CMD_ER 0x02
#define NVM_CMD_WP 0x04
#define NVM_CMD_EAR 0x05
#define NVM_CMD_WAP 0x06
#define NVM_CMD_LR 0x40
#define NVM_CMD_UR 0x41
#define NVM_CMD_SSB 0x45
#define NVM_CMD_PBC 0x44
#define ERASE_ROW_PAGES 4 // pages
// NVM User Row
#define NVM_UR_ADDR 0x804000
#define NVM_UR_SIZE (_size * ERASE_ROW_PAGES)
#define NVM_UR_BOD33_ENABLE_OFFSET 0x1
#define NVM_UR_BOD33_ENABLE_MASK 0x6
#define NVM_UR_BOD33_RESET_OFFSET 0x1
#define NVM_UR_BOD33_RESET_MASK 0x7
#define NVM_UR_NVM_LOCK_OFFSET 0x6
D2xNvmFlash::D2xNvmFlash(
Samba& samba,
const std::string& name,
uint32_t pages,
uint32_t size,
uint32_t user,
uint32_t stack)
:
Flash(samba, name, 0, pages, size, 1, 16, user, stack), _eraseAuto(true)
{
}
D2xNvmFlash::~D2xNvmFlash()
{
}
void
D2xNvmFlash::erase(uint32_t offset, uint32_t size)
{
uint32_t eraseSize = _size * ERASE_ROW_PAGES;
// Offset must be a multiple of the erase size
if (offset % eraseSize)
throw FlashEraseError();
// Offset and size must be in range
if (offset + size > totalSize())
throw FlashEraseError();
uint32_t eraseEnd = (offset + size + eraseSize - 1) / eraseSize;
// Erase each erase size set of pages
for (uint32_t eraseNum = offset / eraseSize; eraseNum < eraseEnd; eraseNum++)
{
waitReady();
// Clear error bits
uint16_t statusReg = readReg(NVM_REG_STATUS);
writeReg(NVM_REG_STATUS, statusReg | NVM_CTRL_STATUS_MASK);
// Issue erase command
uint32_t wordAddr = (eraseNum * eraseSize) / 2;
writeReg(NVM_REG_ADDR, wordAddr);
command(NVM_CMD_ER);
}
}
void
D2xNvmFlash::eraseAll(uint32_t offset)
{
// Use the extended Samba command if available
if (_samba.canChipErase())
{
_samba.chipErase(offset);
}
else
{
erase(offset, totalSize() - offset);
}
}
void
D2xNvmFlash::eraseAuto(bool enable)
{
_eraseAuto = enable;
}
std::vector<bool>
D2xNvmFlash::getLockRegions()
{
uint8_t lockBits = 0;
uint32_t addr = NVM_UR_ADDR + NVM_UR_NVM_LOCK_OFFSET;
std::vector<bool> regions(_lockRegions);
for (uint32_t region = 0; region < _lockRegions; region++)
{
if (region % 8 == 0)
lockBits = _samba.readByte(addr++);
regions[region] = (lockBits & (1 << (region % 8))) == 0;
}
return regions;
}
bool
D2xNvmFlash::getSecurity()
{
return (readReg(NVM_REG_STATUS) & 0x100) != 0;
}
bool
D2xNvmFlash::getBod()
{
uint8_t byte = _samba.readByte(NVM_UR_ADDR + NVM_UR_BOD33_ENABLE_OFFSET);
return (byte & NVM_UR_BOD33_ENABLE_MASK) != 0;
}
bool
D2xNvmFlash::getBor()
{
uint8_t byte = _samba.readByte(NVM_UR_ADDR + NVM_UR_BOD33_RESET_OFFSET);
return (byte & NVM_UR_BOD33_RESET_MASK) != 0;
}
bool
D2xNvmFlash::getBootFlash()
{
return true;
}
void
D2xNvmFlash::readUserRow(std::unique_ptr<uint8_t[]>& userRow)
{
if (!userRow)
{
userRow.reset(new uint8_t[NVM_UR_SIZE]);
_samba.read(NVM_UR_ADDR, userRow.get(), NVM_UR_SIZE);
}
}
void
D2xNvmFlash::writeOptions()
{
std::unique_ptr<uint8_t[]> userRow;
if (canBor() && _bor.isDirty() && _bor.get() != getBor())
{
readUserRow(userRow);
if (_bor.get())
userRow[NVM_UR_BOD33_RESET_OFFSET] |= NVM_UR_BOD33_RESET_MASK;
else
userRow[NVM_UR_BOD33_RESET_OFFSET] &= ~NVM_UR_BOD33_RESET_MASK;
}
if (canBod() && _bod.isDirty() && _bod.get() != getBod())
{
readUserRow(userRow);
if (_bod.get())
userRow[NVM_UR_BOD33_ENABLE_OFFSET] |= NVM_UR_BOD33_ENABLE_MASK;
else
userRow[NVM_UR_BOD33_ENABLE_OFFSET] &= ~NVM_UR_BOD33_ENABLE_MASK;
}
if (_regions.isDirty())
{
// Check if any lock bits are different from the current set
std::vector<bool> current = getLockRegions();
if (!equal(_regions.get().begin(), _regions.get().end(), current.begin()))
{
readUserRow(userRow);
uint8_t* lockBits = &userRow[NVM_UR_NVM_LOCK_OFFSET];
for (uint32_t region = 0; region < _regions.get().size(); region++)
{
if (_regions.get()[region])
lockBits[region / 8] &= ~(1 << (region % 8));
else
lockBits[region / 8] |= (1 << (region % 8));
}
}
}
// Erase and write the user row if modified
if (userRow)
{
// Disable cache and configure manual page write
writeReg(NVM_REG_CTRLB, readReg(NVM_REG_CTRLB) | (0x1 << 18) | (0x1 << 7));
// Erase user row
writeReg(NVM_REG_ADDR, NVM_UR_ADDR / 2);
command(NVM_CMD_EAR);
// Write user row in page chunks
for (uint32_t offset = 0; offset < NVM_UR_SIZE; offset += _size)
{
// Load the buffer with the page
loadBuffer(&userRow[offset], _size);
// Clear page buffer
command(NVM_CMD_PBC);
// Copy page to page buffer
_wordCopy.setDstAddr(NVM_UR_ADDR + offset);
_wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
_onBufferA = !_onBufferA;
waitReady();
_wordCopy.runv();
// Write the page
writeReg(NVM_REG_ADDR, (NVM_UR_ADDR + offset) / 2);
command(NVM_CMD_WAP);
}
}
// Always do security last
if (_security.isDirty() && _security.get() == true && _security.get() != getSecurity())
{
command(NVM_CMD_SSB);
}
}
void
D2xNvmFlash::writePage(uint32_t page)
{
if (page >= _pages)
{
throw FlashPageError();
}
// Disable cache and configure manual page write
writeReg(NVM_REG_CTRLB, readReg(NVM_REG_CTRLB) | (0x1 << 18) | (0x1 << 7));
// Auto-erase if writing at the start of the erase page
if (_eraseAuto && page % ERASE_ROW_PAGES == 0)
erase(page * _size, ERASE_ROW_PAGES * _size);
// Clear page buffer
command(NVM_CMD_PBC);
// Compute the start address.
uint32_t addr = _addr + (page * _size);
_wordCopy.setDstAddr(addr);
_wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
_onBufferA = !_onBufferA;
waitReady();
_wordCopy.runv();
writeReg(NVM_REG_ADDR, addr / 2);
command(NVM_CMD_WP);
}
void
D2xNvmFlash::waitReady()
{
while ((readReg(NVM_REG_INTFLAG) & 0x1) == 0);
}
void
D2xNvmFlash::readPage(uint32_t page, uint8_t* buf)
{
if (page >= _pages)
{
throw FlashPageError();
}
_samba.read(_addr + (page * _size), buf, _size);
}
uint32_t
D2xNvmFlash::readReg(uint8_t reg)
{
return _samba.readWord(NVM_REG_BASE + reg);
}
void
D2xNvmFlash::writeReg(uint8_t reg, uint32_t value)
{
_samba.writeWord(NVM_REG_BASE + reg, value);
}
void
D2xNvmFlash::command(uint8_t cmd)
{
waitReady();
writeReg(NVM_REG_CTRLA, CMDEX_KEY | cmd);
waitReady();
if (readReg(NVM_REG_INTFLAG) & 0x2)
{
// Clear the error bit
writeReg(NVM_REG_INTFLAG, 0x2);
throw FlashCmdError();
}
}
void
D2xNvmFlash::writeBuffer(uint32_t dst_addr, uint32_t size)
{
// Auto-erase if enabled
if (_eraseAuto)
erase(dst_addr, size);
// Call the base class method
Flash::writeBuffer(dst_addr, size);
}

View File

@@ -0,0 +1,76 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2018, ShumaTech
//
// 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 3 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, see <http://www.gnu.org/licenses/>.
///////////////////////////////////////////////////////////////////////////////
#ifndef _D2XNVMFLASH_H
#define _D2XNVMFLASH_H
#include <stdint.h>
#include <exception>
#include "Flash.h"
class D2xNvmFlash : public Flash
{
public:
D2xNvmFlash(
Samba& samba,
const std::string& name,
uint32_t pages,
uint32_t size,
uint32_t user,
uint32_t stack);
virtual ~D2xNvmFlash();
void eraseAll(uint32_t offset);
void eraseAuto(bool enable);
std::vector<bool> getLockRegions();
bool getSecurity();
bool getBod();
bool canBod() { return true; }
bool getBor();
bool canBor() { return true; }
bool getBootFlash();
bool canBootFlash() { return false; }
void writeOptions();
void writePage(uint32_t page);
void readPage(uint32_t page, uint8_t* data);
void writeBuffer(uint32_t dst_addr, uint32_t size);
protected:
bool _eraseAuto;
uint32_t readReg(uint8_t reg);
void writeReg(uint8_t reg, uint32_t value);
void waitReady();
void command(uint8_t cmd);
void erase(uint32_t offset, uint32_t size);
void readUserRow(std::unique_ptr<uint8_t[]>& userRow);
};
#endif // _D2XNVMFLASH_H

View File

@@ -0,0 +1,352 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2018, ShumaTech
//
// 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 3 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, see <http://www.gnu.org/licenses/>.
///////////////////////////////////////////////////////////////////////////////
#include "D5xNvmFlash.h"
#define CMDEX_KEY 0xa500
#define NVM_REG_BASE 0x41004000
#define NVM_REG_CTRLA 0x00
#define NVM_REG_CTRLB 0x04
#define NVM_REG_INTFLAG 0x10
#define NVM_REG_STATUS 0x12
#define NVM_REG_ADDR 0x14
#define NVM_REG_RUNLOCK 0x18
#define NVM_CMD_EP 0x00
#define NVM_CMD_EB 0x01
#define NVM_CMD_WP 0x03
#define NVM_CMD_WQW 0x04
#define NVM_CMD_LR 0x11
#define NVM_CMD_UR 0x12
#define NVM_CMD_SSB 0x16
#define NVM_CMD_PBC 0x15
#define ERASE_BLOCK_PAGES 16 // pages
// NVM User Page
#define NVM_UP_ADDR 0x804000
#define NVM_UP_SIZE (_size)
#define NVM_UP_BOD33_DISABLE_OFFSET 0x0
#define NVM_UP_BOD33_DISABLE_MASK 0x1
#define NVM_UP_BOD33_RESET_OFFSET 0x1
#define NVM_UP_BOD33_RESET_MASK 0x2
#define NVM_UP_NVM_LOCK_OFFSET 0x8
D5xNvmFlash::D5xNvmFlash(
Samba& samba,
const std::string& name,
uint32_t pages,
uint32_t size,
uint32_t user,
uint32_t stack)
:
Flash(samba, name, 0, pages, size, 1, 32, user, stack), _eraseAuto(true)
{
}
D5xNvmFlash::~D5xNvmFlash()
{
}
void
D5xNvmFlash::erase(uint32_t offset, uint32_t size)
{
uint32_t eraseSize = _size * ERASE_BLOCK_PAGES;
// Offset must be a multiple of the erase size
if (offset % eraseSize)
throw FlashEraseError();
// Offset and size must be in range
if (offset + size > totalSize())
throw FlashEraseError();
uint32_t eraseEnd = (offset + size + eraseSize - 1) / eraseSize;
// Erase each erase size set of pages
for (uint32_t eraseNum = offset / eraseSize; eraseNum < eraseEnd; eraseNum++)
{
// Issue erase command
writeRegU32(NVM_REG_ADDR, eraseNum * eraseSize);
command(NVM_CMD_EB);
}
}
void
D5xNvmFlash::eraseAll(uint32_t offset)
{
// Use the extended Samba command if available
if (_samba.canChipErase())
{
_samba.chipErase(offset);
}
else
{
erase(offset, totalSize() - offset);
}
}
void
D5xNvmFlash::waitReady()
{
while ((readRegU16(NVM_REG_STATUS) & 0x1) == 0);
}
void
D5xNvmFlash::eraseAuto(bool enable)
{
_eraseAuto = enable;
}
std::vector<bool>
D5xNvmFlash::getLockRegions()
{
uint8_t lockBits = 0;
uint32_t addr = NVM_UP_ADDR + NVM_UP_NVM_LOCK_OFFSET;
std::vector<bool> regions(_lockRegions);
for (uint32_t region = 0; region < _lockRegions; region++)
{
if (region % 8 == 0)
lockBits = _samba.readByte(addr++);
regions[region] = (lockBits & (1 << (region % 8))) == 0;
}
return regions;
}
bool
D5xNvmFlash::getSecurity()
{
// There doesn't seem to be a way to read this
return false;
}
bool
D5xNvmFlash::getBod()
{
uint8_t byte = _samba.readByte(NVM_UP_ADDR + NVM_UP_BOD33_DISABLE_OFFSET);
return (byte & NVM_UP_BOD33_DISABLE_MASK) == 0;
}
bool
D5xNvmFlash::getBor()
{
uint8_t byte = _samba.readByte(NVM_UP_ADDR + NVM_UP_BOD33_RESET_OFFSET);
return (byte & NVM_UP_BOD33_RESET_MASK) != 0;
}
bool
D5xNvmFlash::getBootFlash()
{
return true;
}
void
D5xNvmFlash::readUserPage(std::unique_ptr<uint8_t[]>& userPage)
{
if (!userPage)
{
userPage.reset(new uint8_t[NVM_UP_SIZE]);
_samba.read(NVM_UP_ADDR, userPage.get(), NVM_UP_SIZE);
}
}
void
D5xNvmFlash::writeOptions()
{
std::unique_ptr<uint8_t[]> userPage;
if (canBor() && _bor.isDirty() && _bor.get() != getBor())
{
readUserPage(userPage);
if (_bor.get())
userPage[NVM_UP_BOD33_RESET_OFFSET] |= NVM_UP_BOD33_RESET_MASK;
else
userPage[NVM_UP_BOD33_RESET_OFFSET] &= ~NVM_UP_BOD33_RESET_MASK;
}
if (canBod() && _bod.isDirty() && _bod.get() != getBod())
{
readUserPage(userPage);
if (_bod.get())
userPage[NVM_UP_BOD33_DISABLE_OFFSET] &= ~NVM_UP_BOD33_DISABLE_MASK;
else
userPage[NVM_UP_BOD33_DISABLE_OFFSET] |= NVM_UP_BOD33_DISABLE_MASK;
}
if (_regions.isDirty())
{
// Check if any lock bits are different from the current set
std::vector<bool> current = getLockRegions();
if (!equal(_regions.get().begin(), _regions.get().end(), current.begin()))
{
readUserPage(userPage);
uint8_t* lockBits = &userPage[NVM_UP_NVM_LOCK_OFFSET];
for (uint32_t region = 0; region < _regions.get().size(); region++)
{
if (_regions.get()[region])
lockBits[region / 8] &= ~(1 << (region % 8));
else
lockBits[region / 8] |= (1 << (region % 8));
}
}
}
// Erase and write the user page if modified
if (userPage)
{
// Configure manual page write and disable caches
writeRegU16(NVM_REG_CTRLA, (readRegU16(NVM_REG_CTRLA) | (0x3 << 14)) & 0xffcf);
// Erase user page
writeRegU32(NVM_REG_ADDR, NVM_UP_ADDR);
command(NVM_CMD_EP);
// Write user page in quad-word chunks
for (uint32_t offset = 0; offset < NVM_UP_SIZE; offset += 16)
{
// Load the buffer with the quad word
loadBuffer(&userPage[offset], 16);
// Clear page buffer
command(NVM_CMD_PBC);
// Copy quad word to page buffer
_wordCopy.setDstAddr(NVM_UP_ADDR + offset);
_wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
_wordCopy.setWords(4);
_onBufferA = !_onBufferA;
waitReady();
_wordCopy.runv();
// Write the quad word
writeRegU32(NVM_REG_ADDR, NVM_UP_ADDR + offset);
command(NVM_CMD_WQW);
}
}
// Always do security last
if (_security.isDirty() && _security.get() == true && _security.get() != getSecurity())
{
command(NVM_CMD_SSB);
}
}
void
D5xNvmFlash::writePage(uint32_t page)
{
if (page >= _pages)
{
throw FlashPageError();
}
// Configure manual page write and disable caches
writeRegU16(NVM_REG_CTRLA, (readRegU16(NVM_REG_CTRLA) | (0x3 << 14)) & 0xffcf);
// Auto-erase if writing at the start of the erase page
if (_eraseAuto && page % ERASE_BLOCK_PAGES == 0)
{
erase(page * _size, ERASE_BLOCK_PAGES * _size);
}
// Clear page bur
command(NVM_CMD_PBC);
uint32_t addr = _addr + (page * _size );
_wordCopy.setDstAddr(addr);
_wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
_wordCopy.setWords(_size / sizeof(uint32_t));
_onBufferA = !_onBufferA;
waitReady();
_wordCopy.runv();
writeRegU32(NVM_REG_ADDR, addr);
command(NVM_CMD_WP);
}
void
D5xNvmFlash::readPage(uint32_t page, uint8_t* buf)
{
if (page >= _pages)
{
throw FlashPageError();
}
_samba.read(_addr + (page * _size), buf, _size);
}
uint16_t
D5xNvmFlash::readRegU16(uint8_t reg)
{
return (uint16_t) _samba.readByte(NVM_REG_BASE + reg) |
(_samba.readByte(NVM_REG_BASE + reg + 1) << 8);
}
void
D5xNvmFlash::writeRegU16(uint8_t reg, uint16_t value)
{
_samba.writeByte(NVM_REG_BASE + reg, value & 0xff);
_samba.writeByte(NVM_REG_BASE + reg + 1, value >> 8);
}
uint32_t
D5xNvmFlash::readRegU32(uint8_t reg)
{
return _samba.readWord(NVM_REG_BASE + reg);
}
void
D5xNvmFlash::writeRegU32(uint8_t reg, uint32_t value)
{
_samba.writeWord(NVM_REG_BASE + reg, value);
}
void
D5xNvmFlash::command(uint8_t cmd)
{
waitReady();
writeRegU32(NVM_REG_CTRLB, CMDEX_KEY | cmd);
waitReady();
if (readRegU16(NVM_REG_INTFLAG) & 0xce)
{
// Clear the error bits
writeRegU16(NVM_REG_INTFLAG, 0xce);
throw FlashCmdError();
}
}
void
D5xNvmFlash::writeBuffer(uint32_t dst_addr, uint32_t size)
{
// Auto-erase if writing at the start of the erase page
if (_eraseAuto && ((dst_addr / _size) % ERASE_BLOCK_PAGES == 0))
erase(dst_addr, size);
// Call the base class method
Flash::writeBuffer(dst_addr, size);
}

View File

@@ -0,0 +1,79 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2018, ShumaTech
//
// 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 3 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, see <http://www.gnu.org/licenses/>.
///////////////////////////////////////////////////////////////////////////////
#ifndef _D5XNVMFLASH_H
#define _D5XNVMFLASH_H
#include <stdint.h>
#include <exception>
#include "Flash.h"
class D5xNvmFlash : public Flash
{
public:
D5xNvmFlash(
Samba& samba,
const std::string& name,
uint32_t pages,
uint32_t size,
uint32_t user,
uint32_t stack);
virtual ~D5xNvmFlash();
void eraseAll(uint32_t offset);
void eraseAuto(bool enable);
std::vector<bool> getLockRegions();
bool getSecurity();
bool getBod();
bool canBod() { return true; }
bool getBor();
bool canBor() { return true; }
bool getBootFlash();
bool canBootFlash() { return false; }
void writeOptions();
void writePage(uint32_t page);
void readPage(uint32_t page, uint8_t* data);
void writeBuffer(uint32_t dst_addr, uint32_t size);
protected:
bool _eraseAuto;
uint16_t readRegU16(uint8_t reg);
void writeRegU16(uint8_t reg, uint16_t value);
uint32_t readRegU32(uint8_t reg);
void writeRegU32(uint8_t reg, uint32_t value);
void waitReady();
void command(uint8_t cmd);
void erase(uint32_t offset, uint32_t size);
void checkError();
void readUserPage(std::unique_ptr<uint8_t[]>& userPage);
};
#endif // _D5XNVMFLASH_H

692
lib/bossac/src/Device.cpp Normal file
View File

@@ -0,0 +1,692 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include "Device.h"
#include "EfcFlash.h"
#include "EefcFlash.h"
#include "D2xNvmFlash.h"
#include "D5xNvmFlash.h"
void
Device::readChipId(uint32_t& chipId, uint32_t& extChipId)
{
if ((chipId = _samba.readWord(0x400e0740)) != 0)
{
extChipId = _samba.readWord(0x400e0744);
}
else if ((chipId = _samba.readWord(0x400e0940)) != 0)
{
extChipId = _samba.readWord(0x400e0944);
}
}
void
Device::create()
{
Flash* flashPtr;
uint32_t chipId = 0;
uint32_t cpuId = 0;
uint32_t extChipId = 0;
uint32_t deviceId = 0;
// Device identification must be performed carefully to avoid reading from
// addresses that devices do not support which will lock up the CPU
// All devices support addresss 0 as the ARM reset vector so if the vector is
// a ARM7TDMI branch, then assume we have an Atmel SAM7/9 CHIPID register
if ((_samba.readWord(0x0) & 0xff000000) == 0xea000000)
{
chipId = _samba.readWord(0xfffff240);
}
else
{
// Next try the ARM CPUID register since all Cortex-M devices support it
cpuId = _samba.readWord(0xe000ed00) & 0x0000fff0;
// Cortex-M0+
if (cpuId == 0xC600)
{
// These should support the ARM device ID register
deviceId = _samba.readWord(0x41002018);
}
// Cortex-M4
else if (cpuId == 0xC240)
{
// SAM4 processors have a reset vector to the SAM-BA ROM
if ((_samba.readWord(0x4) & 0xfff00000) == 0x800000)
{
readChipId(chipId, extChipId);
}
// Else we should have a device that supports the ARM device ID register
else
{
deviceId = _samba.readWord(0x41002018);
}
}
// For all other Cortex versions try the Atmel chip ID registers
else
{
readChipId(chipId, extChipId);
}
}
// Instantiate the proper flash for the device
switch (chipId & 0x7fffffe0)
{
//
// SAM7SE
//
case 0x272a0a40:
_family = FAMILY_SAM7SE;
flashPtr = new EfcFlash(_samba, "AT91SAM7SE512", 0x100000, 2048, 256, 2, 32, 0x202000, 0x208000, true);
break;
case 0x272a0940:
_family = FAMILY_SAM7SE;
flashPtr = new EfcFlash(_samba, "AT91SAM7SE256", 0x100000, 1024, 256, 1, 16, 0x202000, 0x208000, true);
break;
case 0x272a0340:
_family = FAMILY_SAM7SE;
flashPtr = new EfcFlash(_samba, "AT91SAM7SE32", 0x100000, 256, 128, 1, 8, 0x201400, 0x201C00, true);
break;
//
// SAM7S
//
case 0x270b0a40:
_family = FAMILY_SAM7S;
flashPtr = new EfcFlash(_samba, "AT91SAM7S512", 0x100000, 2048, 256, 2, 32, 0x202000, 0x210000, false);
break;
case 0x270d0940: // A
case 0x270b0940: // B/C
_family = FAMILY_SAM7S;
flashPtr = new EfcFlash(_samba, "AT91SAM7S256", 0x100000, 1024, 256, 1, 16, 0x202000, 0x210000, false);
break;
case 0x270c0740: // A
case 0x270a0740: // B/C
_family = FAMILY_SAM7S;
flashPtr = new EfcFlash(_samba, "AT91SAM7S128", 0x100000, 512, 256, 1, 8, 0x202000, 0x208000, false);
break;
case 0x27090540:
_family = FAMILY_SAM7S;
flashPtr = new EfcFlash(_samba, "AT91SAM7S64", 0x100000, 512, 128, 1, 16, 0x202000, 0x204000, false);
break;
case 0x27080340:
_family = FAMILY_SAM7S;
flashPtr = new EfcFlash(_samba, "AT91SAM7S32", 0x100000, 256, 128, 1, 8, 0x201400, 0x202000, false);
break;
case 0x27050240:
_family = FAMILY_SAM7S;
flashPtr = new EfcFlash(_samba, "AT91SAM7S16", 0x100000, 256, 64, 1, 8, 0x200000, 0x200e00, false);
break;
//
// SAM7XC
//
case 0x271c0a40:
_family = FAMILY_SAM7XC;
flashPtr = new EfcFlash(_samba, "AT91SAMXC512", 0x100000, 2048, 256, 2, 32, 0x202000, 0x220000, true);
break;
case 0x271b0940:
_family = FAMILY_SAM7XC;
flashPtr = new EfcFlash(_samba, "AT91SAMXC256", 0x100000, 1024, 256, 1, 16, 0x202000, 0x210000, true);
break;
case 0x271a0740:
_family = FAMILY_SAM7XC;
flashPtr = new EfcFlash(_samba, "AT91SAMXC128", 0x100000, 512, 256, 1, 8, 0x202000, 0x208000, true);
break;
//
// SAM7X
//
case 0x275c0a40:
_family = FAMILY_SAM7X;
flashPtr = new EfcFlash(_samba, "AT91SAMX512", 0x100000, 2048, 256, 2, 32, 0x202000, 0x220000, true);
break;
case 0x275b0940:
_family = FAMILY_SAM7X;
flashPtr = new EfcFlash(_samba, "AT91SAMX256", 0x100000, 1024, 256, 1, 16, 0x202000, 0x210000, true);
break;
case 0x275a0740:
_family = FAMILY_SAM7X;
flashPtr = new EfcFlash(_samba, "AT91SAMX128", 0x100000, 512, 256, 1, 8, 0x202000, 0x208000, true);
break;
//
// SAM4S
//
case 0x29870ee0: // A
case 0x29970ee0: // B
case 0x29A70ee0: // C
_family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4SD32", 0x400000, 4096, 512, 2, 256, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x29870c30: // A
case 0x29970c30: // B
case 0x29a70c30: // C
_family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4SD16", 0x400000, 2048, 512, 2, 256, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x28870ce0: // A
case 0x28970ce0: // B
case 0x28A70ce0: // C
_family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4SA16", 0x400000, 2048, 512, 1, 256, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x288c0ce0 : // A
case 0x289c0ce0 : // B
case 0x28ac0ce0 : // C
_family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4S16", 0x400000, 2048, 512, 1, 128, 0x20001000, 0x20020000, 0x400e0a00, false);
break;
case 0x288c0ae0 : // A
case 0x289c0ae0 : // B
case 0x28ac0ae0 : // C
_family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4S8", 0x400000, 1024, 512, 1, 64, 0x20001000, 0x20020000, 0x400e0a00, false);
break;
case 0x288b09e0 : // A
case 0x289b09e0 : // B
case 0x28ab09e0 : // C
_family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4S4", 0x400000, 512, 512, 1, 16, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x288b07e0 : // A
case 0x289b07e0 : // B
case 0x28ab07e0 : // C
_family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4S2", 0x400000, 256, 512, 1, 16, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
//
// SAM3N
//
case 0x29340960 : // A
case 0x29440960 : // B
case 0x29540960 : // C
_family = FAMILY_SAM3N;
flashPtr = new EefcFlash(_samba, "ATSAM3N4", 0x400000, 1024, 256, 1, 16, 0x20001000, 0x20006000, 0x400e0a00, false);
break;
case 0x29390760 : // A
case 0x29490760 : // B
case 0x29590760 : // C
_family = FAMILY_SAM3N;
flashPtr = new EefcFlash(_samba, "ATSAM3N2", 0x400000, 512, 256, 1, 8, 0x20001000, 0x20004000, 0x400e0a00, false);
break;
case 0x29380560 : // A
case 0x29480560 : // B
case 0x29580560 : // C
_family = FAMILY_SAM3N;
flashPtr = new EefcFlash(_samba, "ATSAM3N1", 0x400000, 256, 256, 1, 4, 0x20000800, 0x20002000, 0x400e0a00, false);
break;
case 0x29380360 : // A
case 0x29480360 : // B
case 0x29580360 : // C
_family = FAMILY_SAM3N;
flashPtr = new EefcFlash(_samba, "ATSAM3N0", 0x400000, 128, 256, 1, 1, 0x20000800, 0x20002000, 0x400e0a00, false);
break;
//
// SAM3S
//
case 0x299b0a60 : // B
case 0x29ab0a60 : // C
_family = FAMILY_SAM3S;
flashPtr = new EefcFlash(_samba, "ATSAM3SD8", 0x400000, 2048, 256, 1, 16, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x289b0a60 : // B
case 0x28ab0a60 : // C
_family = FAMILY_SAM3S;
flashPtr = new EefcFlash(_samba, "ATSAM3S8", 0x400000, 2048, 256, 1, 16, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x28800960 : // A
case 0x28900960 : // B
case 0x28a00960 : // C
_family = FAMILY_SAM3S;
flashPtr = new EefcFlash(_samba, "ATSAM3S4", 0x400000, 1024, 256, 1, 16, 0x20001000, 0x2000c000, 0x400e0a00, false);
break;
case 0x288a0760 : // A
case 0x289a0760 : // B
case 0x28aa0760 : // C
_family = FAMILY_SAM3S;
flashPtr = new EefcFlash(_samba, "ATSAM3S2", 0x400000, 512, 256, 1, 8, 0x20000800, 0x20008000, 0x400e0a00, false);
break;
case 0x288a0560 : // A
case 0x289a0560 : // B
case 0x28aa0560 : // C
_family = FAMILY_SAM3S;
flashPtr = new EefcFlash(_samba, "ATSAM3S1", 0x400000, 256, 256, 1, 4, 0x20000800, 0x20004000, 0x400e0a00, false);
break;
//
// SAM3U
//
case 0x28000960 : // C
case 0x28100960 : // E
_family = FAMILY_SAM3U;
flashPtr = new EefcFlash(_samba, "ATSAM3U4", 0xE0000, 1024, 256, 2, 32, 0x20001000, 0x20008000, 0x400e0800, false);
break;
case 0x280a0760 : // C
case 0x281a0760 : // E
_family = FAMILY_SAM3U;
flashPtr = new EefcFlash(_samba, "ATSAM3U2", 0x80000, 512, 256, 1, 16, 0x20001000, 0x20004000, 0x400e0800, false);
break;
case 0x28090560 : // C
case 0x28190560 : // E
_family = FAMILY_SAM3U;
flashPtr = new EefcFlash(_samba, "ATSAM3U1", 0x80000, 256, 256, 1, 8, 0x20001000, 0x20002000, 0x400e0800, false);
break;
//
// SAM3X
//
case 0x286e0a60 : // 8H
case 0x285e0a60 : // 8E
case 0x284e0a60 : // 8C
_family = FAMILY_SAM3X;
flashPtr = new EefcFlash(_samba, "ATSAM3X8", 0x80000, 2048, 256, 2, 32, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x285b0960 : // 4E
case 0x284b0960 : // 4C
_family = FAMILY_SAM3X;
flashPtr = new EefcFlash(_samba, "ATSAM3X4", 0x80000, 1024, 256, 2, 16, 0x20001000, 0x20008000, 0x400e0a00, false);
break;
//
// SAM3A
//
case 0x283e0A60 : // 8C
_family = FAMILY_SAM3A;
flashPtr = new EefcFlash(_samba, "ATSAM3A8", 0x80000, 2048, 256, 2, 32, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x283b0960 : // 4C
_family = FAMILY_SAM3A;
flashPtr = new EefcFlash(_samba, "ATSAM3A4", 0x80000, 1024, 256, 2, 16, 0x20001000, 0x20008000, 0x400e0a00, false);
break;
//
// SAM7L
//
case 0x27330740 :
_family = FAMILY_SAM7L;
flashPtr = new EefcFlash(_samba, "ATSAM7L128", 0x100000, 512, 256, 1, 16, 0x2ffb40, 0x300700, 0xffffff60, false);
break;
case 0x27330540 :
_family = FAMILY_SAM7L;
flashPtr = new EefcFlash(_samba, "ATSAM7L64", 0x100000, 256, 256, 1, 8, 0x2ffb40, 0x300700, 0xffffff60, false);
break;
//
// SAM9XE
//
case 0x329aa3a0 :
_family = FAMILY_SAM9XE;
flashPtr = new EefcFlash(_samba, "ATSAM9XE512", 0x200000, 1024, 512, 1, 32, 0x300000, 0x307000, 0xfffffa00, true);
break;
case 0x329a93a0 :
_family = FAMILY_SAM9XE;
flashPtr = new EefcFlash(_samba, "ATSAM9XE256", 0x200000, 512, 512, 1, 16, 0x300000, 0x307000, 0xfffffa00, true);
break;
case 0x329973a0 :
_family = FAMILY_SAM9XE;
flashPtr = new EefcFlash(_samba, "ATSAM9XE128", 0x200000, 256, 512, 1, 8, 0x300000, 0x303000, 0xfffffa00, true);
break;
//
// SAM4E
//
case 0x23cc0ce0:
switch (extChipId)
{
case 0x00120200: // E
case 0x00120201: // C
_family = FAMILY_SAM4E;
flashPtr = new EefcFlash(_samba, "ATSAM4E16", 0x400000, 2048, 512, 1, 128, 0x20001000, 0x20020000, 0x400e0a00, false);
break;
case 0x00120208: // E
case 0x00120209: // C
_family = FAMILY_SAM4E;
flashPtr = new EefcFlash(_samba, "ATSAM4E8", 0x400000, 1024, 512, 1, 64, 0x20001000, 0x20020000, 0x400e0a00, false);
break;
}
break;
//
// SAME70
//
case 0x210d0a00:
_family = FAMILY_SAME70;
flashPtr = new EefcFlash(_samba, "ATSAME70x19", 0x400000, 1024, 512, 1, 32, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21020c00:
_family = FAMILY_SAME70;
flashPtr = new EefcFlash(_samba, "ATSAME70x20", 0x400000, 2048, 512, 1, 64, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21020e00:
_family = FAMILY_SAME70;
flashPtr = new EefcFlash(_samba, "ATSAME70x21", 0x400000, 4096, 512, 1, 128, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
//
// SAMS70
//
case 0x211d0a00:
_family = FAMILY_SAMS70;
flashPtr = new EefcFlash(_samba, "ATSAMS70x19", 0x400000, 1024, 512, 1, 32, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21120c00:
_family = FAMILY_SAMS70;
flashPtr = new EefcFlash(_samba, "ATSAMS70x20", 0x400000, 2048, 512, 1, 64, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21120e00:
_family = FAMILY_SAMS70;
flashPtr = new EefcFlash(_samba, "ATSAMS70x21", 0x400000, 4096, 512, 1, 128, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
//
// SAMV70
//
case 0x213d0a00:
_family = FAMILY_SAMV70;
flashPtr = new EefcFlash(_samba, "ATSAMV70x19", 0x400000, 1024, 512, 1, 32, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21320c00:
_family = FAMILY_SAMV70;
flashPtr = new EefcFlash(_samba, "ATSAMV70x20", 0x400000, 2048, 512, 1, 64, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
//
// SAMV71
//
case 0x212d0a00:
_family = FAMILY_SAMV71;
flashPtr = new EefcFlash(_samba, "ATSAMV71x19", 0x400000, 1024, 512, 1, 32, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21220c00:
_family = FAMILY_SAMV71;
flashPtr = new EefcFlash(_samba, "ATSAMV71x20", 0x400000, 2048, 512, 1, 64, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21220e00:
_family = FAMILY_SAMV71;
flashPtr = new EefcFlash(_samba, "ATSAMV71x21", 0x400000, 4096, 512, 1, 128, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
//
// No CHIPID devices
//
case 0:
switch (deviceId & 0xffff00ff)
{
//
// SAMD21
//
case 0x10010003: // J15A
case 0x10010008: // G15A
case 0x1001000d: // E15A
case 0x10010021: // J15B
case 0x10010024: // G15B
case 0x10010027: // E15B
case 0x10010056: // E15B WLCSP
case 0x10010063: // E15C WLCSP
_family = FAMILY_SAMD21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x15", 512, 64, 0x20000800, 0x20001000) ;
break;
case 0x10010002: // J16A
case 0x10010007: // G16A
case 0x1001000c: // E16A
case 0x10010020: // J16B
case 0x10010023: // G16B
case 0x10010026: // E16B
case 0x10010055: // E16B WLCSP
case 0x10010062: // E16C WLCSP
_family = FAMILY_SAMD21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x16", 1024, 64, 0x20001000, 0x20002000) ;
break;
case 0x10010001: // J17A
case 0x10010006: // G17A
case 0x1001000b: // E17A
case 0x10010010: // G17A WLCSP
_family = FAMILY_SAMD21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x17", 2048, 64, 0x20002000, 0x20004000) ;
break;
case 0x10010000: // J18A
case 0x10010005: // G18A
case 0x1001000a: // E18A
case 0x1001000f: // G18A WLCSP
_family = FAMILY_SAMD21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x18", 4096, 64, 0x20004000, 0x20008000) ;
break;
//
// SAMR21
//
case 0x1001001e: // E16A
case 0x1001001b: // G16A
_family = FAMILY_SAMR21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x16", 1024, 64, 0x20001000, 0x20002000) ;
break;
case 0x1001001d: // E17A
case 0x1001001a: // G17A
_family = FAMILY_SAMR21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x17", 2048, 64, 0x20002000, 0x20004000) ;
break;
case 0x1001001c: // E18A
case 0x10010019: // G18A
_family = FAMILY_SAMR21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x18", 4096, 64, 0x20004000, 0x20008000) ;
break;
case 0x10010018: // E19A
_family = FAMILY_SAMR21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x19", 4096, 64, 0x20004000, 0x20008000) ;
break;
//
// SAML21
//
case 0x1081000d: // E15A
case 0x1081001c: // E15B
_family = FAMILY_SAMD21;
flashPtr = new D2xNvmFlash(_samba, "ATSAML21x15", 512, 64, 0x20000800, 0x20001000) ;
break;
case 0x10810002: // J16A
case 0x10810007: // G16A
case 0x1081000c: // E16A
case 0x10810011: // J16B
case 0x10810016: // G16B
case 0x1081001b: // E16B
_family = FAMILY_SAML21;
flashPtr = new D2xNvmFlash(_samba, "ATSAML21x16", 1024, 64, 0x20001000, 0x20002000) ;
break;
case 0x10810001: // J17A
case 0x10810006: // G17A
case 0x1081000b: // E17A
case 0x10810010: // J17B
case 0x10810015: // G17B
case 0x1081001a: // E17B
_family = FAMILY_SAML21;
flashPtr = new D2xNvmFlash(_samba, "ATSAML21x17", 2048, 64, 0x20002000, 0x20004000) ;
break;
case 0x10810000: // J18A
case 0x10810005: // G18A
case 0x1081000a: // E18A
case 0x1081000f: // J18B
case 0x10810014: // G18B
case 0x10810019: // E18B
_family = FAMILY_SAML21;
flashPtr = new D2xNvmFlash(_samba, "ATSAML21x18", 4096, 64, 0x20004000, 0x20008000) ;
break;
//
// SAMD51
//
case 0x60060006: // J18A
case 0x60060008: // G18A
_family = FAMILY_SAMD51;
flashPtr = new D5xNvmFlash(_samba, "ATSAMD51x18", 512, 512, 0x20004000, 0x20008000) ;
break;
case 0x60060001: // P19A
case 0x60060003: // N19A
case 0x60060005: // J19A
case 0x60060007: // G19A
_family = FAMILY_SAMD51;
flashPtr = new D5xNvmFlash(_samba, "ATSAMD51x19", 1024, 512, 0x20004000, 0x20008000) ;
break;
case 0x60060000: // P20A
case 0x60060002: // N20A
case 0x60060004: // J20A
_family = FAMILY_SAMD51;
flashPtr = new D5xNvmFlash(_samba, "ATSAMD51x20", 2048, 512, 0x20004000, 0x20008000) ;
break;
//
// SAME51
//
case 0x61810003: // J18A
_family = FAMILY_SAME51;
flashPtr = new D5xNvmFlash(_samba, "ATSAME51x18", 512, 512, 0x20004000, 0x20008000) ;
break;
case 0x61810002: // J19A
case 0x61810001: // N19A
_family = FAMILY_SAME51;
flashPtr = new D5xNvmFlash(_samba, "ATSAME51x19", 1024, 512, 0x20004000, 0x20008000) ;
break;
case 0x61810004: // J20A
case 0x61810000: // N20A
_family = FAMILY_SAME51;
flashPtr = new D5xNvmFlash(_samba, "ATSAME51x20", 2048, 512, 0x20004000, 0x20008000) ;
break;
//
// SAME53
//
case 0x61830006: // J18A
_family = FAMILY_SAME53;
flashPtr = new D5xNvmFlash(_samba, "ATSAME53x18", 512, 512, 0x20004000, 0x20008000) ;
break;
case 0x61830005: // J19A
case 0x61830003: // N19A
_family = FAMILY_SAME53;
flashPtr = new D5xNvmFlash(_samba, "ATSAME53x19", 1024, 512, 0x20004000, 0x20008000) ;
break;
case 0x61830004: // J20A
case 0x61830002: // N20A
_family = FAMILY_SAME53;
flashPtr = new D5xNvmFlash(_samba, "ATSAME53x20", 2048, 512, 0x20004000, 0x20008000) ;
break;
//
// SAME54
//
case 0x61840001: // P19A
case 0x61840003: // N19A
_family = FAMILY_SAME54;
flashPtr = new D5xNvmFlash(_samba, "ATSAME54x19", 1024, 512, 0x20004000, 0x20008000) ;
break;
case 0x61840000: // P20A
case 0x61840002: // N20A
_family = FAMILY_SAME54;
flashPtr = new D5xNvmFlash(_samba, "ATSAME54x20", 2048, 512, 0x20004000, 0x20008000) ;
break;
//
// Unknown
//
default:
throw DeviceUnsupportedError();
break;
}
break;
//
// Unsupported device
//
default:
throw DeviceUnsupportedError();
break;
}
_flash = std::unique_ptr<Flash>(flashPtr);
}
void
Device::reset()
{
try
{
switch (_family)
{
case FAMILY_SAMD21:
case FAMILY_SAMR21:
case FAMILY_SAML21:
case FAMILY_SAMD51:
case FAMILY_SAME51:
case FAMILY_SAME53:
case FAMILY_SAME54:
case FAMILY_SAME70:
case FAMILY_SAMS70:
case FAMILY_SAMV70:
case FAMILY_SAMV71:
_samba.writeWord(0xE000ED0C, 0x05FA0004);
break;
case FAMILY_SAM3X:
case FAMILY_SAM3S:
case FAMILY_SAM3A:
_samba.writeWord(0x400E1A00, 0xA500000D);
break;
case FAMILY_SAM3U:
_samba.writeWord(0x400E1200, 0xA500000D);
break;
case FAMILY_SAM3N:
case FAMILY_SAM4S:
_samba.writeWord(0x400E1400, 0xA500000D);
break;
case FAMILY_SAM4E:
_samba.writeWord(0x400E1800, 0xA500000D);
break;
case FAMILY_SAM7S:
case FAMILY_SAM7SE:
case FAMILY_SAM7X:
case FAMILY_SAM7XC:
case FAMILY_SAM7L:
case FAMILY_SAM9XE:
_samba.writeWord(0xFFFFFD00, 0xA500000D);
break;
default:
break;
}
}
catch (std::exception& expected)
{ // writeWord will most likely throw an exception when the CPU is reset
}
}

104
lib/bossac/src/Device.h Normal file
View File

@@ -0,0 +1,104 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _DEVICE_H
#define _DEVICE_H
#include <exception>
#include "Samba.h"
#include "Flash.h"
class DeviceUnsupportedError : public std::exception
{
public:
DeviceUnsupportedError() : exception() {};
const char* what() const throw() { return "Device unsupported"; }
};
class Device
{
public:
enum Family {
FAMILY_NONE,
FAMILY_SAM7S,
FAMILY_SAM7SE,
FAMILY_SAM7X,
FAMILY_SAM7XC,
FAMILY_SAM7L,
FAMILY_SAM3N,
FAMILY_SAM3S,
FAMILY_SAM3U,
FAMILY_SAM3X,
FAMILY_SAM3A,
FAMILY_SAM4S,
FAMILY_SAM4E,
FAMILY_SAM9XE,
FAMILY_SAMD21,
FAMILY_SAMR21,
FAMILY_SAML21,
FAMILY_SAMD51,
FAMILY_SAME51,
FAMILY_SAME53,
FAMILY_SAME54,
FAMILY_SAME70,
FAMILY_SAMS70,
FAMILY_SAMV70,
FAMILY_SAMV71,
};
Device(Samba& samba) : _samba(samba), _flash(nullptr), _family(FAMILY_NONE) {}
virtual ~Device() {}
void create();
Family getFamily() { return _family; }
typedef std::unique_ptr<Flash> const FlashPtr;
FlashPtr& getFlash() { return _flash; }
void reset();
private:
Samba& _samba;
std::unique_ptr<Flash> _flash;
Family _family;
void readChipId(uint32_t& chipId, uint32_t& extChipId);
};
#endif // _DEVICE_H

View File

@@ -0,0 +1,363 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include "EefcFlash.h"
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#define EEFC_KEY 0x5a
#define EEFC0_FMR (_regs + 0x00)
#define EEFC0_FCR (_regs + 0x04)
#define EEFC0_FSR (_regs + 0x08)
#define EEFC0_FRR (_regs + 0x0C)
#define EEFC1_FMR (_regs + 0x200)
#define EEFC1_FCR (_regs + 0x204)
#define EEFC1_FSR (_regs + 0x208)
#define EEFC1_FRR (_regs + 0x20C)
#define EEFC_FCMD_GETD 0x0
#define EEFC_FCMD_WP 0x1
#define EEFC_FCMD_WPL 0x2
#define EEFC_FCMD_EWP 0x3
#define EEFC_FCMD_EWPL 0x4
#define EEFC_FCMD_EA 0x5
#define EEFC_FCMD_EPA 0x7
#define EEFC_FCMD_SLB 0x8
#define EEFC_FCMD_CLB 0x9
#define EEFC_FCMD_GLB 0xa
#define EEFC_FCMD_SGPB 0xb
#define EEFC_FCMD_CGPB 0xc
#define EEFC_FCMD_GGPB 0xd
const uint32_t
EefcFlash::PagesPerErase = 8;
EefcFlash::EefcFlash(Samba& samba,
const std::string& name,
uint32_t addr,
uint32_t pages,
uint32_t size,
uint32_t planes,
uint32_t lockRegions,
uint32_t user,
uint32_t stack,
uint32_t regs,
bool canBrownout)
: Flash(samba, name, addr, pages, size, planes, lockRegions, user, stack),
_regs(regs), _canBrownout(canBrownout), _eraseAuto(true)
{
assert(planes == 1 || planes == 2);
assert(pages <= 4096);
assert(lockRegions <= 256);
// SAM3 Errata (FWS must be 6)
_samba.writeWord(EEFC0_FMR, 0x6 << 8);
if (planes == 2)
_samba.writeWord(EEFC1_FMR, 0x6 << 8);
}
EefcFlash::~EefcFlash()
{
}
void
EefcFlash::eraseAll(uint32_t offset)
{
// Do a full chip erase if the offset is 0
if (offset == 0)
{
waitFSR();
writeFCR0(EEFC_FCMD_EA, 0);
if (_planes == 2)
{
waitFSR();
writeFCR1(EEFC_FCMD_EA, 0);
}
// Erase all can take an exceptionally long time on some devices
// so wait on FSR for up to 30 seconds
waitFSR(30);
}
// Else we must do it by pages
else
{
// Offset must be on an erase page boundary
if (offset % (_size * PagesPerErase))
throw FlashEraseError();
// Erase each PagesPerErase set of pages
for (uint32_t pageNum = offset / _size; pageNum < _pages; pageNum += PagesPerErase)
{
if (_planes == 1 || pageNum < _pages / 2)
{
waitFSR();
writeFCR0(EEFC_FCMD_EPA, pageNum | 0x1);
}
else
{
waitFSR();
writeFCR1(EEFC_FCMD_EPA, (pageNum % (_pages / 2)) | 0x1);
}
}
}
}
void
EefcFlash::eraseAuto(bool enable)
{
_eraseAuto = enable;
}
std::vector<bool>
EefcFlash::getLockRegions()
{
std::vector<bool> regions(_lockRegions);
uint32_t frr;
uint32_t bit;
waitFSR();
for (uint32_t region = 0; region < _lockRegions; region++)
{
if (_planes == 2 && region >= _lockRegions / 2)
{
bit = region - _lockRegions / 2;
writeFCR1(EEFC_FCMD_GLB, 0);
waitFSR();
frr = readFRR1();
while (bit >= 32)
{
frr = readFRR1();
bit -= 32;
}
regions[region] = (frr & (1 << bit)) != 0;
}
else
{
bit = region;
writeFCR0(EEFC_FCMD_GLB, 0);
waitFSR();
frr = readFRR0();
while (bit >= 32)
{
frr = readFRR0();
bit -= 32;
}
regions[region] = (frr & (1 << bit)) != 0;
}
}
return regions;
}
bool
EefcFlash::getSecurity()
{
waitFSR();
writeFCR0(EEFC_FCMD_GGPB, 0);
waitFSR();
return (readFRR0() & (1 << 0));
}
bool
EefcFlash::getBod()
{
if (!_canBrownout)
return false;
waitFSR();
writeFCR0(EEFC_FCMD_GGPB, 0);
waitFSR();
return (readFRR0() & (1 << 1));
}
bool
EefcFlash::getBor()
{
if (!_canBrownout)
return false;
waitFSR();
writeFCR0(EEFC_FCMD_GGPB, 0);
waitFSR();
return (readFRR0() & (1 << 2));
}
bool
EefcFlash::getBootFlash()
{
waitFSR();
writeFCR0(EEFC_FCMD_GGPB, 0);
waitFSR();
return (readFRR0() & (1 << (_canBrownout ? 3 : 1)));
}
void
EefcFlash::writeOptions()
{
if (canBootFlash() && _bootFlash.isDirty() && _bootFlash.get() != getBootFlash())
{
waitFSR();
writeFCR0(_bootFlash.get() ? EEFC_FCMD_SGPB : EEFC_FCMD_CGPB, (canBod() ? 3 : 1));
}
if (canBor() && _bor.isDirty() && _bor.get() != getBor())
{
waitFSR();
writeFCR0(_bor.get() ? EEFC_FCMD_SGPB : EEFC_FCMD_CGPB, 2);
}
if (canBod() && _bod.isDirty() && _bod.get() != getBod())
{
waitFSR();
writeFCR0(_bod.get() ? EEFC_FCMD_SGPB : EEFC_FCMD_CGPB, 1);
}
if (_regions.isDirty())
{
uint32_t page;
std::vector<bool> current;
if (_regions.get().size() >= _lockRegions)
throw FlashRegionError();
current = getLockRegions();
for (uint32_t region = 0; region < _lockRegions; region++)
{
if (_regions.get()[region] != current[region])
{
if (_planes == 2 && region >= _lockRegions / 2)
{
page = (region - _lockRegions / 2) * _pages / _lockRegions;
waitFSR();
writeFCR1(_regions.get()[region] ? EEFC_FCMD_SLB : EEFC_FCMD_CLB, page);
}
else
{
page = region * _pages / _lockRegions;
waitFSR();
writeFCR0(_regions.get()[region] ? EEFC_FCMD_SLB : EEFC_FCMD_CLB, page);
}
}
}
}
if (_security.isDirty() && _security.get() == true && _security.get() != getSecurity())
{
waitFSR();
writeFCR0(EEFC_FCMD_SGPB, 0);
}
}
void
EefcFlash::writePage(uint32_t page)
{
if (page >= _pages)
throw FlashPageError();
_wordCopy.setDstAddr(_addr + page * _size);
_wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
_onBufferA = !_onBufferA;
waitFSR();
_wordCopy.runv();
if (_planes == 2 && page >= _pages / 2)
writeFCR1(_eraseAuto ? EEFC_FCMD_EWP : EEFC_FCMD_WP, page - _pages / 2);
else
writeFCR0(_eraseAuto ? EEFC_FCMD_EWP : EEFC_FCMD_WP, page);
}
void
EefcFlash::readPage(uint32_t page, uint8_t* data)
{
if (page >= _pages)
throw FlashPageError();
// The SAM3 firmware has a bug where it returns all zeros for reads
// directly from the flash so instead, we copy the flash page to
// SRAM and read it from there.
_wordCopy.setDstAddr(_onBufferA ? _pageBufferA : _pageBufferB);
_wordCopy.setSrcAddr(_addr + page * _size);
waitFSR();
_wordCopy.runv();
_samba.read(_onBufferA ? _pageBufferA : _pageBufferB, data, _size);
}
void
EefcFlash::waitFSR(int seconds)
{
int tries = seconds * 1000;
uint32_t fsr0;
uint32_t fsr1 = 0x1;
while (tries-- > 0)
{
fsr0 = _samba.readWord(EEFC0_FSR);
if (fsr0 & 0x2)
throw FlashCmdError();
if (fsr0 & 0x4)
throw FlashLockError();
if (_planes == 2)
{
fsr1 = _samba.readWord(EEFC1_FSR);
if (fsr1 & 0x2)
throw FlashCmdError();
if (fsr1 & 0x4)
throw FlashLockError();
}
if (fsr0 & fsr1 & 0x1)
break;
usleep(1000);
}
if (tries == 0)
throw FlashTimeoutError();
}
void
EefcFlash::writeFCR0(uint8_t cmd, uint32_t arg)
{
_samba.writeWord(EEFC0_FCR, (EEFC_KEY << 24) | (arg << 8) | cmd);
}
void
EefcFlash::writeFCR1(uint8_t cmd, uint32_t arg)
{
_samba.writeWord(EEFC1_FCR, (EEFC_KEY << 24) | (arg << 8) | cmd);
}
uint32_t
EefcFlash::readFRR0()
{
return _samba.readWord(EEFC0_FRR);
}
uint32_t
EefcFlash::readFRR1()
{
return _samba.readWord(EEFC1_FRR);
}

View File

@@ -0,0 +1,88 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _EEFCFLASH_H
#define _EEFCFLASH_H
#include <stdint.h>
#include <exception>
#include "Flash.h"
class EefcFlash : public Flash
{
public:
EefcFlash(Samba& samba,
const std::string& name,
uint32_t addr,
uint32_t pages,
uint32_t size,
uint32_t planes,
uint32_t lockRegions,
uint32_t user,
uint32_t stack,
uint32_t regs,
bool canBrownout);
virtual ~EefcFlash();
void eraseAll(uint32_t offset);
void eraseAuto(bool enable);
std::vector<bool> getLockRegions();
bool getSecurity();
bool getBod();
bool canBod() { return _canBrownout; }
bool getBor();
bool canBor() { return _canBrownout; }
bool getBootFlash();
bool canBootFlash() { return true; }
void writeOptions();
void writePage(uint32_t page);
void readPage(uint32_t page, uint8_t* data);
static const uint32_t PagesPerErase;
private:
uint32_t _regs;
bool _canBrownout;
bool _eraseAuto;
void waitFSR(int seconds = 1);
void writeFCR0(uint8_t cmd, uint32_t arg);
void writeFCR1(uint8_t cmd, uint32_t arg);
uint32_t readFRR0();
uint32_t readFRR1();
};
#endif // _EEFCFLASH_H

295
lib/bossac/src/EfcFlash.cpp Normal file
View File

@@ -0,0 +1,295 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include "EfcFlash.h"
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#define EFC_KEY 0x5a
#define EFC0_FMR 0xffffff60
#define EFC0_FCR 0xffffff64
#define EFC0_FSR 0xffffff68
#define EFC1_FMR 0xffffff70
#define EFC1_FCR 0xffffff74
#define EFC1_FSR 0xffffff78
#define EFC_FCMD_WP 0x1
#define EFC_FCMD_SLB 0x2
#define EFC_FCMD_WPL 0x3
#define EFC_FCMD_CLB 0x4
#define EFC_FCMD_EA 0x8
#define EFC_FCMD_SGPB 0xb
#define EFC_FCMD_CGPB 0xd
#define EFC_FCMD_SSB 0xf
EfcFlash::EfcFlash(Samba& samba,
const std::string& name,
uint32_t addr,
uint32_t pages,
uint32_t size,
uint32_t planes,
uint32_t lockRegions,
uint32_t user,
uint32_t stack,
bool canBootFlash)
: Flash(samba, name, addr, pages, size, planes, lockRegions, user, stack),
_canBootFlash(canBootFlash)
{
assert(planes == 1 || planes == 2);
assert(pages <= planes * 1024);
assert(lockRegions <= 32);
eraseAuto(true);
}
EfcFlash::~EfcFlash()
{
}
void
EfcFlash::eraseAll(uint32_t offset)
{
if (offset != 0)
throw FlashEraseError();
waitFSR();
writeFCR0(EFC_FCMD_EA, 0);
if (_planes == 2)
{
waitFSR();
writeFCR0(EFC_FCMD_EA, _pages / 2);
}
}
void
EfcFlash::eraseAuto(bool enable)
{
uint32_t fmr;
waitFSR();
fmr = _samba.readWord(EFC0_FMR);
if (enable)
fmr &= ~(1 << 7);
else
fmr |= (1 << 7);
_samba.writeWord(EFC0_FMR, fmr);
if (_planes == 2)
{
waitFSR();
_samba.writeWord(EFC1_FMR, fmr);
}
}
std::vector<bool>
EfcFlash::getLockRegions()
{
std::vector<bool> regions(_lockRegions);
uint32_t fsr0;
uint32_t fsr1;
fsr0 = readFSR0();
if (_planes == 2)
fsr1 = readFSR1();
else
fsr1 = 0;
for (uint32_t region = 0; region < _lockRegions; region++)
{
if (_planes == 2 && region >= _lockRegions / 2)
regions[region] = (fsr1 & (1 << (16 + region - _lockRegions / 2))) != 0;
else
regions[region] = (fsr0 & (1 << (16 + region))) != 0;
}
return regions;
}
bool
EfcFlash::getSecurity()
{
return (readFSR0() & (1 << 4));
}
bool
EfcFlash::getBod()
{
return (readFSR0() & (1 << 8));
}
bool
EfcFlash::getBor()
{
return (readFSR0() & (2 << 8));
}
bool
EfcFlash::getBootFlash()
{
if (!_canBootFlash)
return false;
return (readFSR0() & (1 << 10));
}
void
EfcFlash::writeOptions()
{
if (canBootFlash() && _bootFlash.isDirty() && _bootFlash.get() != getBootFlash())
{
waitFSR();
writeFCR0(_bootFlash.get() ? EFC_FCMD_SGPB : EFC_FCMD_CGPB, 2);
}
if (canBor() && _bor.isDirty() && _bor.get() != getBor())
{
waitFSR();
writeFCR0(_bor.get() ? EFC_FCMD_SGPB : EFC_FCMD_CGPB, 1);
}
if (canBod() && _bod.isDirty() && _bod.get() != getBod())
{
waitFSR();
writeFCR0(_bod.get() ? EFC_FCMD_SGPB : EFC_FCMD_CGPB, 0);
}
if (_regions.isDirty())
{
uint32_t page;
std::vector<bool> current;
current = getLockRegions();
for (uint32_t region = 0; region < _regions.get().size(); region++)
{
if (_regions.get()[region] != current[region])
{
if (_planes == 2 && region >= _lockRegions / 2)
{
page = (region - _lockRegions / 2) * _pages / _lockRegions;
waitFSR();
writeFCR1(_regions.get()[region] ? EFC_FCMD_SLB : EFC_FCMD_CLB, page);
}
else
{
page = region * _pages / _lockRegions;
waitFSR();
writeFCR0(_regions.get()[region] ? EFC_FCMD_SLB : EFC_FCMD_CLB, page);
}
}
}
}
if (_security.isDirty() && _security.get() == true && _security.get() != getSecurity())
{
waitFSR();
writeFCR0(EFC_FCMD_SSB, 0);
}
}
void
EfcFlash::writePage(uint32_t page)
{
if (page >= _pages)
throw FlashPageError();
_wordCopy.setDstAddr(_addr + page * _size);
_wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
_onBufferA = !_onBufferA;
waitFSR();
_wordCopy.run();
if (_planes == 2 && page >= _pages / 2)
writeFCR1(EFC_FCMD_WP, page - _pages / 2);
else
writeFCR0(EFC_FCMD_WP, page);
}
void
EfcFlash::readPage(uint32_t page, uint8_t* data)
{
if (page >= _pages)
throw FlashPageError();
waitFSR();
_samba.read(_addr + page * _size, data, _size);
}
void
EfcFlash::waitFSR(int seconds)
{
int tries = seconds * 1000;
uint32_t fsr0;
uint32_t fsr1 = 0x1;
while (tries-- > 0)
{
fsr0 = readFSR0();
if (fsr0 & 0x2)
throw FlashCmdError();
if (fsr0 & 0x4)
throw FlashLockError();
if (_planes == 2)
{
fsr1 = readFSR1();
if (fsr1 & 0x2)
throw FlashCmdError();
if (fsr1 & 0x4)
throw FlashLockError();
}
if (fsr0 & fsr1 & 0x1)
break;
usleep(1000);
}
if (tries == 0)
throw FlashTimeoutError();
}
void
EfcFlash::writeFCR0(uint8_t cmd, uint32_t arg)
{
_samba.writeWord(EFC0_FCR, (EFC_KEY << 24) | (arg << 8) | cmd);
}
void
EfcFlash::writeFCR1(uint8_t cmd, uint32_t arg)
{
_samba.writeWord(EFC1_FCR, (EFC_KEY << 24) | (arg << 8) | cmd);
}
uint32_t
EfcFlash::readFSR0()
{
return _samba.readWord(EFC0_FSR);
}
uint32_t
EfcFlash::readFSR1()
{
return _samba.readWord(EFC1_FSR);
}

83
lib/bossac/src/EfcFlash.h Normal file
View File

@@ -0,0 +1,83 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _EFCFLASH_H
#define _EFCFLASH_H
#include <stdint.h>
#include <exception>
#include "Flash.h"
class EfcFlash : public Flash
{
public:
EfcFlash(Samba& samba,
const std::string& name,
uint32_t addr,
uint32_t pages,
uint32_t size,
uint32_t planes,
uint32_t lockRegions,
uint32_t user,
uint32_t stack,
bool canBootFlash);
virtual ~EfcFlash();
void eraseAll(uint32_t offset);
void eraseAuto(bool enable);
std::vector<bool> getLockRegions();
bool getSecurity();
bool getBod();
bool canBod() { return true; }
bool getBor();
bool canBor() { return true; }
bool getBootFlash();
bool canBootFlash() { return _canBootFlash; }
void writeOptions();
void writePage(uint32_t page);
void readPage(uint32_t page, uint8_t* data);
private:
bool _canBootFlash;
void waitFSR(int seconds = 1);
void writeFCR0(uint8_t cmd, uint32_t arg);
void writeFCR1(uint8_t cmd, uint32_t arg);
uint32_t readFSR0();
uint32_t readFSR1();
};
#endif // _EFCFLASH_H

View File

@@ -0,0 +1,94 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _FILEERROR_H
#define _FILEERROR_H
#include <exception>
#include <errno.h>
#include <string.h>
#include "Flash.h"
#include "Samba.h"
class FileError : public std::exception
{
public:
FileError() : std::exception() {}
};
class FileOpenError : public FileError
{
public:
FileOpenError() : FileError(), _errnum(0) {};
FileOpenError(int errnum) : FileError(), _errnum(errnum) {};
const char* what() const throw()
{
if (_errnum == 0)
return "Unable to open file";
else
return strerror(_errnum);
}
private:
int _errnum;
};
class FileIoError : public FileError
{
public:
FileIoError() : FileError(), _errnum(0) {};
FileIoError(int errnum) : FileError(), _errnum(errnum) {};
const char* what() const throw()
{
if (_errnum == 0)
return "File I/O operation failed";
else
return strerror(_errnum);
}
private:
int _errnum;
};
class FileShortError : public FileError
{
public:
FileShortError() : FileError() {};
const char* what() const throw()
{
return "Operation ended with a short write";
}
};
class FileSizeError : public FileError
{
public:
FileSizeError() {};
const char* what() const throw() { return "File operation exceeds flash size"; }
};
#endif // _FILEERROR_H

106
lib/bossac/src/Flash.cpp Normal file
View File

@@ -0,0 +1,106 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include "Flash.h"
#include <assert.h>
Flash::Flash(Samba& samba,
const std::string& name,
uint32_t addr,
uint32_t pages,
uint32_t size,
uint32_t planes,
uint32_t lockRegions,
uint32_t user,
uint32_t stack)
: _samba(samba), _name(name), _addr(addr), _pages(pages), _size(size),
_planes(planes), _lockRegions(lockRegions), _user(user), _wordCopy(samba, user)
{
assert((size & (size - 1)) == 0);
assert((pages & (pages - 1)) == 0);
assert((lockRegions & (lockRegions - 1)) == 0);
_wordCopy.setWords(size / sizeof(uint32_t));
_wordCopy.setStack(stack);
_onBufferA = true;
// page buffers will have the size of a physical page and will be situated right after the applet
_pageBufferA = ((_user + _wordCopy.size() + 3) / 4) * 4; // we need to avoid non 32bits aligned access on Cortex-M0+
_pageBufferB = _pageBufferA + size;
}
void
Flash::setLockRegions(const std::vector<bool>& regions)
{
if (regions.size() > _lockRegions)
throw FlashRegionError();
_regions.set(regions);
}
void
Flash::setSecurity()
{
_security.set(true);
}
void
Flash::setBor(bool enable)
{
if (canBor())
_bor.set(enable);
}
void
Flash::setBod(bool enable)
{
if (canBod())
_bod.set(enable);
}
void
Flash::setBootFlash(bool enable)
{
if (canBootFlash())
_bootFlash.set(enable);
}
void
Flash::loadBuffer(const uint8_t* data, uint16_t bufferSize)
{
_samba.write(_onBufferA ? _pageBufferA : _pageBufferB, data, bufferSize);
}
void
Flash::writeBuffer(uint32_t dst_addr, uint32_t size)
{
_samba.writeBuffer(_onBufferA ? _pageBufferA : _pageBufferB, dst_addr + _addr, size);
}

180
lib/bossac/src/Flash.h Normal file
View File

@@ -0,0 +1,180 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _FLASH_H
#define _FLASH_H
#include <stdint.h>
#include <vector>
#include <memory>
#include <exception>
#include "Samba.h"
#include "WordCopyApplet.h"
class FlashPageError : public std::exception
{
public:
FlashPageError() : exception() {};
const char* what() const throw() { return "Invalid flash page"; }
};
class FlashRegionError : public std::exception
{
public:
FlashRegionError() : exception() {};
const char* what() const throw() { return "Invalid lock region"; }
};
class FlashLockError : public std::exception
{
public:
FlashLockError() : exception() {};
const char* what() const throw() { return "Flash page is locked"; }
};
class FlashCmdError : public std::exception
{
public:
FlashCmdError() : exception() {};
const char* what() const throw() { return "Flash command failed"; }
};
class FlashTimeoutError : public std::exception
{
public:
FlashTimeoutError() : exception() {};
const char* what() const throw() { return "Flash command timeout"; }
};
class BootFlashError : public std::exception
{
public:
BootFlashError() : exception() {};
const char* what() const throw() { return "Unable to clear boot flash for this device"; }
};
class FlashEraseError : public std::exception
{
public:
FlashEraseError() : exception() {};
const char* what() const throw() { return "Flash erase failed"; }
};
template<class T>
class FlashOption
{
public:
FlashOption() : _dirty(false) {}
virtual ~FlashOption() {}
void set(const T& value) { _value = value; _dirty = true; }
const T& get() { return _value; }
bool isDirty() { return _dirty; }
private:
T _value;
bool _dirty;
};
class Flash
{
public:
Flash(Samba& samba,
const std::string& name,
uint32_t addr, // Flash base address
uint32_t pages, // Number of pages
uint32_t size, // Page size in bytes
uint32_t planes, // Number of flash planes
uint32_t lockRegions, // Number of flash lock regions
uint32_t user, // Address in SRAM where the applet and buffers will be placed
uint32_t stack); // Address in SRAM where the applet stack will be placed
virtual ~Flash() {}
const std::string& name() { return _name; }
virtual uint32_t address() { return _addr; }
virtual uint32_t pageSize() { return _size; }
virtual uint32_t numPages() { return _pages; }
virtual uint32_t numPlanes() { return _planes; }
virtual uint32_t totalSize() { return _size * _pages; }
virtual uint32_t lockRegions() { return _lockRegions; }
virtual void eraseAll(uint32_t offset) = 0;
virtual void eraseAuto(bool enable) = 0;
virtual std::vector<bool> getLockRegions() = 0;
virtual void setLockRegions(const std::vector<bool>& regions);
virtual bool getSecurity() = 0;
virtual void setSecurity();
virtual bool getBod() = 0;
virtual void setBod(bool enable);
virtual bool canBod() = 0;
virtual bool getBor() = 0;
virtual void setBor(bool enable);
virtual bool canBor() = 0;
virtual bool getBootFlash() = 0;
virtual void setBootFlash(bool enable);
virtual bool canBootFlash() = 0;
virtual void writeOptions() = 0;
virtual void writePage(uint32_t page) = 0;
virtual void readPage(uint32_t page, uint8_t* data) = 0;
virtual void writeBuffer(uint32_t dst_addr, uint32_t size);
virtual void loadBuffer(const uint8_t* data, uint16_t size);
protected:
Samba& _samba;
std::string _name;
uint32_t _addr;
uint32_t _pages;
uint32_t _size;
uint32_t _planes;
uint32_t _lockRegions;
uint32_t _user;
WordCopyApplet _wordCopy;
FlashOption<bool> _bootFlash;
FlashOption< std::vector<bool> > _regions;
FlashOption<bool> _bod;
FlashOption<bool> _bor;
FlashOption<bool> _security;
bool _onBufferA;
uint32_t _pageBufferA;
uint32_t _pageBufferB;
};
#endif // _FLASH_H

373
lib/bossac/src/Flasher.cpp Normal file
View File

@@ -0,0 +1,373 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include <string>
#include <exception>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "Flasher.h"
using namespace std;
void
FlasherInfo::print()
{
bool first;
printf("Device : %s\n", name.c_str());
printf("Version : %s\n", version.c_str());
printf("Address : 0x%x\n", address);
printf("Pages : %d\n", numPages);
printf("Page Size : %d bytes\n", pageSize);
printf("Total Size : %dKB\n", totalSize / 1024);
printf("Planes : %d\n", numPlanes);
printf("Lock Regions : %zd\n", lockRegions.size());
printf("Locked : ");
first = true;
for (uint32_t region = 0; region < lockRegions.size(); region++)
{
if (lockRegions[region])
{
printf("%s%d", first ? "" : ",", region);
first = false;
}
}
printf("%s\n", first ? "none" : "");
printf("Security : %s\n", security ? "true" : "false");
if (canBootFlash)
printf("Boot Flash : %s\n", bootFlash ? "true" : "false");
if (canBod)
printf("BOD : %s\n", bod ? "true" : "false");
if (canBor)
printf("BOR : %s\n", bor ? "true" : "false");
}
void
Flasher::erase(uint32_t foffset)
{
_observer.onStatus("Erase flash\n");
_flash->eraseAll(foffset);
_flash->eraseAuto(false);
}
void
Flasher::write(const char* filename, uint32_t foffset)
{
FILE* infile;
uint32_t pageSize = _flash->pageSize();
uint32_t pageNum = 0;
uint32_t numPages;
long fsize;
size_t fbytes;
if (foffset % pageSize != 0 || foffset >= _flash->totalSize())
throw FlashOffsetError();
infile = fopen(filename, "rb");
if (!infile)
throw FileOpenError(errno);
try
{
if (fseek(infile, 0, SEEK_END) != 0 || (fsize = ftell(infile)) < 0)
throw FileIoError(errno);
rewind(infile);
numPages = (fsize + pageSize - 1) / pageSize;
if (numPages > _flash->numPages())
throw FileSizeError();
_observer.onStatus("Write %ld bytes to flash (%u pages)\n", fsize, numPages);
if (_samba.canWriteBuffer())
{
uint32_t offset = 0;
uint32_t bufferSize = _samba.writeBufferSize();
uint8_t buffer[bufferSize];
while ((fbytes = fread(buffer, 1, bufferSize, infile)) > 0)
{
_observer.onProgress(offset / pageSize, numPages);
if (fbytes < bufferSize)
{
memset(buffer + fbytes, 0, bufferSize - fbytes);
fbytes = (fbytes + pageSize - 1) / pageSize * pageSize;
}
_flash->loadBuffer(buffer, fbytes);
_flash->writeBuffer(foffset + offset, fbytes);
offset += fbytes;
}
}
else
{
uint8_t buffer[pageSize];
uint32_t pageOffset = foffset / pageSize;
while ((fbytes = fread(buffer, 1, pageSize, infile)) > 0)
{
_observer.onProgress(pageNum, numPages);
_flash->loadBuffer(buffer, fbytes);
_flash->writePage(pageOffset + pageNum);
pageNum++;
if (pageNum == numPages || fbytes != pageSize)
break;
}
}
}
catch(...)
{
fclose(infile);
throw;
}
fclose(infile);
_observer.onProgress(numPages, numPages);
}
bool
Flasher::verify(const char* filename, uint32_t& pageErrors, uint32_t& totalErrors, uint32_t foffset)
{
FILE* infile;
uint32_t pageSize = _flash->pageSize();
uint8_t bufferA[pageSize];
uint8_t bufferB[pageSize];
uint32_t pageNum = 0;
uint32_t numPages;
uint32_t pageOffset;
uint32_t byteErrors = 0;
uint16_t calcCrc = 0;
uint16_t flashCrc;
long fsize;
size_t fbytes;
pageErrors = 0;
totalErrors = 0;
if (foffset % pageSize != 0 || foffset >= _flash->totalSize())
throw FlashOffsetError();
pageOffset = foffset / pageSize;
infile = fopen(filename, "rb");
if (!infile)
throw FileOpenError(errno);
try
{
if (fseek(infile, 0, SEEK_END) != 0 || (fsize = ftell(infile)) < 0)
throw FileIoError(errno);
rewind(infile);
numPages = (fsize + pageSize - 1) / pageSize;
if (numPages > _flash->numPages())
throw FileSizeError();
_observer.onStatus("Verify %ld bytes of flash\n", fsize);
while ((fbytes = fread(bufferA, 1, pageSize, infile)) > 0)
{
byteErrors = 0;
_observer.onProgress(pageNum, numPages);
if (_samba.canChecksumBuffer())
{
for (uint32_t i = 0; i < fbytes; i++)
calcCrc = _samba.checksumCalc(bufferA[i], calcCrc);
flashCrc = _samba.checksumBuffer((pageOffset + pageNum) * pageSize, fbytes);
if (flashCrc != calcCrc)
{
_flash->readPage(pageOffset + pageNum, bufferB);
for (uint32_t i = 0; i < fbytes; i++)
{
if (bufferA[i] != bufferB[i])
byteErrors++;
}
}
}
else
{
_flash->readPage(pageOffset + pageNum, bufferB);
for (uint32_t i = 0; i < fbytes; i++)
{
if (bufferA[i] != bufferB[i])
byteErrors++;
}
}
if (byteErrors != 0)
{
pageErrors++;
totalErrors += byteErrors;
}
pageNum++;
if (pageNum == numPages || fbytes != pageSize)
break;
}
}
catch(...)
{
fclose(infile);
throw;
}
fclose(infile);
_observer.onProgress(numPages, numPages);
if (pageErrors != 0)
return false;
return true;
}
void
Flasher::read(const char* filename, uint32_t fsize, uint32_t foffset)
{
FILE* outfile;
uint32_t pageSize = _flash->pageSize();
uint8_t buffer[pageSize];
uint32_t pageNum = 0;
uint32_t pageOffset;
uint32_t numPages;
size_t fbytes;
if (foffset % pageSize != 0 || foffset >= _flash->totalSize())
throw FlashOffsetError();
pageOffset = foffset / pageSize;
if (fsize == 0)
fsize = pageSize * (_flash->numPages() - pageOffset);
numPages = (fsize + pageSize - 1) / pageSize;
if (pageOffset + numPages > _flash->numPages())
throw FileSizeError();
outfile = fopen(filename, "wb");
if (!outfile)
throw FileOpenError(errno);
_observer.onStatus("Read %d bytes from flash\n", fsize);
try
{
for (pageNum = 0; pageNum < numPages; pageNum++)
{
_observer.onProgress(pageNum, numPages);
_flash->readPage(pageOffset + pageNum, buffer);
if (pageNum == numPages - 1 && fsize % pageSize > 0)
pageSize = fsize % pageSize;
fbytes = fwrite(buffer, 1, pageSize, outfile);
if (fbytes != pageSize)
throw FileShortError();
}
}
catch(...)
{
fclose(outfile);
throw;
}
_observer.onProgress(numPages, numPages);
fclose(outfile);
}
void
Flasher::lock(string& regionArg, bool enable)
{
if (regionArg.empty())
{
_observer.onStatus("%s all regions\n", enable ? "Lock" : "Unlock");
std::vector<bool> regions(_flash->lockRegions(), enable);
_flash->setLockRegions(regions);
}
else
{
size_t pos = 0;
size_t delim;
uint32_t region;
string sub;
std::vector<bool> regions = _flash->getLockRegions();
do
{
delim = regionArg.find(',', pos);
sub = regionArg.substr(pos, delim - pos);
region = strtol(sub.c_str(), NULL, 0);
_observer.onStatus("%s region %d\n", enable ? "Lock" : "Unlock", region);
regions[region] = enable;
pos = delim + 1;
} while (delim != string::npos);
_flash->setLockRegions(regions);
}
}
void
Flasher::info(FlasherInfo& info)
{
info.name = _flash->name();
info.version = _samba.version();
info.address = _flash->address();
info.numPages = _flash->numPages();
info.pageSize = _flash->pageSize();
info.totalSize = _flash->numPages() * _flash->pageSize();
info.numPlanes = _flash->numPlanes();
info.security = _flash->getSecurity();
info.bootFlash = _flash->getBootFlash();
info.bod = _flash->getBod();
info.bor = _flash->getBor();
info.canBootFlash = _flash->canBootFlash();
info.canBod = _flash->canBod();
info.canBor = _flash->canBor();
info.canChipErase = _samba.canChipErase();
info.canWriteBuffer = _samba.canWriteBuffer();
info.canChecksumBuffer = _samba.canChecksumBuffer();
info.lockRegions = _flash->getLockRegions();
}

110
lib/bossac/src/Flasher.h Normal file
View File

@@ -0,0 +1,110 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _FLASHER_H
#define _FLASHER_H
#include <string>
#include <exception>
#include <vector>
#include "Device.h"
#include "Flash.h"
#include "Samba.h"
#include "FileError.h"
class FlashOffsetError : public std::exception
{
public:
FlashOffsetError() : std::exception() {};
virtual const char* what() const throw() { return "Flash offset is invalid"; }
};
class FlasherObserver
{
public:
FlasherObserver() {}
virtual ~FlasherObserver() {}
virtual void onStatus(const char *message, ...) = 0;
virtual void onProgress(int num, int div) = 0;
};
class FlasherInfo
{
public:
FlasherInfo() {}
virtual ~FlasherInfo() {}
void print();
std::string name;
uint32_t chipId;
uint32_t extChipId;
std::string version;
uint32_t address;
uint32_t numPages;
uint32_t pageSize;
uint32_t totalSize;
uint32_t numPlanes;
bool security;
bool bootFlash;
bool bod;
bool bor;
bool canBootFlash;
bool canBod;
bool canBor;
bool canChipErase;
bool canWriteBuffer;
bool canChecksumBuffer;
std::vector<bool> lockRegions;
};
class Flasher
{
public:
Flasher(Samba& samba, Device& device, FlasherObserver& observer) : _samba(samba), _flash(device.getFlash()), _observer(observer) {}
virtual ~Flasher() {}
void erase(uint32_t foffset);
void write(const char* filename, uint32_t foffset = 0);
bool verify(const char* filename, uint32_t& pageErrors, uint32_t& totalErrors, uint32_t foffset = 0);
void read(const char* filename, uint32_t fsize, uint32_t foffset = 0);
void lock(std::string& regionArg, bool enable);
void info(FlasherInfo& info);
private:
Samba& _samba;
Device::FlashPtr& _flash;
FlasherObserver& _observer;
};
#endif // _FLASHER_H

View File

@@ -0,0 +1,109 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include "LinuxPortFactory.h"
#include "PosixSerialPort.h"
#include <string.h>
#include <stdio.h>
#include <string>
LinuxPortFactory::LinuxPortFactory()
{
_dir = opendir("/dev");
}
LinuxPortFactory::~LinuxPortFactory()
{
if (_dir)
closedir(_dir);
}
SerialPort::Ptr
LinuxPortFactory::create(const std::string& name)
{
bool isUsb = false;
if (name.find("ttyUSB") != std::string::npos ||
name.find("ttyACM") != std::string::npos)
isUsb = true;
return create(name, isUsb);
}
SerialPort::Ptr
LinuxPortFactory::create(const std::string& name, bool isUsb)
{
return SerialPort::Ptr(new PosixSerialPort(name, isUsb));
}
std::string
LinuxPortFactory::begin()
{
if (!_dir)
return end();
rewinddir(_dir);
return next();
}
std::string
LinuxPortFactory::next()
{
struct dirent* entry;
if (!_dir)
return end();
while ((entry = readdir(_dir)))
{
if (strncmp("ttyUSB", entry->d_name, sizeof("ttyUSB") - 1) == 0)
return std::string(entry->d_name);
else if (strncmp("ttyACM", entry->d_name, sizeof("ttyACM") - 1) == 0)
return std::string(entry->d_name);
else if (strncmp("ttyS", entry->d_name, sizeof("ttyS") - 1) == 0)
return std::string(entry->d_name);
}
return end();
}
std::string
LinuxPortFactory::end()
{
return std::string();
}
std::string
LinuxPortFactory::def()
{
return std::string("/dev/ttyACM0");
}

View File

@@ -0,0 +1,60 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _LINUXPORTFACTORY_H
#define _LINUXPORTFACTORY_H
class LinuxPortFactory;
#include "PortFactory.h"
#include <sys/types.h>
#include <dirent.h>
#include <string>
class LinuxPortFactory : public PortFactoryBase
{
public:
LinuxPortFactory();
virtual ~LinuxPortFactory();
virtual std::string begin();
virtual std::string end();
virtual std::string next();
virtual std::string def();
virtual SerialPort::Ptr create(const std::string& name);
virtual SerialPort::Ptr create(const std::string& name, bool isUsb);
private:
std::string _empty;
DIR* _dir;
};
#endif // _LINUXPORTFACTORY_H

View File

@@ -0,0 +1,68 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _PORTFACTORY_H
#define _PORTFACTORY_H
#include <string>
#include "SerialPort.h"
class PortFactoryBase
{
public:
PortFactoryBase() {}
virtual ~PortFactoryBase() {}
virtual std::string begin() = 0;
virtual std::string end() = 0;
virtual std::string next() = 0;
virtual std::string def() = 0;
virtual SerialPort::Ptr create(const std::string& name) = 0;
virtual SerialPort::Ptr create(const std::string& name, bool isUsb) = 0;
};
#if defined(__WIN32__)
#include "WinPortFactory.h"
typedef WinPortFactory PortFactory;
#elif defined(__linux__)
#include "LinuxPortFactory.h"
typedef LinuxPortFactory PortFactory;
#elif defined(__APPLE__)
#include "OSXPortFactory.h"
typedef OSXPortFactory PortFactory;
#elif defined(__OpenBSD__) || defined(__FreeBSD__)
// This is likely to work (but not tested) for the other BSDs as well
#include "BSDPortFactory.h"
typedef BSDPortFactory PortFactory;
#else
#error "Platform is not supported"
#endif
#endif // _PORTFACTORY_H

View File

@@ -0,0 +1,332 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include "PosixSerialPort.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <string>
#ifndef B460800
#define B460800 460800
#endif
#ifndef B921600
#define B921600 921600
#endif
PosixSerialPort::PosixSerialPort(const std::string& name, bool isUsb) :
SerialPort(name), _devfd(-1), _isUsb(isUsb), _timeout(0),
_autoFlush(false)
{
}
PosixSerialPort::~PosixSerialPort()
{
if (_devfd >= 0)
::close(_devfd);
}
bool
PosixSerialPort::open(int baud,
int data,
SerialPort::Parity parity,
SerialPort::StopBit stop)
{
struct termios options;
speed_t speed;
// Try opening port assuming _name is full path. If it fails
// try "/dev/" + _name
_devfd = ::open(_name.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if (_devfd == -1)
{
std::string dev("/dev/");
dev += _name;
_devfd = ::open(dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if (_devfd == -1)
return false;
}
if (tcgetattr(_devfd, &options) == -1)
{
close();
return false;
}
switch (baud)
{
case 1200:
speed = B1200;
break;
case 9600:
speed = B9600;
break;
case 19200:
speed = B19200;
break;
case 38400:
speed = B38400;
break;
case 57600:
speed = B57600;
break;
case 115200:
speed = B115200;
break;
case 230400:
speed = B230400;
break;
case 460800:
speed = B460800;
break;
case 921600:
speed = B921600;
break;
default:
close();
return false;
}
if (cfsetispeed(&options, speed) || cfsetospeed(&options, speed))
{
close();
return false;
}
options.c_cflag |= (CLOCAL | CREAD);
switch (data)
{
case 8:
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
break;
case 7:
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;
break;
default:
close();
return false;
}
switch (parity)
{
case SerialPort::ParityNone:
options.c_cflag &= ~PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag &= ~(INPCK | ISTRIP);
break;
case SerialPort::ParityOdd:
options.c_cflag |= PARENB;
options.c_cflag |= PARODD;
options.c_iflag |= (INPCK | ISTRIP);
break;
case SerialPort::ParityEven:
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= (INPCK | ISTRIP);
break;
default:
close();
return false;
}
switch (stop)
{
case StopBitOne:
options.c_cflag &= ~CSTOPB;
break;
case StopBitTwo:
options.c_cflag |= CSTOPB;
break;
default:
close();
return false;
}
// No hardware flow control
options.c_cflag &= ~CRTSCTS;
// No software flow control
options.c_iflag &= ~(IXON | IXOFF | IXANY);
// Raw input
options.c_iflag &= ~(BRKINT | ICRNL);
options.c_lflag &= ~(ICANON | IEXTEN | ECHO | ECHOE | ISIG);
// Raw output
options.c_oflag &= ~OPOST;
// No wait time
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 0;
if (tcsetattr(_devfd, TCSANOW, &options))
{
close();
return false;
}
return true;
}
void
PosixSerialPort::close()
{
if (_devfd >= 0)
::close(_devfd);
_devfd = -1;
}
int
PosixSerialPort::read(uint8_t* buffer, int len)
{
fd_set fds;
struct timeval tv;
int numread = 0;
int retval;
if (_devfd == -1)
return -1;
while (numread < len)
{
FD_ZERO(&fds);
FD_SET(_devfd, &fds);
tv.tv_sec = _timeout / 1000;
tv.tv_usec = (_timeout % 1000) * 1000;
retval = select(_devfd + 1, &fds, NULL, NULL, &tv);
if (retval < 0)
{
return -1;
}
else if (retval == 0)
{
return numread;
}
else if (FD_ISSET(_devfd, &fds))
{
retval = ::read(_devfd, (uint8_t*) buffer + numread, len - numread);
if (retval < 0)
return -1;
numread += retval;
}
}
return numread;
}
int
PosixSerialPort::write(const uint8_t* buffer, int len)
{
if (_devfd == -1)
return -1;
int res = ::write(_devfd, buffer, len);
// Used on macos to avoid upload errors
if (_autoFlush)
flush();
return res;
}
int
PosixSerialPort::get()
{
uint8_t byte;
if (_devfd == -1)
return -1;
if (read(&byte, 1) != 1)
return -1;
return byte;
}
int
PosixSerialPort::put(int c)
{
uint8_t byte;
byte = c;
return write(&byte, 1);
}
void
PosixSerialPort::flush()
{
// There isn't a reliable way to flush on a file descriptor
// so we just wait it out. One millisecond is the USB poll
// interval so that should cover it.
usleep(1000);
}
bool
PosixSerialPort::timeout(int millisecs)
{
_timeout = millisecs;
return true;
}
void
PosixSerialPort::setDTR(bool dtr)
{
if (_devfd == -1)
return;
int iFlags = TIOCM_DTR;
ioctl(_devfd, (dtr ? TIOCMBIS : TIOCMBIC), &iFlags);
}
void
PosixSerialPort::setRTS(bool rts)
{
if (_devfd == -1)
return;
int iFlags = TIOCM_RTS;
ioctl(_devfd, (rts ? TIOCMBIS : TIOCMBIC), &iFlags);
}
void
PosixSerialPort::setAutoFlush(bool autoflush)
{
_autoFlush = autoflush;
}

View File

@@ -0,0 +1,66 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _POSIXSERIALPORT_H
#define _POSIXSERIALPORT_H
#include "SerialPort.h"
class PosixSerialPort : public SerialPort
{
public:
PosixSerialPort(const std::string& name, bool isUsb);
virtual ~PosixSerialPort();
bool open(int baud = 115200,
int data = 8,
SerialPort::Parity parity = SerialPort::ParityNone,
SerialPort::StopBit stop = SerialPort::StopBitOne);
void close();
bool isUsb() { return _isUsb; };
int read(uint8_t* data, int size);
int write(const uint8_t* data, int size);
int get();
int put(int c);
bool timeout(int millisecs);
void flush();
void setDTR(bool dtr);
void setRTS(bool rts);
void setAutoFlush(bool autoflush);
private:
int _devfd;
bool _isUsb;
int _timeout;
bool _autoFlush;
};
#endif // _POSIXSERIALPORT_H

672
lib/bossac/src/Samba.cpp Normal file
View File

@@ -0,0 +1,672 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include "Samba.h"
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
using namespace std;
// XMODEM definitions
#define BLK_SIZE 128
#define MAX_RETRIES 5
#define SOH 0x01
#define EOT 0x04
#define ACK 0x06
#define NAK 0x15
#define CAN 0x18
#define START 'C'
#define TIMEOUT_QUICK 100
#define TIMEOUT_NORMAL 1000
#define TIMEOUT_LONG 5000
#define min(a, b) ((a) < (b) ? (a) : (b))
Samba::Samba() :
_canChipErase(false),
_canWriteBuffer(false),
_canChecksumBuffer(false),
_readBufferSize(0),
_debug(false),
_isUsb(false)
{
}
Samba::~Samba()
{
}
bool
Samba::init()
{
uint8_t cmd[3];
_port->timeout(TIMEOUT_QUICK);
// Flush garbage
uint8_t dummy[1024];
_port->read(dummy, sizeof(dummy));
if (!_isUsb)
{
if (_debug)
printf("Send auto-baud\n");
// RS-232 auto-baud sequence
_port->put(0x80);
_port->get();
_port->put(0x80);
_port->get();
_port->put('#');
_port->read(cmd, 3);
}
// Set binary mode
if (_debug)
printf("Set binary mode\n");
cmd[0] = 'N';
cmd[1] = '#';
_port->write(cmd, 2);
_port->read(cmd, 2);
std::string ver;
try
{
ver = version();
}
catch(SambaError& err)
{
return false;
}
std::size_t extIndex = ver.find("[Arduino:");
if (extIndex != string::npos)
{
extIndex += 9;
while (ver[extIndex] != ']')
{
switch (ver[extIndex])
{
case 'X': _canChipErase = true; break;
case 'Y': _canWriteBuffer = true; break;
case 'Z': _canChecksumBuffer = true; break;
}
extIndex++;
}
// All SAMD-based Arduino/AdaFruit boards have a bug in their bootloader
// that trying to read 64 bytes or more over USB corrupts the data.
// We must limit these boards to read chunks of 63 bytes.
if (_isUsb)
_readBufferSize = 63;
}
_port->timeout(TIMEOUT_NORMAL);
return true;
}
bool
Samba::connect(SerialPort::Ptr port, int bps)
{
_port = move(port);
// Try to connect at a high speed if USB
_isUsb = _port->isUsb();
if (_isUsb)
{
if (_port->open(921600) && init())
{
if (_debug)
printf("Connected at 921600 baud\n");
return true;
}
else
{
_port->close();
}
}
_isUsb = false;
// Try the serial port at slower speed
if (_port->open(bps) && init())
{
if (_debug)
printf("Connected at %d baud\n", bps);
return true;
}
disconnect();
return false;
}
void
Samba::disconnect()
{
_port->close();
_port.release();
}
void
Samba::writeByte(uint32_t addr, uint8_t value)
{
uint8_t cmd[14];
if (_debug)
printf("%s(addr=%#x,value=%#x)\n", __FUNCTION__, addr, value);
snprintf((char*) cmd, sizeof(cmd), "O%08X,%02X#", addr, value);
if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
throw SambaError();
// The SAM firmware has a bug that if the command and binary data
// are received in the same USB data packet, then the firmware
// gets confused. Even though the writes are separated in the code,
// USB drivers often do write combining which can put them together
// in the same USB data packet. To avoid this, we call the serial
// port object's flush method before writing the data.
if (_isUsb)
_port->flush();
}
uint8_t
Samba::readByte(uint32_t addr)
{
uint8_t cmd[13];
uint8_t value;
snprintf((char*) cmd, sizeof(cmd), "o%08X,4#", addr);
if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
throw SambaError();
if (_port->read(cmd, sizeof(uint8_t)) != sizeof(uint8_t))
throw SambaError();
value = cmd[0];
if (_debug)
printf("%s(addr=%#x)=%#x\n", __FUNCTION__, addr, value);
return value;
}
void
Samba::writeWord(uint32_t addr, uint32_t value)
{
uint8_t cmd[20];
if (_debug)
printf("%s(addr=%#x,value=%#x)\n", __FUNCTION__, addr, value);
snprintf((char*) cmd, sizeof(cmd), "W%08X,%08X#", addr, value);
if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
throw SambaError();
// The SAM firmware has a bug that if the command and binary data
// are received in the same USB data packet, then the firmware
// gets confused. Even though the writes are sperated in the code,
// USB drivers often do write combining which can put them together
// in the same USB data packet. To avoid this, we call the serial
// port object's flush method before writing the data.
if (_isUsb)
_port->flush();
}
uint32_t
Samba::readWord(uint32_t addr)
{
uint8_t cmd[13];
uint32_t value;
snprintf((char*) cmd, sizeof(cmd), "w%08X,4#", addr);
if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
throw SambaError();
if (_port->read(cmd, sizeof(uint32_t)) != sizeof(uint32_t))
throw SambaError();
value = (cmd[3] << 24 | cmd[2] << 16 | cmd[1] << 8 | cmd[0] << 0);
if (_debug)
printf("%s(addr=%#x)=%#x\n", __FUNCTION__, addr, value);
return value;
}
static const uint16_t crc16Table[256] = {
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
};
uint16_t
Samba::crc16Calc(const uint8_t *data, int len)
{
uint16_t crc16 = 0;
while (len-- > 0)
crc16 = (crc16 << 8) ^ crc16Table[((crc16 >> 8) ^ *(uint8_t*) data++) & 0xff];
return crc16;
}
bool
Samba::crc16Check(const uint8_t *blk)
{
uint16_t crc16;
crc16 = blk[BLK_SIZE + 3] << 8 | blk[BLK_SIZE + 4];
return (crc16Calc(&blk[3], BLK_SIZE) == crc16);
}
void
Samba::crc16Add(uint8_t *blk)
{
uint16_t crc16;
crc16 = crc16Calc(&blk[3], BLK_SIZE);
blk[BLK_SIZE + 3] = (crc16 >> 8) & 0xff;
blk[BLK_SIZE + 4] = crc16 & 0xff;
}
uint16_t
Samba::checksumCalc(uint8_t data, uint16_t crc16) {
return (crc16 << 8) ^ crc16Table[((crc16 >> 8) ^ data) & 0xff];
}
void
Samba::readXmodem(uint8_t* buffer, int size)
{
uint8_t blk[BLK_SIZE + 5];
uint32_t blkNum = 1;
int retries;
int bytes;
while (size > 0)
{
for (retries = 0; retries < MAX_RETRIES; retries++)
{
if (blkNum == 1)
_port->put(START);
bytes = _port->read(blk, sizeof(blk));
if (bytes == sizeof(blk) &&
blk[0] == SOH &&
blk[1] == (blkNum & 0xff) &&
crc16Check(blk))
break;
if (blkNum != 1)
_port->put(NAK);
}
if (retries == MAX_RETRIES)
throw SambaError();
_port->put(ACK);
memmove(buffer, &blk[3], min(size, BLK_SIZE));
buffer += BLK_SIZE;
size -= BLK_SIZE;
blkNum++;
}
for (retries = 0; retries < MAX_RETRIES; retries++)
{
if (_port->get() == EOT)
{
_port->put(ACK);
break;
}
_port->put(NAK);
}
if (retries == MAX_RETRIES)
throw SambaError();
}
void
Samba::writeXmodem(const uint8_t* buffer, int size)
{
uint8_t blk[BLK_SIZE + 5];
uint32_t blkNum = 1;
int retries;
int bytes;
for (retries = 0; retries < MAX_RETRIES; retries++)
{
if (_port->get() == START)
break;
}
if (retries == MAX_RETRIES)
throw SambaError();
while (size > 0)
{
blk[0] = SOH;
blk[1] = (blkNum & 0xff);
blk[2] = ~(blkNum & 0xff);
memmove(&blk[3], buffer, min(size, BLK_SIZE));
if (size < BLK_SIZE)
memset(&blk[3] + size, 0, BLK_SIZE - size);
crc16Add(blk);
for (retries = 0; retries < MAX_RETRIES; retries++)
{
bytes = _port->write(blk, sizeof(blk));
if (bytes != sizeof(blk))
throw SambaError();
if (_port->get() == ACK)
break;
}
if (retries == MAX_RETRIES)
throw SambaError();
buffer += BLK_SIZE;
size -= BLK_SIZE;
blkNum++;
}
for (retries = 0; retries < MAX_RETRIES; retries++)
{
_port->put(EOT);
if (_port->get() == ACK)
break;
}
if (retries == MAX_RETRIES)
throw SambaError();
}
void
Samba::readBinary(uint8_t* buffer, int size)
{
if (_port->read(buffer, size) != size)
throw SambaError();
}
void
Samba::writeBinary(const uint8_t* buffer, int size)
{
while (size)
{
int written = _port->write(buffer, size);
if (written <= 0)
throw SambaError();
buffer += written;
size -= written;
}
}
void
Samba::read(uint32_t addr, uint8_t* buffer, int size)
{
uint8_t cmd[20];
int chunk;
if (_debug)
printf("%s(addr=%#x,size=%#x)\n", __FUNCTION__, addr, size);
// The SAM firmware has a bug reading powers of 2 over 32 bytes
// via USB. If that is the case here, then read the first byte
// with a readByte and then read one less than the requested size.
if (_isUsb && _readBufferSize == 0 && size > 32 && !(size & (size - 1)))
{
*buffer = readByte(addr);
addr++;
buffer++;
size--;
}
while (size > 0)
{
// Handle any limitations on the size of the read
if (_readBufferSize > 0 && size > _readBufferSize)
chunk = _readBufferSize;
else
chunk = size;
snprintf((char*) cmd, sizeof(cmd), "R%08X,%08X#", addr, chunk);
if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
throw SambaError();
if (_isUsb)
readBinary(buffer, chunk);
else
readXmodem(buffer, chunk);
size -= chunk;
addr += chunk;
buffer += chunk;
}
}
void
Samba::write(uint32_t addr, const uint8_t* buffer, int size)
{
uint8_t cmd[20];
if (_debug)
printf("%s(addr=%#x,size=%#x)\n", __FUNCTION__, addr, size);
snprintf((char*) cmd, sizeof(cmd), "S%08X,%08X#", addr, size);
if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
throw SambaError();
// The SAM firmware has a bug that if the command and binary data
// are received in the same USB data packet, then the firmware
// gets confused. Even though the writes are separated in the code,
// USB drivers often do write combining which can put them together
// in the same USB data packet. To avoid this, we call the serial
// port object's flush method before writing the data.
if (_isUsb)
{
_port->flush();
writeBinary(buffer, size);
}
else
{
writeXmodem(buffer, size);
}
}
void
Samba::go(uint32_t addr)
{
uint8_t cmd[11];
if (_debug)
printf("%s(addr=%#x)\n", __FUNCTION__, addr);
snprintf((char*) cmd, sizeof(cmd), "G%08X#", addr);
if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
throw SambaError();
// The SAM firmware can get confused if another command is
// received in the same USB data packet as the go command
// so we flush after writing the command over USB.
if (_isUsb)
_port->flush();
}
std::string
Samba::version()
{
uint8_t cmd[256];
char* str;
int size;
int pos;
cmd[0] = 'V';
cmd[1] = '#';
_port->write(cmd, 2);
_port->timeout(TIMEOUT_QUICK);
size = _port->read(cmd, sizeof(cmd) - 1);
_port->timeout(TIMEOUT_NORMAL);
if (size <= 0)
throw SambaError();
str = (char*) cmd;
for (pos = 0; pos < size; pos++)
{
if (!isprint(str[pos]))
break;
}
str[pos] = '\0';
std::string ver(str);
if (_debug)
printf("%s()=%s\n", __FUNCTION__, ver.c_str());
return ver;
}
void
Samba::chipErase(uint32_t start_addr)
{
if (!_canChipErase)
throw SambaError();
uint8_t cmd[64];
if (_debug)
printf("%s(addr=%#x)\n", __FUNCTION__, start_addr);
int l = snprintf((char*) cmd, sizeof(cmd), "X%08X#", start_addr);
if (_port->write(cmd, l) != l)
throw SambaError();
_port->timeout(TIMEOUT_LONG);
_port->read(cmd, 3); // Expects "X\n\r"
_port->timeout(TIMEOUT_NORMAL);
if (cmd[0] != 'X')
throw SambaError();
}
void
Samba::writeBuffer(uint32_t src_addr, uint32_t dst_addr, uint32_t size)
{
if (!_canWriteBuffer)
throw SambaError();
if (size > checksumBufferSize())
throw SambaError();
if (_debug)
printf("%s(scr_addr=%#x, dst_addr=%#x, size=%#x)\n", __FUNCTION__, src_addr, dst_addr, size);
uint8_t cmd[64];
int l = snprintf((char*) cmd, sizeof(cmd), "Y%08X,0#", src_addr);
if (_port->write(cmd, l) != l)
throw SambaError();
_port->timeout(TIMEOUT_QUICK);
cmd[0] = 0;
_port->read(cmd, 3); // Expects "Y\n\r"
_port->timeout(TIMEOUT_NORMAL);
if (cmd[0] != 'Y')
throw SambaError();
l = snprintf((char*) cmd, sizeof(cmd), "Y%08X,%08X#", dst_addr, size);
if (_port->write(cmd, l) != l)
throw SambaError();
_port->timeout(TIMEOUT_LONG);
cmd[0] = 0;
_port->read(cmd, 3); // Expects "Y\n\r"
_port->timeout(TIMEOUT_NORMAL);
if (cmd[0] != 'Y')
throw SambaError();
}
uint16_t
Samba::checksumBuffer(uint32_t start_addr, uint32_t size)
{
if (!_canChecksumBuffer)
throw SambaError();
if (size > checksumBufferSize())
throw SambaError();
if (_debug)
printf("%s(start_addr=%#x, size=%#x) = ", __FUNCTION__, start_addr, size);
uint8_t cmd[64];
int l = snprintf((char*) cmd, sizeof(cmd), "Z%08X,%08X#", start_addr, size);
if (_port->write(cmd, l) != l)
throw SambaError();
_port->timeout(TIMEOUT_LONG);
cmd[0] = 0;
_port->read(cmd, 12); // Expects "Z00000000#\n\r"
_port->timeout(TIMEOUT_NORMAL);
if (cmd[0] != 'Z')
throw SambaError();
cmd[9] = 0;
errno = 0;
uint32_t res = strtol((char*) &cmd[1], NULL, 16);
if (errno != 0)
throw SambaError();
if (_debug)
printf("%x\n", res);
return res;
}

115
lib/bossac/src/Samba.h Normal file
View File

@@ -0,0 +1,115 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _SAMBA_H
#define _SAMBA_H
#include <string>
#include <stdint.h>
#include <exception>
#include <memory>
#include "SerialPort.h"
class SambaError : public std::exception
{
public:
SambaError() : exception() {};
const char* what() const throw() { return "SAM-BA operation failed"; }
};
class Samba
{
public:
Samba();
virtual ~Samba();
bool connect(SerialPort::Ptr port, int bps = 115200);
void disconnect();
void writeByte(uint32_t addr, uint8_t value);
uint8_t readByte(uint32_t addr);
void writeWord(uint32_t addr, uint32_t value);
uint32_t readWord(uint32_t addr);
void write(uint32_t addr, const uint8_t* buffer, int size);
void read(uint32_t addr, uint8_t* buffer, int size);
void go(uint32_t addr);
std::string version();
void chipId(uint32_t& chipId, uint32_t& extChipId);
void setDebug(bool debug) { _debug = debug; }
const SerialPort& getSerialPort() { return *_port; }
void reset();
// Extended SAM-BA functions
bool canChipErase() { return _canChipErase; }
void chipErase(uint32_t start_addr);
bool canWriteBuffer() { return _canWriteBuffer; }
void writeBuffer(uint32_t src_addr, uint32_t dst_addr, uint32_t size);
uint32_t writeBufferSize() { return 4096; }
bool canChecksumBuffer() { return _canChecksumBuffer; }
uint16_t checksumBuffer(uint32_t start_addr, uint32_t size);
uint32_t checksumBufferSize() { return 4096; }
uint16_t checksumCalc(uint8_t c, uint16_t crc);
private:
bool _canChipErase;
bool _canWriteBuffer;
bool _canChecksumBuffer;
int _readBufferSize;
bool _debug;
bool _isUsb;
SerialPort::Ptr _port;
bool init();
uint16_t crc16Calc(const uint8_t *data, int len);
bool crc16Check(const uint8_t *blk);
void crc16Add(uint8_t *blk);
void writeXmodem(const uint8_t* buffer, int size);
void readXmodem(uint8_t* buffer, int size);
void writeBinary(const uint8_t* buffer, int size);
void readBinary(uint8_t* buffer, int size);
};
#endif // _SAMBA_H

View File

@@ -0,0 +1,82 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _SERIALPORT_H
#define _SERIALPORT_H
#include <string>
#include <memory>
#include <stdint.h>
class SerialPort
{
public:
SerialPort(const std::string& name) : _name(name) {}
virtual ~SerialPort() {}
enum Parity
{
ParityNone,
ParityOdd,
ParityEven,
};
enum StopBit
{
StopBitOne,
StopBitOneFive,
StopBitTwo,
};
virtual bool open(int baud = 115200,
int data = 8,
Parity parity = ParityNone,
StopBit stop = StopBitOne) = 0;
virtual void close() = 0;
virtual bool isUsb() = 0;
virtual int read(uint8_t* data, int size) = 0;
virtual int write(const uint8_t* data, int size) = 0;
virtual int get() = 0;
virtual int put(int c) = 0;
virtual bool timeout(int millisecs) = 0;
virtual void flush() = 0;
virtual void setDTR(bool dtr) = 0;
virtual void setRTS(bool rts) = 0;
virtual std::string name() const { return _name; }
typedef std::unique_ptr<SerialPort> Ptr;
protected:
std::string _name;
};
#endif // _SERIALPORT_H

View File

@@ -0,0 +1,62 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include "WordCopyApplet.h"
WordCopyApplet::WordCopyApplet(Samba& samba, uint32_t addr)
: Applet(samba,
addr,
applet.code,
sizeof(applet.code),
addr + applet.start,
addr + applet.stack,
addr + applet.reset)
{
}
WordCopyApplet::~WordCopyApplet()
{
}
void
WordCopyApplet::setDstAddr(uint32_t dstAddr)
{
_samba.writeWord(_addr + applet.dst_addr, dstAddr);
}
void
WordCopyApplet::setSrcAddr(uint32_t srcAddr)
{
_samba.writeWord(_addr + applet.src_addr, srcAddr);
}
void
WordCopyApplet::setWords(uint32_t words)
{
_samba.writeWord(_addr + applet.words, words);
}

View File

@@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#ifndef _WORDCOPYAPPLET_H
#define _WORDCOPYAPPLET_H
#include "Applet.h"
#include "WordCopyArm.h"
class WordCopyApplet : public Applet
{
public:
WordCopyApplet(Samba& samba, uint32_t addr);
virtual ~WordCopyApplet();
void setDstAddr(uint32_t dstAddr);
void setSrcAddr(uint32_t srcAddr);
void setWords(uint32_t words);
private:
static WordCopyArm applet;
};
#endif // _WORDCOPYAPPLET_H

View File

@@ -0,0 +1,47 @@
.global start
.global stack
.global reset
.global dst_addr
.global src_addr
.global words
.text
.thumb
.align 0
start:
ldr r0, dst_addr
ldr r1, src_addr
ldr r2, words
b check
copy:
ldmia r1!, {r3}
stmia r0!, {r3}
sub r2, #1
check:
cmp r2, #0
bne copy
@ Fix for SAM-BA stack bug
ldr r0, reset
cmp r0, #0
bne return
ldr r0, stack
mov sp, r0
return:
bx lr
.align 0
stack:
.word 0
reset:
.word 0
dst_addr:
.word 0
src_addr:
.word 0
words:
.word 0

View File

@@ -0,0 +1,25 @@
// WARNING!!! DO NOT EDIT - FILE GENERATED BY APPLETGEN
#include "WordCopyArm.h"
#include "WordCopyApplet.h"
WordCopyArm WordCopyApplet::applet = {
// dst_addr
0x00000028,
// reset
0x00000024,
// src_addr
0x0000002c,
// stack
0x00000020,
// start
0x00000000,
// words
0x00000030,
// code
{
0x09, 0x48, 0x0a, 0x49, 0x0a, 0x4a, 0x02, 0xe0, 0x08, 0xc9, 0x08, 0xc0, 0x01, 0x3a, 0x00, 0x2a,
0xfa, 0xd1, 0x04, 0x48, 0x00, 0x28, 0x01, 0xd1, 0x01, 0x48, 0x85, 0x46, 0x70, 0x47, 0xc0, 0x46,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}
};

View File

@@ -0,0 +1,18 @@
// WARNING!!! DO NOT EDIT - FILE GENERATED BY APPLETGEN
#ifndef _WORDCOPYARM_H
#define _WORDCOPYARM_H
#include <stdint.h>
typedef struct
{
uint32_t dst_addr;
uint32_t reset;
uint32_t src_addr;
uint32_t stack;
uint32_t start;
uint32_t words;
uint8_t code[52];
} WordCopyArm;
#endif // _WORDCOPYARM_H

489
lib/bossac/src/bossac.cpp Normal file
View File

@@ -0,0 +1,489 @@
///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2018, ShumaTech
// 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 following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
///////////////////////////////////////////////////////////////////////////////
#include <string>
#include <exception>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/time.h>
#include "CmdOpts.h"
#include "Samba.h"
#include "PortFactory.h"
#include "Device.h"
#include "Flasher.h"
using namespace std;
class BossaConfig
{
public:
BossaConfig();
virtual ~BossaConfig() {}
bool erase;
bool write;
bool read;
bool verify;
bool offset;
bool reset;
bool port;
bool boot;
bool bor;
bool bod;
bool lock;
bool unlock;
bool security;
bool info;
bool debug;
bool help;
bool usbPort;
bool arduinoErase;
int readArg;
int offsetArg;
string portArg;
int bootArg;
int bodArg;
int borArg;
string lockArg;
string unlockArg;
bool usbPortArg;
};
BossaConfig::BossaConfig()
{
erase = false;
write = false;
read = false;
verify = false;
port = false;
boot = false;
bod = false;
bor = false;
lock = false;
security = false;
info = false;
help = false;
usbPort = false;
arduinoErase = false;
readArg = 0;
offsetArg = 0;
bootArg = 1;
bodArg = 1;
borArg = 1;
usbPortArg=1;
reset = false;
}
class BossaObserver : public FlasherObserver
{
public:
BossaObserver() : _lastTicks(-1) {}
virtual ~BossaObserver() {}
virtual void onStatus(const char *message, ...);
virtual void onProgress(int num, int div);
private:
int _lastTicks;
};
void
BossaObserver::onStatus(const char *message, ...)
{
va_list ap;
va_start(ap, message);
vprintf(message, ap);
va_end(ap);
}
void
BossaObserver::onProgress(int num, int div)
{
int ticks;
int bars = 30;
ticks = num * bars / div;
if (ticks == _lastTicks)
return;
printf("\r[");
while (ticks-- > 0)
{
putchar('=');
bars--;
}
while (bars-- > 0)
{
putchar(' ');
}
printf("] %d%% (%d/%d pages)", num * 100 / div, num, div);
fflush(stdout);
_lastTicks = 0;
}
static BossaConfig config;
static Option opts[] =
{
{
'e', "erase", &config.erase,
{ ArgNone },
"erase the entire flash starting at the offset"
},
{
'w', "write", &config.write,
{ ArgNone },
"write FILE to the flash; accelerated when\n"
"combined with erase option"
},
{
'r', "read", &config.read,
{ ArgOptional, ArgInt, "SIZE", { &config.readArg } },
"read SIZE from flash and store in FILE;\n"
"read entire flash if SIZE not specified"
},
{
'v', "verify", &config.verify,
{ ArgNone },
"verify FILE matches flash contents"
},
{
'o', "offset", &config.offset,
{ ArgRequired, ArgInt, "OFFSET", { &config.offsetArg } },
"start erase/write/read/verify operation at flash OFFSET;\n"
"OFFSET must be aligned to a flash page boundary"
},
{
'p', "port", &config.port,
{ ArgRequired, ArgString, "PORT", { &config.portArg } },
"use serial PORT to communicate to device;\n"
"default behavior is to use first serial port"
},
{
'b', "boot", &config.boot,
{ ArgOptional, ArgInt, "BOOL", { &config.bootArg } },
"boot from ROM if BOOL is 0;\n"
"boot from FLASH if BOOL is 1 [default];\n"
"option is ignored on unsupported devices"
},
{
'c', "bod", &config.bod,
{ ArgOptional, ArgInt, "BOOL", { &config.bodArg } },
"no brownout detection if BOOL is 0;\n"
"brownout detection is on if BOOL is 1 [default]"
},
{
't', "bor", &config.bor,
{ ArgOptional, ArgInt, "BOOL", { &config.borArg } },
"no brownout reset if BOOL is 0;\n"
"brownout reset is on if BOOL is 1 [default]"
},
{
'l', "lock", &config.lock,
{ ArgOptional, ArgString, "REGION", { &config.lockArg } },
"lock the flash REGION as a comma-separated list;\n"
"lock all if not given [default]"
},
{
'u', "unlock", &config.unlock,
{ ArgOptional, ArgString, "REGION", { &config.unlockArg } },
"unlock the flash REGION as a comma-separated list;\n"
"unlock all if not given [default]"
},
{
's', "security", &config.security,
{ ArgNone },
"set the flash security flag"
},
{
'i', "info", &config.info,
{ ArgNone },
"display device information"
},
{
'd', "debug", &config.debug,
{ ArgNone },
"print debug messages"
},
{
'h', "help", &config.help,
{ ArgNone },
"display this help text"
},
{
'U', "usb-port", &config.usbPort,
{ ArgOptional, ArgInt, "BOOL", { &config.usbPortArg } },
"force serial port detection to USB if BOOL is 1 [default]\n"
"or to RS-232 if BOOL is 0"
},
{
'R', "reset", &config.reset,
{ ArgNone },
"reset CPU (if supported)"
},
{
'a', "arduino-erase", &config.arduinoErase,
{ ArgNone },
"erase and reset via Arduino 1200 baud hack"
}
};
int
help(const char* program)
{
fprintf(stderr, "Try '%s -h' or '%s --help' for more information\n", program, program);
return 1;
}
static struct timeval start_time;
void
timer_start()
{
gettimeofday(&start_time, NULL);
}
float
timer_stop()
{
struct timeval end;
gettimeofday(&end, NULL);
return (end.tv_sec - start_time.tv_sec) + (end.tv_usec - start_time.tv_usec) / 1000000.0;
}
int
main(int argc, char* argv[])
{
int args;
char* pos;
CmdOpts cmd(argc, argv, sizeof(opts) / sizeof(opts[0]), opts);
if ((pos = strrchr(argv[0], '/')) || (pos = strrchr(argv[0], '\\')))
argv[0] = pos + 1;
if (argc <= 1)
{
fprintf(stderr, "%s: you must specify at least one option\n", argv[0]);
return help(argv[0]);
}
args = cmd.parse();
if (args < 0)
return help(argv[0]);
if (config.read && (config.write || config.verify))
{
fprintf(stderr, "%s: read option is exclusive of write or verify\n", argv[0]);
return help(argv[0]);
}
if (config.read || config.write || config.verify)
{
if (args == argc)
{
fprintf(stderr, "%s: missing file\n", argv[0]);
return help(argv[0]);
}
argc--;
}
if (args != argc)
{
fprintf(stderr, "%s: extra arguments found\n", argv[0]);
return help(argv[0]);
}
if (config.help)
{
printf("Usage: %s [OPTION...] [FILE]\n", argv[0]);
printf("Basic Open Source SAM-BA Application (BOSSA) Version " VERSION "\n"
"Flash programmer for Atmel SAM devices.\n"
"Copyright (c) 2011-2018 ShumaTech (http://www.shumatech.com)\n"
"\n"
"Examples:\n"
" bossac -e -w -v -b image.bin # Erase flash, write flash with image.bin,\n"
" # verify the write, and set boot from flash\n"
" bossac -r0x10000 image.bin # Read 64KB from flash and store in image.bin\n"
);
printf("\nOptions:\n");
cmd.usage(stdout);
printf("\nReport bugs to <bugs@shumatech.com>\n");
return 1;
}
try
{
Samba samba;
PortFactory portFactory;
if (config.debug)
samba.setDebug(true);
if (!config.port)
config.portArg = portFactory.def();
if (config.arduinoErase)
{
SerialPort::Ptr port;
port = portFactory.create(config.portArg, config.usbPortArg != 0);
if(!port->open(1200))
{
fprintf(stderr, "Failed to open port at 1200bps\n");
return 1;
}
port->setRTS(true);
port->setDTR(false);
port->close();
}
if (config.portArg.empty())
{
fprintf(stderr, "No serial ports available\n");
return 1;
}
bool res;
if (config.usbPort)
res = samba.connect(portFactory.create(config.portArg, config.usbPortArg != 0));
else
res = samba.connect(portFactory.create(config.portArg));
if (!res)
{
fprintf(stderr, "No device found on %s\n", config.portArg.c_str());
return 1;
}
Device device(samba);
device.create();
Device::FlashPtr& flash = device.getFlash();
BossaObserver observer;
Flasher flasher(samba, device, observer);
if (config.info)
{
FlasherInfo info;
flasher.info(info);
info.print();
}
if (config.unlock)
flasher.lock(config.unlockArg, false);
if (config.erase)
{
timer_start();
flasher.erase(config.offsetArg);
printf("\nDone in %5.3f seconds\n", timer_stop());
}
if (config.write)
{
timer_start();
flasher.write(argv[args], config.offsetArg);
printf("\nDone in %5.3f seconds\n", timer_stop());
}
if (config.verify)
{
uint32_t pageErrors;
uint32_t totalErrors;
timer_start();
if (!flasher.verify(argv[args], pageErrors, totalErrors, config.offsetArg))
{
printf("\nVerify failed\nPage errors: %d\nByte errors: %d\n",
pageErrors, totalErrors);
return 2;
}
printf("\nVerify successful\nDone in %5.3f seconds\n", timer_stop());
}
if (config.read)
{
timer_start();
flasher.read(argv[args], config.readArg, config.offsetArg);
printf("\nDone in %5.3f seconds\n", timer_stop());
}
if (config.boot)
{
printf("Set boot flash %s\n", config.bootArg ? "true" : "false");
flash->setBootFlash(config.bootArg);
}
if (config.bod)
{
printf("Set brownout detect %s\n", config.bodArg ? "true" : "false");
flash->setBod(config.bodArg);
}
if (config.bor)
{
printf("Set brownout reset %s\n", config.borArg ? "true" : "false");
flash->setBor(config.borArg);
}
if (config.security)
{
printf("Set security\n");
flash->setSecurity();
}
if (config.lock)
flasher.lock(config.lockArg, true);
flash->writeOptions();
if (config.reset)
device.reset();
}
catch (exception& e)
{
fprintf(stderr, "\n%s\n", e.what());
return 1;
}
catch(...)
{
fprintf(stderr, "\nUnhandled exception\n");
return 1;
}
return 0;
}

1258
lib/can2040/can2040.c Normal file

File diff suppressed because it is too large Load Diff

79
lib/can2040/can2040.h Normal file
View File

@@ -0,0 +1,79 @@
#ifndef _CAN2040_H
#define _CAN2040_H
#include <stdint.h> // uint32_t
struct can2040_msg {
uint32_t id;
uint32_t dlc;
union {
uint8_t data[8];
uint32_t data32[2];
};
};
enum {
CAN2040_ID_RTR = 1<<30,
CAN2040_ID_EFF = 1<<31,
};
enum {
CAN2040_NOTIFY_RX = 1<<20,
CAN2040_NOTIFY_TX = 1<<21,
CAN2040_NOTIFY_ERROR = 1<<23,
};
struct can2040;
typedef void (*can2040_rx_cb)(struct can2040 *cd, uint32_t notify
, struct can2040_msg *msg);
void can2040_setup(struct can2040 *cd, uint32_t pio_num);
void can2040_callback_config(struct can2040 *cd, can2040_rx_cb rx_cb);
void can2040_start(struct can2040 *cd, uint32_t sys_clock, uint32_t bitrate
, uint32_t gpio_rx, uint32_t gpio_tx);
void can2040_shutdown(struct can2040 *cd);
void can2040_pio_irq_handler(struct can2040 *cd);
int can2040_check_transmit(struct can2040 *cd);
int can2040_transmit(struct can2040 *cd, struct can2040_msg *msg);
/****************************************************************
* Internal definitions
****************************************************************/
struct can2040_bitunstuffer {
uint32_t stuffed_bits, count_stuff;
uint32_t unstuffed_bits, count_unstuff;
};
struct can2040_transmit {
struct can2040_msg msg;
uint32_t crc, stuffed_words, stuffed_data[5];
};
struct can2040 {
// Setup
uint32_t pio_num;
void *pio_hw;
uint32_t gpio_rx, gpio_tx;
can2040_rx_cb rx_cb;
// Bit unstuffing
struct can2040_bitunstuffer unstuf;
uint32_t raw_bit_count;
// Input data state
uint32_t parse_state;
uint32_t parse_crc;
struct can2040_msg parse_msg;
// Reporting
uint32_t report_state;
uint32_t report_eof_key;
// Transmits
uint32_t tx_state;
uint32_t tx_pull_pos, tx_push_pos;
struct can2040_transmit tx_queue[4];
};
#endif // can2040.h

624
lib/canboot/flash_can.py Normal file
View File

@@ -0,0 +1,624 @@
#!/usr/bin/env python3
# Script to upload software via Can Bootloader
#
# Copyright (C) 2022 Eric Callahan <arksine.code@gmail.com>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
from __future__ import annotations
import sys
import os
import asyncio
import socket
import struct
import logging
import errno
import argparse
import hashlib
import pathlib
from typing import Dict, List, Optional, Union
def output_line(msg: str) -> None:
sys.stdout.write(msg + "\n")
sys.stdout.flush()
def output(msg: str) -> None:
sys.stdout.write(msg)
sys.stdout.flush()
# Standard crc16 ccitt, take from msgproto.py in Klipper
def crc16_ccitt(buf: Union[bytes, bytearray]) -> int:
crc = 0xffff
for data in buf:
data ^= crc & 0xff
data ^= (data & 0x0f) << 4
crc = ((data << 8) | (crc >> 8)) ^ (data >> 4) ^ (data << 3)
return crc & 0xFFFF
logging.basicConfig(level=logging.INFO)
CAN_FMT = "<IB3x8s"
CAN_READER_LIMIT = 1024 * 1024
# Canboot Defs
CMD_HEADER = b'\x01\x88'
CMD_TRAILER = b'\x99\x03'
BOOTLOADER_CMDS = {
'CONNECT': 0x11,
'SEND_BLOCK': 0x12,
'SEND_EOF': 0x13,
'REQUEST_BLOCK': 0x14,
'COMPLETE': 0x15,
'GET_CANBUS_ID': 0x16,
}
ACK_SUCCESS = 0xa0
NACK = 0xf1
# Klipper Admin Defs (for jumping to bootloader)
KLIPPER_ADMIN_ID = 0x3f0
KLIPPER_SET_NODE_CMD = 0x01
KLIPPER_REBOOT_CMD = 0x02
# CAN Admin Defs
CANBUS_ID_ADMIN = 0x3f0
CANBUS_ID_ADMIN_RESP = 0x3f1
CANBUS_CMD_QUERY_UNASSIGNED = 0x00
CANBUS_CMD_SET_NODEID = 0x11
CANBUS_CMD_CLEAR_NODE_ID = 0x12
CANBUS_RESP_NEED_NODEID = 0x20
CANBUS_NODEID_OFFSET = 128
class FlashCanError(Exception):
pass
class CanFlasher:
def __init__(
self,
node: CanNode,
fw_file: pathlib.Path
) -> None:
self.node = node
self.fw_name = fw_file
self.fw_sha = hashlib.sha1()
self.file_size = 0
self.block_size = 64
self.block_count = 0
self.app_start_addr = 0
async def connect_btl(self):
output_line("Attempting to connect to bootloader")
ret = await self.send_command('CONNECT')
pinfo = ret[:12]
mcu_type = ret[12:]
ver_bytes, start_addr, self.block_size = struct.unpack("<4sII", pinfo)
self.app_start_addr = start_addr
proto_version = ".".join([str(v) for v in reversed(ver_bytes[:3])])
if self.block_size not in [64, 128, 256, 512]:
raise FlashCanError("Invalid Block Size: %d" % (self.block_size,))
while mcu_type and mcu_type[-1] == 0x00:
mcu_type = mcu_type[:-1]
mcu_type = mcu_type.decode()
output_line(
f"CanBoot Connected\nProtocol Version: {proto_version}\n"
f"Block Size: {self.block_size} bytes\n"
f"Application Start: 0x{self.app_start_addr:4X}\n"
f"MCU type: {mcu_type}"
)
async def verify_canbus_uuid(self, uuid):
output_line("Verifying canbus connection")
ret = await self.send_command('GET_CANBUS_ID')
mcu_uuid = sum([v << ((5 - i) * 8) for i, v in enumerate(ret[:6])])
if mcu_uuid != uuid:
raise FlashCanError("UUID mismatch (%s vs %s)" % (uuid, mcu_uuid))
async def send_command(
self,
cmdname: str,
payload: bytes = b"",
tries: int = 5
) -> bytearray:
word_cnt = (len(payload) // 4) & 0xFF
cmd = BOOTLOADER_CMDS[cmdname]
out_cmd = bytearray(CMD_HEADER)
out_cmd.append(cmd)
out_cmd.append(word_cnt)
if payload:
out_cmd.extend(payload)
crc = crc16_ccitt(out_cmd[2:])
out_cmd.extend(struct.pack("<H", crc))
out_cmd.extend(CMD_TRAILER)
while tries:
data = bytearray()
recd_len = 0
try:
self.node.write(out_cmd)
read_done = False
while not read_done:
ret = await self.node.readuntil()
data.extend(ret)
while len(data) > 7:
if data[:2] != CMD_HEADER:
data = data[1:]
continue
recd_len = data[3] * 4
read_done = len(data) == recd_len + 8
break
except Exception:
logging.exception("Can Read Error")
else:
trailer = data[-2:]
recd_crc, = struct.unpack("<H", data[-4:-2])
calc_crc = crc16_ccitt(data[2:-4])
recd_ack = data[2]
cmd_response = 0
if recd_len:
cmd_response, = struct.unpack("<I", data[4:8])
if trailer != CMD_TRAILER:
logging.info(
f"Command '{cmdname}': Invalid Trailer Received "
f"0x{trailer.hex()}"
)
elif recd_crc != calc_crc:
logging.info(
f"Command '{cmdname}': Frame CRC Mismatch, expected: "
f"{calc_crc}, received {recd_crc}"
)
elif recd_ack != ACK_SUCCESS:
logging.info(f"Command '{cmdname}': Received NACK")
elif cmd_response != cmd:
logging.info(
f"Command '{cmdname}': Acknowledged wrong command, "
f"expected: {cmd:2x}, received: {cmd_response:2x}"
)
else:
# Validation passed, return payload sans command
if recd_len <= 4:
return bytearray()
return data[8:recd_len + 4]
tries -= 1
# clear the read buffer
try:
await self.node.read(1024, timeout=.1)
except asyncio.TimeoutError:
pass
await asyncio.sleep(.1)
raise FlashCanError("Error sending command [%s] to Can Device"
% (cmdname))
async def send_file(self):
last_percent = 0
output_line("Flashing '%s'..." % (self.fw_name))
output("\n[")
with open(self.fw_name, 'rb') as f:
f.seek(0, os.SEEK_END)
self.file_size = f.tell()
f.seek(0)
flash_address = self.app_start_addr
while True:
buf = f.read(self.block_size)
if not buf:
break
if len(buf) < self.block_size:
buf += b"\xFF" * (self.block_size - len(buf))
self.fw_sha.update(buf)
prefix = struct.pack("<I", flash_address)
for _ in range(3):
resp = await self.send_command('SEND_BLOCK', prefix + buf)
recd_addr, = struct.unpack("<I", resp)
if recd_addr == flash_address:
break
logging.info(
f"Block write mismatch: expected: {flash_address:4X}, "
f"received: {recd_addr:4X}"
)
await asyncio.sleep(.1)
else:
raise FlashCanError(
f"Flash write failed, block address 0x{recd_addr:4X}"
)
flash_address += self.block_size
self.block_count += 1
uploaded = self.block_count * self.block_size
pct = int(uploaded / float(self.file_size) * 100 + .5)
if pct >= last_percent + 2:
last_percent += 2.
output("#")
resp = await self.send_command('SEND_EOF')
page_count, = struct.unpack("<I", resp)
output_line("]\n\nWrite complete: %d pages" % (page_count))
async def verify_file(self):
last_percent = 0
output_line("Verifying (block count = %d)..." % (self.block_count,))
output("\n[")
ver_sha = hashlib.sha1()
for i in range(self.block_count):
flash_address = i * self.block_size + self.app_start_addr
for _ in range(3):
payload = struct.pack("<I", flash_address)
resp = await self.send_command("REQUEST_BLOCK", payload)
recd_addr, = struct.unpack("<I", resp[:4])
if recd_addr == flash_address:
break
logging.info(
f"Block read mismatch: expected: 0x{flash_address:4X}, "
f"received: 0x{recd_addr}"
)
await asyncio.sleep(.1)
else:
output_line("Error")
raise FlashCanError("Block Request Error, block: %d" % (i,))
ver_sha.update(resp[4:])
pct = int(i * self.block_size / float(self.file_size) * 100 + .5)
if pct >= last_percent + 2:
last_percent += 2
output("#")
ver_hex = ver_sha.hexdigest().upper()
fw_hex = self.fw_sha.hexdigest().upper()
if ver_hex != fw_hex:
raise FlashCanError("Checksum mismatch: Expected %s, Received %s"
% (fw_hex, ver_hex))
output_line("]\n\nVerification Complete: SHA = %s" % (ver_hex))
async def finish(self):
await self.send_command("COMPLETE")
class CanNode:
def __init__(self, node_id: int, cansocket: CanSocket) -> None:
self.node_id = node_id
self._reader = asyncio.StreamReader(CAN_READER_LIMIT)
self._cansocket = cansocket
async def read(
self, n: int = -1, timeout: Optional[float] = 2
) -> bytes:
return await asyncio.wait_for(self._reader.read(n), timeout)
async def readexactly(
self, n: int, timeout: Optional[float] = 2
) -> bytes:
return await asyncio.wait_for(self._reader.readexactly(n), timeout)
async def readuntil(
self, sep: bytes = b"\x03", timeout: Optional[float] = 2
) -> bytes:
return await asyncio.wait_for(self._reader.readuntil(sep), timeout)
def write(self, payload: Union[bytes, bytearray]) -> None:
if isinstance(payload, bytearray):
payload = bytes(payload)
self._cansocket.send(self.node_id, payload)
async def write_with_response(
self,
payload: Union[bytearray, bytes],
resp_length: int,
timeout: Optional[float] = 2.
) -> bytes:
self.write(payload)
return await self.readexactly(resp_length, timeout)
def feed_data(self, data: bytes) -> None:
self._reader.feed_data(data)
def close(self) -> None:
self._reader.feed_eof()
class CanSocket:
def __init__(self, loop: asyncio.AbstractEventLoop):
self._loop = loop
self.cansock = socket.socket(socket.PF_CAN, socket.SOCK_RAW,
socket.CAN_RAW)
self.admin_node = CanNode(CANBUS_ID_ADMIN, self)
self.nodes: Dict[int, CanNode] = {
CANBUS_ID_ADMIN_RESP: self.admin_node
}
self.input_buffer = b""
self.output_packets: List[bytes] = []
self.input_busy = False
self.output_busy = False
self.closed = True
def _handle_can_response(self) -> None:
try:
data = self.cansock.recv(4096)
except socket.error as e:
# If bad file descriptor allow connection to be
# closed by the data check
if e.errno == errno.EBADF:
logging.exception("Can Socket Read Error, closing")
data = b''
else:
return
if not data:
# socket closed
self.close()
return
self.input_buffer += data
if self.input_busy:
return
self.input_busy = True
while len(self.input_buffer) >= 16:
packet = self.input_buffer[:16]
self._process_packet(packet)
self.input_buffer = self.input_buffer[16:]
self.input_busy = False
def _process_packet(self, packet: bytes) -> None:
can_id, length, data = struct.unpack(CAN_FMT, packet)
can_id &= socket.CAN_EFF_MASK
payload = data[:length]
node = self.nodes.get(can_id)
if node is not None:
node.feed_data(payload)
def send(self, can_id: int, payload: bytes = b"") -> None:
if can_id > 0x7FF:
can_id |= socket.CAN_EFF_FLAG
if not payload:
packet = struct.pack(CAN_FMT, can_id, 0, b"")
self.output_packets.append(packet)
else:
while payload:
length = min(len(payload), 8)
pkt_data = payload[:length]
payload = payload[length:]
packet = struct.pack(
CAN_FMT, can_id, length, pkt_data)
self.output_packets.append(packet)
if self.output_busy:
return
self.output_busy = True
asyncio.create_task(self._do_can_send())
async def _do_can_send(self):
while self.output_packets:
packet = self.output_packets.pop(0)
try:
await self._loop.sock_sendall(self.cansock, packet)
except socket.error:
logging.info("Socket Write Error, closing")
self.close()
break
self.output_busy = False
def _jump_to_bootloader(self, uuid: int):
# TODO: Send Klipper Admin command to jump to bootloader.
# It will need to be implemented
output_line("Sending bootloader jump command...")
plist = [(uuid >> ((5 - i) * 8)) & 0xFF for i in range(6)]
plist.insert(0, KLIPPER_REBOOT_CMD)
self.send(KLIPPER_ADMIN_ID, bytes(plist))
async def _query_uuids(self) -> List[int]:
output_line("Checking for canboot nodes...")
payload = bytes([CANBUS_CMD_QUERY_UNASSIGNED])
self.admin_node.write(payload)
curtime = self._loop.time()
endtime = curtime + 2.
self.uuids: List[int] = []
while curtime < endtime:
diff = endtime - curtime
try:
resp = await self.admin_node.readexactly(8, diff)
except asyncio.TimeoutError:
break
finally:
curtime = self._loop.time()
if resp[0] != CANBUS_RESP_NEED_NODEID:
continue
app_names = {
KLIPPER_SET_NODE_CMD: "Klipper",
CANBUS_CMD_SET_NODEID: "CanBoot"
}
app = app_names.get(resp[7], "Unknown")
data = resp[1:7]
output_line(f"Detected UUID: {data.hex()}, Application: {app}")
uuid = sum([v << ((5 - i) * 8) for i, v in enumerate(data)])
if uuid not in self.uuids and app == "CanBoot":
self.uuids.append(uuid)
return self.uuids
def _reset_nodes(self) -> None:
output_line("Resetting all bootloader node IDs...")
payload = bytes([CANBUS_CMD_CLEAR_NODE_ID])
self.admin_node.write(payload)
def _set_node_id(self, uuid: int) -> CanNode:
# Convert ID to a list
plist = [(uuid >> ((5 - i) * 8)) & 0xFF for i in range(6)]
plist.insert(0, CANBUS_CMD_SET_NODEID)
node_id = len(self.nodes) + CANBUS_NODEID_OFFSET
plist.append(node_id)
payload = bytes(plist)
self.admin_node.write(payload)
decoded_id = node_id * 2 + 0x100
node = CanNode(decoded_id, self)
self.nodes[decoded_id + 1] = node
return node
async def run(self, intf: str, uuid: int, fw_path: pathlib.Path) -> None:
if not fw_path.is_file():
raise FlashCanError("Invalid firmware path '%s'" % (fw_path))
try:
self.cansock.bind((intf,))
except Exception:
raise FlashCanError("Unable to bind socket to can0")
self.closed = False
self.cansock.setblocking(False)
self._loop.add_reader(
self.cansock.fileno(), self._handle_can_response)
self._jump_to_bootloader(uuid)
await asyncio.sleep(.5)
self._reset_nodes()
await asyncio.sleep(.5)
id_list = await self._query_uuids()
if uuid not in id_list:
raise FlashCanError(
f"Unable to find node matching UUID: {uuid:06x}"
)
node = self._set_node_id(uuid)
flasher = CanFlasher(node, fw_path)
await asyncio.sleep(.5)
try:
await flasher.connect_btl()
await flasher.verify_canbus_uuid(uuid)
await flasher.send_file()
await flasher.verify_file()
finally:
# always attempt to send the complete command. If
# there is an error it will exit the bootloader
# unless comms were broken
await flasher.finish()
async def run_query(self, intf: str):
try:
self.cansock.bind((intf,))
except Exception:
raise FlashCanError("Unable to bind socket to can0")
self.closed = False
self.cansock.setblocking(False)
self._loop.add_reader(
self.cansock.fileno(), self._handle_can_response)
self._reset_nodes()
await asyncio.sleep(.5)
await self._query_uuids()
def close(self):
if self.closed:
return
self.closed = True
for node in self.nodes.values():
node.close()
self._loop.remove_reader(self.cansock.fileno())
self.cansock.close()
class SerialSocket:
def __init__(self, loop: asyncio.AbstractEventLoop):
self._loop = loop
self.serial = self.serial_error = None
self.node = CanNode(0, self)
def _handle_response(self) -> None:
try:
data = self.serial.read(4096)
except self.serial_error as e:
logging.exception("Error on serial read")
self.close()
self.node.feed_data(data)
def send(self, can_id: int, payload: bytes = b"") -> None:
try:
self.serial.write(payload)
except self.serial_error as e:
logging.exception("Error on serial write")
self.close()
async def run(self, intf: str, baud: int, fw_path: pathlib.Path) -> None:
if not fw_path.is_file():
raise FlashCanError("Invalid firmware path '%s'" % (fw_path))
import serial
self.serial_error = serial.SerialException
try:
serial_dev = serial.Serial(baudrate=baud, timeout=0,
exclusive=True)
serial_dev.port = intf
serial_dev.open()
except (OSError, IOError, self.serial_error) as e:
raise FlashCanError("Unable to open serial port: %s" % (e,))
self.serial = serial_dev
self._loop.add_reader(self.serial.fileno(), self._handle_response)
flasher = CanFlasher(self.node, fw_path)
try:
await flasher.connect_btl()
await flasher.send_file()
await flasher.verify_file()
finally:
# always attempt to send the complete command. If
# there is an error it will exit the bootloader
# unless comms were broken
await flasher.finish()
def close(self):
if self.serial is None:
return
self._loop.remove_reader(self.serial.fileno())
self.serial.close()
self.serial = None
def main():
parser = argparse.ArgumentParser(
description="Can Bootloader Flash Utility")
parser.add_argument(
"-d", "--device", metavar='<serial device>',
help="Serial Device"
)
parser.add_argument(
"-b", "--baud", default=250000, metavar='<baud rate>',
help="Serial baud rate"
)
parser.add_argument(
"-i", "--interface", default="can0", metavar='<can interface>',
help="Can Interface"
)
parser.add_argument(
"-f", "--firmware", metavar="<klipper.bin>",
default="~/klipper/out/klipper.bin",
help="Path to Klipper firmware file")
parser.add_argument(
"-u", "--uuid", metavar="<uuid>", default=None,
help="Can device uuid"
)
parser.add_argument(
"-q", "--query", action="store_true",
help="Query Bootloader Device IDs"
)
parser.add_argument(
"-v", "--verbose", action="store_true",
help="Enable verbose responses"
)
args = parser.parse_args()
if not args.verbose:
logging.getLogger().setLevel(logging.ERROR)
intf = args.interface
fpath = pathlib.Path(args.firmware).expanduser().resolve()
loop = asyncio.get_event_loop()
iscan = args.device is None
sock = None
try:
if iscan:
sock = CanSocket(loop)
if args.query:
loop.run_until_complete(sock.run_query(intf))
else:
if args.uuid is None:
raise FlashCanError(
"The 'uuid' option must be specified to flash a device"
)
uuid = int(args.uuid, 16)
loop.run_until_complete(sock.run(intf, uuid, fpath))
else:
if args.device is None:
raise FlashCanError(
"The 'device' option must be specified to flash a device"
)
sock = SerialSocket(loop)
loop.run_until_complete(sock.run(args.device, args.baud, fpath))
except Exception as e:
logging.exception("Can Flash Error")
sys.exit(-1)
finally:
if sock is not None:
sock.close()
if args.query:
output_line("Query Complete")
else:
output_line("CAN Flash Success")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,411 @@
/******************************************************************************
* @file cachel1_armv7.h
* @brief CMSIS Level 1 Cache API for Armv7-M and later
* @version V1.0.0
* @date 03. March 2020
******************************************************************************/
/*
* Copyright (c) 2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef ARM_CACHEL1_ARMV7_H
#define ARM_CACHEL1_ARMV7_H
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_CacheFunctions Cache Functions
\brief Functions that configure Instruction and Data cache.
@{
*/
/* Cache Size ID Register Macros */
#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos)
#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos )
#ifndef __SCB_DCACHE_LINE_SIZE
#define __SCB_DCACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */
#endif
#ifndef __SCB_ICACHE_LINE_SIZE
#define __SCB_ICACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */
#endif
/**
\brief Enable I-Cache
\details Turns on I-Cache
*/
__STATIC_FORCEINLINE void SCB_EnableICache (void)
{
#if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */
__DSB();
__ISB();
SCB->ICIALLU = 0UL; /* invalidate I-Cache */
__DSB();
__ISB();
SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */
__DSB();
__ISB();
#endif
}
/**
\brief Disable I-Cache
\details Turns off I-Cache
*/
__STATIC_FORCEINLINE void SCB_DisableICache (void)
{
#if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
__DSB();
__ISB();
SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */
SCB->ICIALLU = 0UL; /* invalidate I-Cache */
__DSB();
__ISB();
#endif
}
/**
\brief Invalidate I-Cache
\details Invalidates I-Cache
*/
__STATIC_FORCEINLINE void SCB_InvalidateICache (void)
{
#if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
__DSB();
__ISB();
SCB->ICIALLU = 0UL;
__DSB();
__ISB();
#endif
}
/**
\brief I-Cache Invalidate by address
\details Invalidates I-Cache for the given address.
I-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity.
I-Cache memory blocks which are part of given address + given size are invalidated.
\param[in] addr address
\param[in] isize size of memory block (in number of bytes)
*/
__STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr (void *addr, int32_t isize)
{
#if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
if ( isize > 0 ) {
int32_t op_size = isize + (((uint32_t)addr) & (__SCB_ICACHE_LINE_SIZE - 1U));
uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_ICACHE_LINE_SIZE - 1U) */;
__DSB();
do {
SCB->ICIMVAU = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
op_addr += __SCB_ICACHE_LINE_SIZE;
op_size -= __SCB_ICACHE_LINE_SIZE;
} while ( op_size > 0 );
__DSB();
__ISB();
}
#endif
}
/**
\brief Enable D-Cache
\details Turns on D-Cache
*/
__STATIC_FORCEINLINE void SCB_EnableDCache (void)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
uint32_t ccsidr;
uint32_t sets;
uint32_t ways;
if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */
SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
ccsidr = SCB->CCSIDR;
/* invalidate D-Cache */
sets = (uint32_t)(CCSIDR_SETS(ccsidr));
do {
ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
do {
SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |
((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) );
#if defined ( __CC_ARM )
__schedule_barrier();
#endif
} while (ways-- != 0U);
} while(sets-- != 0U);
__DSB();
SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */
__DSB();
__ISB();
#endif
}
/**
\brief Disable D-Cache
\details Turns off D-Cache
*/
__STATIC_FORCEINLINE void SCB_DisableDCache (void)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
uint32_t ccsidr;
uint32_t sets;
uint32_t ways;
SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */
__DSB();
ccsidr = SCB->CCSIDR;
/* clean & invalidate D-Cache */
sets = (uint32_t)(CCSIDR_SETS(ccsidr));
do {
ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
do {
SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) );
#if defined ( __CC_ARM )
__schedule_barrier();
#endif
} while (ways-- != 0U);
} while(sets-- != 0U);
__DSB();
__ISB();
#endif
}
/**
\brief Invalidate D-Cache
\details Invalidates D-Cache
*/
__STATIC_FORCEINLINE void SCB_InvalidateDCache (void)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
uint32_t ccsidr;
uint32_t sets;
uint32_t ways;
SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
ccsidr = SCB->CCSIDR;
/* invalidate D-Cache */
sets = (uint32_t)(CCSIDR_SETS(ccsidr));
do {
ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
do {
SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |
((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) );
#if defined ( __CC_ARM )
__schedule_barrier();
#endif
} while (ways-- != 0U);
} while(sets-- != 0U);
__DSB();
__ISB();
#endif
}
/**
\brief Clean D-Cache
\details Cleans D-Cache
*/
__STATIC_FORCEINLINE void SCB_CleanDCache (void)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
uint32_t ccsidr;
uint32_t sets;
uint32_t ways;
SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
ccsidr = SCB->CCSIDR;
/* clean D-Cache */
sets = (uint32_t)(CCSIDR_SETS(ccsidr));
do {
ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
do {
SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) |
((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) );
#if defined ( __CC_ARM )
__schedule_barrier();
#endif
} while (ways-- != 0U);
} while(sets-- != 0U);
__DSB();
__ISB();
#endif
}
/**
\brief Clean & Invalidate D-Cache
\details Cleans and Invalidates D-Cache
*/
__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
uint32_t ccsidr;
uint32_t sets;
uint32_t ways;
SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
ccsidr = SCB->CCSIDR;
/* clean & invalidate D-Cache */
sets = (uint32_t)(CCSIDR_SETS(ccsidr));
do {
ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
do {
SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) );
#if defined ( __CC_ARM )
__schedule_barrier();
#endif
} while (ways-- != 0U);
} while(sets-- != 0U);
__DSB();
__ISB();
#endif
}
/**
\brief D-Cache Invalidate by address
\details Invalidates D-Cache for the given address.
D-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity.
D-Cache memory blocks which are part of given address + given size are invalidated.
\param[in] addr address
\param[in] dsize size of memory block (in number of bytes)
*/
__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (void *addr, int32_t dsize)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
if ( dsize > 0 ) {
int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
__DSB();
do {
SCB->DCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
op_addr += __SCB_DCACHE_LINE_SIZE;
op_size -= __SCB_DCACHE_LINE_SIZE;
} while ( op_size > 0 );
__DSB();
__ISB();
}
#endif
}
/**
\brief D-Cache Clean by address
\details Cleans D-Cache for the given address
D-Cache is cleaned starting from a 32 byte aligned address in 32 byte granularity.
D-Cache memory blocks which are part of given address + given size are cleaned.
\param[in] addr address
\param[in] dsize size of memory block (in number of bytes)
*/
__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
if ( dsize > 0 ) {
int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
__DSB();
do {
SCB->DCCMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
op_addr += __SCB_DCACHE_LINE_SIZE;
op_size -= __SCB_DCACHE_LINE_SIZE;
} while ( op_size > 0 );
__DSB();
__ISB();
}
#endif
}
/**
\brief D-Cache Clean and Invalidate by address
\details Cleans and invalidates D_Cache for the given address
D-Cache is cleaned and invalidated starting from a 32 byte aligned address in 32 byte granularity.
D-Cache memory blocks which are part of given address + given size are cleaned and invalidated.
\param[in] addr address (aligned to 32-byte boundary)
\param[in] dsize size of memory block (in number of bytes)
*/
__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
if ( dsize > 0 ) {
int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
__DSB();
do {
SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
op_addr += __SCB_DCACHE_LINE_SIZE;
op_size -= __SCB_DCACHE_LINE_SIZE;
} while ( op_size > 0 );
__DSB();
__ISB();
}
#endif
}
/*@} end of CMSIS_Core_CacheFunctions */
#endif /* ARM_CACHEL1_ARMV7_H */

View File

@@ -0,0 +1,283 @@
/**************************************************************************//**
* @file cmsis_compiler.h
* @brief CMSIS compiler generic header file
* @version V5.1.0
* @date 09. October 2018
******************************************************************************/
/*
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_COMPILER_H
#define __CMSIS_COMPILER_H
#include <stdint.h>
/*
* Arm Compiler 4/5
*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*
* Arm Compiler 6.6 LTM (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100)
#include "cmsis_armclang_ltm.h"
/*
* Arm Compiler above 6.10.1 (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
#include "cmsis_armclang.h"
/*
* GNU Compiler
*/
#elif defined ( __GNUC__ )
#include "cmsis_gcc.h"
/*
* IAR Compiler
*/
#elif defined ( __ICCARM__ )
#include <cmsis_iccarm.h>
/*
* TI Arm Compiler
*/
#elif defined ( __TI_ARM__ )
#include <cmsis_ccs.h>
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed))
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
/*
* TASKING Compiler
*/
#elif defined ( __TASKING__ )
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __packed__
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __packed__
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __packed__
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __align(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
/*
* COSMIC Compiler
*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#ifndef __ASM
#define __ASM _asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
// NO RETURN is automatically detected hence no warning here
#define __NO_RETURN
#endif
#ifndef __USED
#warning No compiler specific solution for __USED. __USED is ignored.
#define __USED
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __PACKED
#define __PACKED @packed
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT @packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION @packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
@packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
#else
#error Unknown compiler.
#endif
#endif /* __CMSIS_COMPILER_H */

2177
lib/cmsis-core/cmsis_gcc.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
/**************************************************************************//**
* @file cmsis_version.h
* @brief CMSIS Core(M) Version definitions
* @version V5.0.4
* @date 23. July 2019
******************************************************************************/
/*
* Copyright (c) 2009-2019 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CMSIS_VERSION_H
#define __CMSIS_VERSION_H
/* CMSIS Version definitions */
#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
#define __CM_CMSIS_VERSION_SUB ( 4U) /*!< [15:0] CMSIS Core(M) sub version */
#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
__CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
#endif

952
lib/cmsis-core/core_cm0.h Normal file
View File

@@ -0,0 +1,952 @@
/**************************************************************************//**
* @file core_cm0.h
* @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
* @version V5.0.8
* @date 21. August 2019
******************************************************************************/
/*
* Copyright (c) 2009-2019 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CORE_CM0_H_GENERIC
#define __CORE_CM0_H_GENERIC
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
\page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
CMSIS violates the following MISRA-C:2004 rules:
\li Required Rule 8.5, object/function definition in header file.<br>
Function definitions in header files are used to allow 'inlining'.
\li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
Unions are used for effective representation of core registers.
\li Advisory Rule 19.7, Function-like macro defined.<br>
Function-like macros are used to allow more efficient code.
*/
/*******************************************************************************
* CMSIS definitions
******************************************************************************/
/**
\ingroup Cortex_M0
@{
*/
#include "cmsis_version.h"
/* CMSIS CM0 definitions */
#define __CM0_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __CM0_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \
__CM0_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M (0U) /*!< Cortex-M Core */
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
*/
#define __FPU_USED 0U
#if defined ( __CC_ARM )
#if defined __TARGET_FPU_VFP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#if defined __ARM_FP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __GNUC__ )
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __ICCARM__ )
#if defined __ARMVFP__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TI_ARM__ )
#if defined __TI_VFP_SUPPORT__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TASKING__ )
#if defined __FPU_VFP__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __CSMC__ )
#if ( __CSMC__ & 0x400U)
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#endif
#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CM0_H_GENERIC */
#ifndef __CMSIS_GENERIC
#ifndef __CORE_CM0_H_DEPENDANT
#define __CORE_CM0_H_DEPENDANT
#ifdef __cplusplus
extern "C" {
#endif
/* check device defines and use defaults */
#if defined __CHECK_DEVICE_DEFINES
#ifndef __CM0_REV
#define __CM0_REV 0x0000U
#warning "__CM0_REV not defined in device header file; using default!"
#endif
#ifndef __NVIC_PRIO_BITS
#define __NVIC_PRIO_BITS 2U
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
#endif
#ifndef __Vendor_SysTickConfig
#define __Vendor_SysTickConfig 0U
#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
#endif
#endif
/* IO definitions (access restrictions to peripheral registers) */
/**
\defgroup CMSIS_glob_defs CMSIS Global Defines
<strong>IO Type Qualifiers</strong> are used
\li to specify the access to peripheral variables.
\li for automatic generation of peripheral register debug information.
*/
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
/* following defines should be used for structure members */
#define __IM volatile const /*! Defines 'read only' structure member permissions */
#define __OM volatile /*! Defines 'write only' structure member permissions */
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
/*@} end of group Cortex_M0 */
/*******************************************************************************
* Register Abstraction
Core Register contain:
- Core Register
- Core NVIC Register
- Core SCB Register
- Core SysTick Register
******************************************************************************/
/**
\defgroup CMSIS_core_register Defines and Type Definitions
\brief Type definitions and defines for Cortex-M processor based devices.
*/
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_CORE Status and Control Registers
\brief Core Register type definitions.
@{
*/
/**
\brief Union type to access the Application Program Status Register (APSR).
*/
typedef union
{
struct
{
uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} APSR_Type;
/* APSR Register Definitions */
#define APSR_N_Pos 31U /*!< APSR: N Position */
#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
#define APSR_Z_Pos 30U /*!< APSR: Z Position */
#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
#define APSR_C_Pos 29U /*!< APSR: C Position */
#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
#define APSR_V_Pos 28U /*!< APSR: V Position */
#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
/**
\brief Union type to access the Interrupt Program Status Register (IPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} IPSR_Type;
/* IPSR Register Definitions */
#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
/**
\brief Union type to access the Special-Purpose Program Status Registers (xPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} xPSR_Type;
/* xPSR Register Definitions */
#define xPSR_N_Pos 31U /*!< xPSR: N Position */
#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
#define xPSR_C_Pos 29U /*!< xPSR: C Position */
#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
#define xPSR_V_Pos 28U /*!< xPSR: V Position */
#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
#define xPSR_T_Pos 24U /*!< xPSR: T Position */
#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
/**
\brief Union type to access the Control Registers (CONTROL).
*/
typedef union
{
struct
{
uint32_t _reserved0:1; /*!< bit: 0 Reserved */
uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} CONTROL_Type;
/* CONTROL Register Definitions */
#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
/*@} end of group CMSIS_CORE */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
\brief Type definitions for the NVIC Registers
@{
*/
/**
\brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
*/
typedef struct
{
__IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[31U];
__IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RESERVED1[31U];
__IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[31U];
__IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[31U];
uint32_t RESERVED4[64U];
__IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
} NVIC_Type;
/*@} end of group CMSIS_NVIC */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_SCB System Control Block (SCB)
\brief Type definitions for the System Control Block Registers
@{
*/
/**
\brief Structure type to access the System Control Block (SCB).
*/
typedef struct
{
__IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
uint32_t RESERVED0;
__IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
__IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
__IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
uint32_t RESERVED1;
__IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
__IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
} SCB_Type;
/* SCB CPUID Register Definitions */
#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
/* SCB Interrupt Control State Register Definitions */
#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
/* SCB Application Interrupt and Reset Control Register Definitions */
#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
/* SCB System Control Register Definitions */
#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
/* SCB Configuration Control Register Definitions */
#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
/* SCB System Handler Control and State Register Definitions */
#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
/*@} end of group CMSIS_SCB */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_SysTick System Tick Timer (SysTick)
\brief Type definitions for the System Timer Registers.
@{
*/
/**
\brief Structure type to access the System Timer (SysTick).
*/
typedef struct
{
__IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
/* SysTick Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
/* SysTick Current Register Definitions */
#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
/* SysTick Calibration Register Definitions */
#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
/*@} end of group CMSIS_SysTick */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
\brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
Therefore they are not covered by the Cortex-M0 header file.
@{
*/
/*@} end of group CMSIS_CoreDebug */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_core_bitfield Core register bit field macros
\brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
@{
*/
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
\param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
\return Masked and shifted value.
*/
#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
\param[in] value Value of register. This parameter is interpreted as an uint32_t type.
\return Masked and shifted bit field value.
*/
#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_core_base Core Definitions
\brief Definitions for base addresses, unions, and structures.
@{
*/
/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
/*@} */
/*******************************************************************************
* Hardware Abstraction Layer
Core Function Interface contains:
- Core NVIC Functions
- Core SysTick Functions
- Core Register Access Functions
******************************************************************************/
/**
\defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
*/
/* ########################## NVIC functions #################################### */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_NVICFunctions NVIC Functions
\brief Functions that manage interrupts and exceptions via the NVIC.
@{
*/
#ifdef CMSIS_NVIC_VIRTUAL
#ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
#define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
#endif
#include CMSIS_NVIC_VIRTUAL_HEADER_FILE
#else
#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
#define NVIC_EnableIRQ __NVIC_EnableIRQ
#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
#define NVIC_DisableIRQ __NVIC_DisableIRQ
#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0 */
#define NVIC_SetPriority __NVIC_SetPriority
#define NVIC_GetPriority __NVIC_GetPriority
#define NVIC_SystemReset __NVIC_SystemReset
#endif /* CMSIS_NVIC_VIRTUAL */
#ifdef CMSIS_VECTAB_VIRTUAL
#ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
#define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
#endif
#include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
#else
#define NVIC_SetVector __NVIC_SetVector
#define NVIC_GetVector __NVIC_GetVector
#endif /* (CMSIS_VECTAB_VIRTUAL) */
#define NVIC_USER_IRQ_OFFSET 16
/* The following EXC_RETURN values are saved the LR on exception entry */
#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
/* Interrupt Priorities are WORD accessible only under Armv6-M */
/* The following MACROS handle generation of the register offset and byte masks */
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
#define __NVIC_SetPriorityGrouping(X) (void)(X)
#define __NVIC_GetPriorityGrouping() (0U)
/**
\brief Enable Interrupt
\details Enables a device specific interrupt in the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
__COMPILER_BARRIER();
NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
__COMPILER_BARRIER();
}
}
/**
\brief Get Interrupt Enable status
\details Returns a device specific interrupt enable status from the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\return 0 Interrupt is not enabled.
\return 1 Interrupt is enabled.
\note IRQn must not be negative.
*/
__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
else
{
return(0U);
}
}
/**
\brief Disable Interrupt
\details Disables a device specific interrupt in the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
__DSB();
__ISB();
}
}
/**
\brief Get Pending Interrupt
\details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
\param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
\note IRQn must not be negative.
*/
__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
else
{
return(0U);
}
}
/**
\brief Set Pending Interrupt
\details Sets the pending bit of a device specific interrupt in the NVIC pending register.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
}
}
/**
\brief Clear Pending Interrupt
\details Clears the pending bit of a device specific interrupt in the NVIC pending register.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
}
}
/**
\brief Set Interrupt Priority
\details Sets the priority of a device specific interrupt or a processor exception.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
\note The priority cannot be set for every processor exception.
*/
__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
else
{
SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
}
/**
\brief Get Interrupt Priority
\details Reads the priority of a device specific interrupt or a processor exception.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
else
{
return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
}
/**
\brief Encode Priority
\details Encodes the priority for an interrupt with the given priority group,
preemptive priority value, and subpriority value.
In case of a conflict between priority grouping and available
priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
\param [in] PriorityGroup Used priority group.
\param [in] PreemptPriority Preemptive priority value (starting from 0).
\param [in] SubPriority Subpriority value (starting from 0).
\return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
*/
__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
{
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
uint32_t PreemptPriorityBits;
uint32_t SubPriorityBits;
PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
return (
((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
);
}
/**
\brief Decode Priority
\details Decodes an interrupt priority value with a given priority group to
preemptive priority value and subpriority value.
In case of a conflict between priority grouping and available
priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
\param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
\param [in] PriorityGroup Used priority group.
\param [out] pPreemptPriority Preemptive priority value (starting from 0).
\param [out] pSubPriority Subpriority value (starting from 0).
*/
__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
{
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
uint32_t PreemptPriorityBits;
uint32_t SubPriorityBits;
PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
*pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
*pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
}
/**
\brief Set Interrupt Vector
\details Sets an interrupt vector in SRAM based interrupt vector table.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
Address 0 must be mapped to SRAM.
\param [in] IRQn Interrupt number
\param [in] vector Address of interrupt handler function
*/
__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
{
uint32_t *vectors = (uint32_t *)(NVIC_USER_IRQ_OFFSET << 2); /* point to 1st user interrupt */
*(vectors + (int32_t)IRQn) = vector; /* use pointer arithmetic to access vector */
/* ARM Application Note 321 states that the M0 does not require the architectural barrier */
}
/**
\brief Get Interrupt Vector
\details Reads an interrupt vector from interrupt vector table.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Address of interrupt handler function
*/
__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
{
uint32_t *vectors = (uint32_t *)(NVIC_USER_IRQ_OFFSET << 2); /* point to 1st user interrupt */
return *(vectors + (int32_t)IRQn); /* use pointer arithmetic to access vector */
}
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
SCB_AIRCR_SYSRESETREQ_Msk);
__DSB(); /* Ensure completion of memory access */
for(;;) /* wait until reset */
{
__NOP();
}
}
/*@} end of CMSIS_Core_NVICFunctions */
/* ########################## FPU functions #################################### */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_FpuFunctions FPU Functions
\brief Function that provides FPU type.
@{
*/
/**
\brief get FPU type
\details returns the FPU type
\returns
- \b 0: No FPU
- \b 1: Single precision FPU
- \b 2: Double + Single precision FPU
*/
__STATIC_INLINE uint32_t SCB_GetFPUType(void)
{
return 0U; /* No FPU */
}
/*@} end of CMSIS_Core_FpuFunctions */
/* ################################## SysTick function ############################################ */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_SysTickFunctions SysTick Functions
\brief Functions that configure the System.
@{
*/
#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
\details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
Counter is in free running mode to generate periodic interrupts.
\param [in] ticks Number of ticks between two interrupts.
\return 0 Function succeeded.
\return 1 Function failed.
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
must contain a vendor-specific implementation of this function.
*/
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL); /* Reload value impossible */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0UL); /* Function successful */
}
#endif
/*@} end of CMSIS_Core_SysTickFunctions */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CM0_H_DEPENDANT */
#endif /* __CMSIS_GENERIC */

File diff suppressed because it is too large Load Diff

1943
lib/cmsis-core/core_cm3.h Normal file

File diff suppressed because it is too large Load Diff

2129
lib/cmsis-core/core_cm4.h Normal file

File diff suppressed because it is too large Load Diff

2362
lib/cmsis-core/core_cm7.h Normal file

File diff suppressed because it is too large Load Diff

275
lib/cmsis-core/mpu_armv7.h Normal file
View File

@@ -0,0 +1,275 @@
/******************************************************************************
* @file mpu_armv7.h
* @brief CMSIS MPU API for Armv7-M MPU
* @version V5.1.1
* @date 10. February 2020
******************************************************************************/
/*
* Copyright (c) 2017-2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef ARM_MPU_ARMV7_H
#define ARM_MPU_ARMV7_H
#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes
#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes
#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes
#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes
#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes
#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte
#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes
#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes
#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes
#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes
#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes
#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes
#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes
#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes
#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes
#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte
#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes
#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes
#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes
#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes
#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes
#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes
#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes
#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes
#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes
#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte
#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes
#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes
#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access
#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only
#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only
#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access
#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only
#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access
/** MPU Region Base Address Register Value
*
* \param Region The region to be configured, number 0 to 15.
* \param BaseAddress The base address for the region.
*/
#define ARM_MPU_RBAR(Region, BaseAddress) \
(((BaseAddress) & MPU_RBAR_ADDR_Msk) | \
((Region) & MPU_RBAR_REGION_Msk) | \
(MPU_RBAR_VALID_Msk))
/**
* MPU Memory Access Attributes
*
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable Region is shareable between multiple bus masters.
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
*/
#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \
((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
(((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
(((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
(((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
(((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \
(((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \
(((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \
(((MPU_RASR_ENABLE_Msk))))
/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable Region is shareable between multiple bus masters.
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size)
/**
* MPU Memory Access Attribute for strongly ordered memory.
* - TEX: 000b
* - Shareable
* - Non-cacheable
* - Non-bufferable
*/
#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U)
/**
* MPU Memory Access Attribute for device memory.
* - TEX: 000b (if shareable) or 010b (if non-shareable)
* - Shareable or non-shareable
* - Non-cacheable
* - Bufferable (if shareable) or non-bufferable (if non-shareable)
*
* \param IsShareable Configures the device memory as shareable or non-shareable.
*/
#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U))
/**
* MPU Memory Access Attribute for normal memory.
* - TEX: 1BBb (reflecting outer cacheability rules)
* - Shareable or non-shareable
* - Cacheable or non-cacheable (reflecting inner cacheability rules)
* - Bufferable or non-bufferable (reflecting inner cacheability rules)
*
* \param OuterCp Configures the outer cache policy.
* \param InnerCp Configures the inner cache policy.
* \param IsShareable Configures the memory as shareable or non-shareable.
*/
#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) >> 1U), ((InnerCp) & 1U))
/**
* MPU Memory Access Attribute non-cacheable policy.
*/
#define ARM_MPU_CACHEP_NOCACHE 0U
/**
* MPU Memory Access Attribute write-back, write and read allocate policy.
*/
#define ARM_MPU_CACHEP_WB_WRA 1U
/**
* MPU Memory Access Attribute write-through, no write allocate policy.
*/
#define ARM_MPU_CACHEP_WT_NWA 2U
/**
* MPU Memory Access Attribute write-back, no write allocate policy.
*/
#define ARM_MPU_CACHEP_WB_NWA 3U
/**
* Struct for a single MPU Region
*/
typedef struct {
uint32_t RBAR; //!< The region base address register value (RBAR)
uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
} ARM_MPU_Region_t;
/** Enable the MPU.
* \param MPU_Control Default access permissions for unconfigured regions.
*/
__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
{
__DMB();
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
#endif
__DSB();
__ISB();
}
/** Disable the MPU.
*/
__STATIC_INLINE void ARM_MPU_Disable(void)
{
__DMB();
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
#endif
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
__DSB();
__ISB();
}
/** Clear and disable the given MPU region.
* \param rnr Region number to be cleared.
*/
__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
{
MPU->RNR = rnr;
MPU->RASR = 0U;
}
/** Configure an MPU region.
* \param rbar Value for RBAR register.
* \param rsar Value for RSAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
{
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Configure the given MPU region.
* \param rnr Region number to be configured.
* \param rbar Value for RBAR register.
* \param rsar Value for RSAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
{
MPU->RNR = rnr;
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Memcopy with strictly ordered memory access, e.g. for register targets.
* \param dst Destination data is copied to.
* \param src Source data is copied from.
* \param len Amount of data words to be copied.
*/
__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
{
uint32_t i;
for (i = 0U; i < len; ++i)
{
dst[i] = src[i];
}
}
/** Load the given number of MPU regions from a table.
* \param table Pointer to the MPU configuration table.
* \param cnt Amount of regions to be configured.
*/
__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
{
const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
while (cnt > MPU_TYPE_RALIASES) {
ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize);
table += MPU_TYPE_RALIASES;
cnt -= MPU_TYPE_RALIASES;
}
ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize);
}
#endif

75
lib/fast-hash/fasthash.c Normal file
View File

@@ -0,0 +1,75 @@
/* The MIT License
Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com)
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "fasthash.h"
// Compression function for Merkle-Damgard construction.
// This function is generated using the framework provided.
#define mix(h) ({ \
(h) ^= (h) >> 23; \
(h) *= 0x2127599bf4325c37ULL; \
(h) ^= (h) >> 47; })
uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
{
const uint64_t m = 0x880355f21e6d1965ULL;
const uint64_t *pos = (const uint64_t *)buf;
const uint64_t *end = pos + (len / 8);
const unsigned char *pos2;
uint64_t h = seed ^ (len * m);
uint64_t v;
while (pos != end) {
v = *pos++;
h ^= mix(v);
h *= m;
}
pos2 = (const unsigned char*)pos;
v = 0;
switch (len & 7) {
case 7: v ^= (uint64_t)pos2[6] << 48;
case 6: v ^= (uint64_t)pos2[5] << 40;
case 5: v ^= (uint64_t)pos2[4] << 32;
case 4: v ^= (uint64_t)pos2[3] << 24;
case 3: v ^= (uint64_t)pos2[2] << 16;
case 2: v ^= (uint64_t)pos2[1] << 8;
case 1: v ^= (uint64_t)pos2[0];
h ^= mix(v);
h *= m;
}
return mix(h);
}
uint32_t fasthash32(const void *buf, size_t len, uint32_t seed)
{
// the following trick converts the 64-bit hashcode to Fermat
// residue, which shall retain information from both the higher
// and lower parts of hashcode.
uint64_t h = fasthash64(buf, len, seed);
return h - (h >> 32);
}

56
lib/fast-hash/fasthash.h Normal file
View File

@@ -0,0 +1,56 @@
/* The MIT License
Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com)
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _FASTHASH_H
#define _FASTHASH_H
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* fasthash32 - 32-bit implementation of fasthash
* @buf: data buffer
* @len: data size
* @seed: the seed
*/
uint32_t fasthash32(const void *buf, size_t len, uint32_t seed);
/**
* fasthash64 - 64-bit implementation of fasthash
* @buf: data buffer
* @len: data size
* @seed: the seed
*/
uint64_t fasthash64(const void *buf, size_t len, uint64_t seed);
#ifdef __cplusplus
}
#endif
#endif

24
lib/fatfs/LICENSE.txt Normal file
View File

@@ -0,0 +1,24 @@
FatFs License
FatFs has being developped as a personal project of the author, ChaN. It is free from the code anyone else wrote at current release. Following code block shows a copy of the FatFs license document that heading the source files.
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem Module Rx.xx /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 20xx, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/----------------------------------------------------------------------------*/
Therefore FatFs license is one of the BSD-style licenses, but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, do not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most of open source software licenses include GNU GPL. When you redistribute the FatFs source code with changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software license that not conflict with FatFs license.

77
lib/fatfs/diskio.h Normal file
View File

@@ -0,0 +1,77 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2019 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

6874
lib/fatfs/ff.c Normal file

File diff suppressed because it is too large Load Diff

422
lib/fatfs/ff.h Normal file
View File

@@ -0,0 +1,422 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.14a /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2020, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/
/----------------------------------------------------------------------------*/
#ifndef FF_DEFINED
#define FF_DEFINED 80196 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "ffconf.h" /* FatFs configuration options */
#if FF_DEFINED != FFCONF_DEF
#error Wrong configuration file (ffconf.h).
#endif
/* Integer types used for FatFs API */
#if defined(_WIN32) /* Main development platform */
#define FF_INTDEF 2
#include <windows.h>
typedef unsigned __int64 QWORD;
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
#define FF_INTDEF 2
#include <stdint.h>
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
typedef unsigned char BYTE; /* char must be 8-bit */
typedef uint16_t WORD; /* 16-bit unsigned integer */
typedef uint32_t DWORD; /* 32-bit unsigned integer */
typedef uint64_t QWORD; /* 64-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#else /* Earlier than C99 */
#define FF_INTDEF 1
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
typedef unsigned char BYTE; /* char must be 8-bit */
typedef unsigned short WORD; /* 16-bit unsigned integer */
typedef unsigned long DWORD; /* 32-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#endif
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#endif
/* Type of path name strings on FatFs API */
#ifndef _INC_TCHAR
#define _INC_TCHAR
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8 ## x
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U ## x
#define _TEXT(x) U ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size and LBA variables */
#if FF_FS_EXFAT
#if FF_INTDEF != 2
#error exFAT feature wants C99 or later
#endif
typedef QWORD FSIZE_t;
#if FF_LBA64
typedef QWORD LBA_t;
#else
typedef DWORD LBA_t;
#endif
#else
#if FF_LBA64
#error exFAT needs to be enabled when enable 64-bit LBA
#endif
typedef DWORD FSIZE_t;
typedef DWORD LBA_t;
#endif
/* Filesystem object structure (FATFS) */
typedef struct {
BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE pdrv; /* Associated physical drive */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if FF_MAX_SS != FF_MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if FF_USE_LFN
WCHAR* lfnbuf; /* LFN working buffer */
#endif
#if FF_FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
#endif
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if FF_FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#if FF_FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
LBA_t volbase; /* Volume base sector */
LBA_t fatbase; /* FAT base sector */
LBA_t dirbase; /* Root directory base sector/cluster */
LBA_t database; /* Data base sector */
#if FF_FS_EXFAT
LBA_t bitbase; /* Allocation bitmap base sector */
#endif
LBA_t winsect; /* Current sector appearing in the win[] */
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* Object ID and allocation information (FFOBJID) */
typedef struct {
FATFS* fs; /* Pointer to the hosting volume of this object */
WORD id; /* Hosting volume mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if FF_FS_EXFAT
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */
#endif
#if FF_FS_LOCK
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} FFOBJID;
/* File object structure (FIL) */
typedef struct {
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */
#if !FF_FS_READONLY
LBA_t dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
#endif
#if FF_USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
FFOBJID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
LBA_t sect; /* Current sector (0:Read operation has terminated) */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if FF_USE_LFN
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if FF_USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[12 + 1]; /* File name */
#endif
} FILINFO;
/* Format parameter structure (MKFS_PARM) */
typedef struct {
BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
BYTE n_fat; /* Number of FATs */
UINT align; /* Data area alignment (sector) */
UINT n_root; /* Number of root directory entries */
DWORD au_size; /* Cluster size (byte) */
} MKFS_PARM;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp); /* Truncate the file */
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void* work); /* Divide a physical drive into some partitions */
FRESULT f_setcp (WORD cp); /* Set current code page */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime (void);
#endif
/* LFN support functions */
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
#endif
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
/* Sync functions */
#if FF_FS_REENTRANT
int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01
#define FA_WRITE 0x02
#define FA_OPEN_EXISTING 0x00
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA_OPEN_APPEND 0x30
/* Fast seek controls (2nd argument of f_lseek) */
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
/* Format options (2nd argument of f_mkfs) */
#define FM_FAT 0x01
#define FM_FAT32 0x02
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
#define FS_EXFAT 4
/* File attribute bits for directory entry (FILINFO.fattrib) */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#ifdef __cplusplus
}
#endif
#endif /* FF_DEFINED */

298
lib/fatfs/ffconf.h Normal file
View File

@@ -0,0 +1,298 @@
/*---------------------------------------------------------------------------/
/ FatFs Functional Configurations
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 80196 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define FF_FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: Basic functions are fully enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define FF_USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define FF_USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define FF_USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define FF_USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
#define FF_USE_LABEL 1
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define FF_USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define FF_CODE_PAGE 437
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect code page setting can cause a file open failure.
/
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
/ 0 - Include all code pages above and configured by f_setcp()
*/
#define FF_USE_LFN 0
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/ 0: Disable LFN. FF_MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
/ be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN
/ specification.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */
#define FF_LFN_UNICODE 0
/* This option switches the character encoding on the API when LFN is enabled.
/
/ 0: ANSI/OEM in current CP (TCHAR = char)
/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
/ 2: Unicode in UTF-8 (TCHAR = char)
/ 3: Unicode in UTF-32 (TCHAR = DWORD)
/
/ Also behavior of string I/O functions will be affected by this option.
/ When LFN is not enabled, this option has no effect. */
#define FF_LFN_BUF 255
#define FF_SFN_BUF 12
/* This set of options defines size of file name members in the FILINFO structure
/ which is used to read out directory items. These values should be suffcient for
/ the file names to read. The maximum possible length of the read file name depends
/ on character encoding. When LFN is not enabled, these options have no effect. */
#define FF_STRF_ENCODE 3
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
#define FF_FS_RPATH 0
/* This option configures support for relative path.
/
/ 0: Disable relative path and remove related functions.
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define FF_VOLUMES 1
/* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 0
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
/ not defined, a user defined volume string table needs to be defined as:
/
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
*/
#define FF_MULTI_PARTITION 0
/* This option switches support for multiple volumes on the physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When this function is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
#define FF_MIN_SS 512
#define FF_MAX_SS 512
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/ for variable sector size mode and disk_ioctl() function needs to implement
/ GET_SECTOR_SIZE command. */
#define FF_LBA64 0
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
#define FF_MIN_GPT 0x10000000
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
#define FF_USE_TRIM 0
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
#define FF_FS_EXFAT 0
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
#define FF_FS_NORTC 0
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2020
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
#define FF_FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
#define FF_FS_LOCK 0
/* The option FF_FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
/ is 1.
/
/ 0: Disable file lock function. To avoid volume corruption, application program
/ should avoid illegal open, remove and rename to the open objects.
/ >0: Enable file lock function. The value defines how many files/sub-directories
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
/* #include <somertos.h> // O/S definitions */
#define FF_FS_REENTRANT 0
#define FF_FS_TIMEOUT 1000
#define FF_SYNC_t HANDLE
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/*--- End of configuration options ---*/

170
lib/fatfs/ffsystem.c Normal file
View File

@@ -0,0 +1,170 @@
/*------------------------------------------------------------------------*/
/* Sample Code of OS Dependent Functions for FatFs */
/* (C)ChaN, 2018 */
/*------------------------------------------------------------------------*/
#include "ff.h"
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
)
{
free(mblock); /* Free the memory block with POSIX API */
}
#endif
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object for the volume, such as semaphore and mutex.
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
*/
//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
FF_SYNC_t* sobj /* Pointer to return the created sync object */
)
{
/* Win32 */
*sobj = CreateMutex(NULL, FALSE, NULL);
return (int)(*sobj != INVALID_HANDLE_VALUE);
/* uITRON */
// T_CSEM csem = {TA_TPRI,1,1};
// *sobj = acre_sem(&csem);
// return (int)(*sobj > 0);
/* uC/OS-II */
// OS_ERR err;
// *sobj = OSMutexCreate(0, &err);
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// *sobj = xSemaphoreCreateMutex();
// return (int)(*sobj != NULL);
/* CMSIS-RTOS */
// *sobj = osMutexCreate(&Mutex[vol]);
// return (int)(*sobj != NULL);
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */
FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
/* Win32 */
return (int)CloseHandle(sobj);
/* uITRON */
// return (int)(del_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// vSemaphoreDelete(sobj);
// return 1;
/* CMSIS-RTOS */
// return (int)(osMutexDelete(sobj) == osOK);
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
FF_SYNC_t sobj /* Sync object to wait */
)
{
/* Win32 */
return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
/* uITRON */
// return (int)(wai_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
/* CMSIS-RTOS */
// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
FF_SYNC_t sobj /* Sync object to be signaled */
)
{
/* Win32 */
ReleaseMutex(sobj);
/* uITRON */
// sig_sem(sobj);
/* uC/OS-II */
// OSMutexPost(sobj);
/* FreeRTOS */
// xSemaphoreGive(sobj);
/* CMSIS-RTOS */
// osMutexRelease(sobj);
}
#endif

15593
lib/fatfs/ffunicode.c Normal file

File diff suppressed because it is too large Load Diff

15
lib/hidflash/LICENSE Normal file
View File

@@ -0,0 +1,15 @@
* STM32 HID Bootloader - USB HID bootloader for STM32F10X
* Copyright (c) 2018 Bruno Freitas - bruno@brunofreitas.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.

48
lib/hidflash/Makefile Normal file
View File

@@ -0,0 +1,48 @@
CC=gcc
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.c
INCLUDE_DIRS=-I .
CHECK=1
ifeq ($(OS),Windows_NT)
SOURCES+=hid-win.c
SOURCES+=rs232.c
LIBS=-lsetupapi -lhid
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
SOURCES+=hid-mac.c
SOURCES+=rs232.c
LIBS=-framework IOKit -framework CoreFoundation
else
CHECK:=$(shell pkg-config --exists libusb-1.0 && echo 1)
SOURCES+=hid-libusb.c
SOURCES+=rs232.c
LIBS=`pkg-config libusb-1.0 --libs` -lrt -lpthread
INCLUDE_DIRS+=`pkg-config libusb-1.0 --cflags`
CFLAGS+=-std=gnu99
LDFLAGS+=-no-pie
endif
endif
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE = hid-flash
ifeq ($(CHECK), 1)
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $@
.c.o:
$(CC) $(CFLAGS) $(INCLUDE_DIRS) $< -o $@
else
all:
@echo " hid-flash requires libusb-1.0, please install with:"
@echo " sudo apt-get install libusb-1.0"
endif
clean:
rm -f $(OBJECTS) $(EXECUTABLE) $(EXECUTABLE).exe

34
lib/hidflash/README Normal file
View File

@@ -0,0 +1,34 @@
The source for the hid-flash program in this folder is a deriviative of the
"cli" modified by Vassilis Serasidis to work with the STM32 Arduino core,
available here:
https://github.com/Serasidis/STM32_HID_Bootloader/tree/master/cli
The original source for hid-flash was written by Bruno Freitas, available
here:
https://github.com/bootsector/stm32-hid-bootloader/tree/master/cli
This derivative contains the following changes:
1) The "port" argument is now optional. If not supplied hid-flash will not
attempt to open a serial port and enter the bootloader, it will assume
that the device has already entered the bootloader and look for a USB
device with the appropriate Vendor and Product IDs. This change allows
Klipper's "flash_usb.py" script to enter the bootloader and wait for the
mcu to reconnect.
2) When the serial port is specified, hid-flash will use Klipper's procedure
for entering the bootloader (Open the port at 1200 baud and toggle DTR).
3) The hid-flash program now accepts a command from the bootloader that allows
a STM32F103 device to identify itself as a "high-density" device during
the flashing process. This fixes a bug where the final page would not
be written if the last portion of the binary was less than or equal to
1024 bytes. A forked version of the bootloader is required to send the
"high-density" command, however the tool will still work correctly with
the original bootloader (sans the bug that affects high density devices).
4) A typo was fixed where an "if" statement was using an assignment operator
to test for equality.
5) The Makefile was changed to check for the libusb-1.0 dependency. If it
does not exist the user will be warned and the build aborted, however
no error will be generated. This allows Klipper's "make FLASH"
functionality to work when flashing via DFU without installing the
libusb-1.0 dependency for hid-flash.
- Eric Callahan <arksine.code@gmail.com>

305
lib/hidflash/changes.diff Normal file
View File

@@ -0,0 +1,305 @@
diff --git a/cli/Makefile b/cli/Makefile
index dee725e..d038615 100644
--- a/cli/Makefile
+++ b/cli/Makefile
@@ -3,6 +3,7 @@ CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.c
INCLUDE_DIRS=-I .
+CHECK=1
ifeq ($(OS),Windows_NT)
SOURCES+=hid-win.c
@@ -15,19 +16,21 @@ else
SOURCES+=rs232.c
LIBS=-framework IOKit -framework CoreFoundation
else
+ CHECK:=$(shell pkg-config --exists libusb-1.0 && echo 1)
SOURCES+=hid-libusb.c
SOURCES+=rs232.c
LIBS=`pkg-config libusb-1.0 --libs` -lrt -lpthread
INCLUDE_DIRS+=`pkg-config libusb-1.0 --cflags`
CFLAGS+=-std=gnu99
LDFLAGS+=-no-pie
- endif
+ endif
endif
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE = hid-flash
+ifeq ($(CHECK), 1)
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
@@ -35,6 +38,11 @@ $(EXECUTABLE): $(OBJECTS)
.c.o:
$(CC) $(CFLAGS) $(INCLUDE_DIRS) $< -o $@
+else
+all:
+ @echo " hid-flash requires libusb-1.0, please install with:"
+ @echo " sudo apt-get install libusb-1.0"
+endif
clean:
rm -f $(OBJECTS) $(EXECUTABLE) $(EXECUTABLE).exe
diff --git a/cli/main.c b/cli/main.c
index a6a8f7f..84abc33 100644
--- a/cli/main.c
+++ b/cli/main.c
@@ -19,6 +19,12 @@
* by Vassilis Serasidis <avrsite@yahoo.gr>
* This HID bootloader work with bluepill + STM32duino + Arduino IDE <http://www.stm32duino.com/>
*
+* Modified 4/24/2020
+* by Eric Callahan <arksine.code@gmail.com>
+* This version of hid-flash has been modified to work with Klipper.
+* The serial port argument is now optional. If entered and found this program
+* will attempt to force Klipper jump to the bootloader by connecting at
+* 1200 baud and enabling DTR.
*/
#include <stdlib.h>
@@ -37,6 +43,8 @@
#define PID 0xBEBA
#define FIRMWARE_VER 0x0300
+#define MAX_PAGE_SIZE 2048
+
int serial_init(char *argument, uint8_t __timer);
@@ -73,45 +81,48 @@ int main(int argc, char *argv[]) {
int i;
setbuf(stdout, NULL);
uint8_t _timer = 0;
-
+
printf("\n+-----------------------------------------------------------------------+\n");
printf ("| HID-Flash v2.2.1 - STM32 HID Bootloader Flash Tool |\n");
printf ("| (c) 2018 - Bruno Freitas http://www.brunofreitas.com |\n");
printf ("| (c) 2018-2019 - Vassilis Serasidis https://www.serasidis.gr |\n");
printf ("| Customized for STM32duino ecosystem https://www.stm32duino.com |\n");
printf ("+-----------------------------------------------------------------------+\n\n");
-
- if(argc < 3) {
- printf("Usage: hid-flash <bin_firmware_file> <comport> <delay (optional)>\n");
+
+ // TODO: This really needs an option parser
+ if(argc < 2) {
+ printf("Usage: hid-flash <bin_firmware_file> <comport (optional)> <delay (optional)>\n");
return 1;
}else if(argc == 4){
_timer = atol(argv[3]);
}
-
+
firmware_file = fopen(argv[1], "rb");
if(!firmware_file) {
printf("> Error opening firmware file: %s\n", argv[1]);
return error;
}
-
- if(serial_init(argv[2], _timer) == 0){ //Setting up Serial port
- RS232_CloseComport();
- }else{
- printf("> Unable to open the [%s]\n",argv[2]);
+
+ if (argc > 2) {
+ if(serial_init(argv[2], _timer) == 0){ //Setting up Serial port
+ RS232_CloseComport();
+ }else{
+ printf("> Unable to open the [%s]\n",argv[2]);
+ }
}
-
+
hid_init();
-
+
printf("> Searching for [%04X:%04X] device...\n",VID,PID);
-
+
struct hid_device_info *devs, *cur_dev;
uint8_t valid_hid_devices = 0;
-
+
for(i=0;i<10;i++){ //Try up to 10 times to open the HID device.
devs = hid_enumerate(VID, PID);
cur_dev = devs;
while (cur_dev) { //Search for valid HID Bootloader USB devices
- if((cur_dev->vendor_id == VID)&&(cur_dev->product_id = PID)){
+ if((cur_dev->vendor_id == VID)&&(cur_dev->product_id == PID)){
valid_hid_devices++;
if(cur_dev->release_number < FIRMWARE_VER){ //The STM32 board has firmware lower than 3.00
printf("\nError - Please update the firmware to the latest version (v3.00+)");
@@ -129,18 +140,18 @@ int main(int argc, char *argv[]) {
printf("\nError - [%04X:%04X] device is not found :(",VID,PID);
error = 1;
goto exit;
- }
-
+ }
+
handle = hid_open(VID, PID, NULL);
-
+
if (i == 10 && handle != NULL) {
printf("\n> Unable to open the [%04X:%04X] device.\n",VID,PID);
error = 1;
goto exit;
}
-
+
printf("\n> [%04X:%04X] device is found !\n",VID,PID);
-
+
// Send RESET PAGES command to put HID bootloader in initial stage...
memset(hid_tx_buf, 0, sizeof(hid_tx_buf)); //Fill the hid_tx_buf with zeros.
memcpy(&hid_tx_buf[1], CMD_RESET_PAGES, sizeof(CMD_RESET_PAGES));
@@ -161,7 +172,7 @@ int main(int argc, char *argv[]) {
memset(page_data, 0, sizeof(page_data));
read_bytes = fread(page_data, 1, sizeof(page_data), firmware_file);
- while(read_bytes > 0) {
+ while(1) {
for(int i = 0; i < SECTOR_SIZE; i += HID_TX_SIZE - 1) {
memcpy(&hid_tx_buf[1], page_data + i, HID_TX_SIZE - 1);
@@ -169,7 +180,7 @@ int main(int argc, char *argv[]) {
if((i % 1024) == 0){
printf(".");
}
-
+
// Flash is unavailable when writing to it, so USB interrupt may fail here
if(!usb_write(handle, hid_tx_buf, HID_TX_SIZE)) {
printf("> Error while flashing firmware data.\n");
@@ -179,20 +190,31 @@ int main(int argc, char *argv[]) {
n_bytes += (HID_TX_SIZE - 1);
usleep(500);
}
-
+
printf(" %d Bytes\n", n_bytes);
do{
hid_read(handle, hid_rx_buf, 9);
usleep(500);
- }while(hid_rx_buf[7] != 0x02);
-
+ // Exit the loop if we recieve 0x02 or 0x03
+ }while((hid_rx_buf[7] & 0xFE) != 0x02);
+
memset(page_data, 0, sizeof(page_data));
read_bytes = fread(page_data, 1, sizeof(page_data), firmware_file);
+
+ // For stm32f1 high density devices (2K page size) will receive a
+ // 0x03 command acknowledgement above. In that case, we must
+ // make sure that we send a full 2K so the last page is written.
+ // Note that this issue does not affect STM32F4 devices with larger
+ // page sizes.
+ if (read_bytes == 0) {
+ if (hid_rx_buf[7] != 0x03 || (n_bytes % MAX_PAGE_SIZE) == 0)
+ break;
+ }
}
printf("\n> Done!\n");
-
+
// Send CMD_REBOOT_MCU command to reboot the microcontroller...
memset(hid_tx_buf, 0, sizeof(hid_tx_buf));
memcpy(&hid_tx_buf[1], CMD_REBOOT_MCU, sizeof(CMD_REBOOT_MCU));
@@ -203,7 +225,7 @@ int main(int argc, char *argv[]) {
if(!usb_write(handle, hid_tx_buf, HID_TX_SIZE)) {
printf("> Error while sending <reboot mcu> command.\n");
}
-
+
exit:
if(handle) {
hid_close(handle);
@@ -214,22 +236,24 @@ exit:
if(firmware_file) {
fclose(firmware_file);
}
-
- printf("> Searching for [%s] ...\n",argv[2]);
- for(int i=0;i<5;i++){
- if(RS232_OpenComport(argv[2]) == 0){
- printf("> [%s] is found !\n",argv[2] );
- break;
+ if (argc > 2) {
+ printf("> Searching for [%s] ...\n",argv[2]);
+
+ for(int i=0;i<5;i++){
+ if(RS232_OpenComport(argv[2]) == 0){
+ printf("> [%s] is found !\n",argv[2] );
+ break;
+ }
+ sleep(1);
+ }
+
+ if(i==5){
+ printf("> Comport is not found\n");
}
- sleep(1);
- }
-
- if(i==5){
- printf("> Comport is not found\n");
}
printf("> Finish\n");
-
+
return error;
}
@@ -240,20 +264,14 @@ int serial_init(char *argument, uint8_t __timer) {
return(1);
}
printf("> Toggling DTR...\n");
-
+
RS232_disableRTS();
- RS232_enableDTR();
- usleep(200000L);
RS232_disableDTR();
usleep(200000L);
RS232_enableDTR();
usleep(200000L);
- RS232_disableDTR();
- usleep(200000L);
- RS232_send_magic();
- usleep(200000L);
RS232_CloseComport();
-
+
//printf("A %i\n",__timer);
if (__timer > 0) {
usleep(__timer);
diff --git a/cli/rs232.c b/cli/rs232.c
index 067ef1a..ce7de08 100644
--- a/cli/rs232.c
+++ b/cli/rs232.c
@@ -80,12 +80,12 @@
new_termios.c_cc[VEOL2] = 0;
- if (cfsetispeed(&new_termios, B9600) != 0) {
- fprintf(stderr, "cfsetispeed(&new_termios, B9600) failed: %s\n", strerror(errno));
+ if (cfsetispeed(&new_termios, B1200) != 0) {
+ fprintf(stderr, "cfsetispeed(&new_termios, B1200) failed: %s\n", strerror(errno));
return 1;
}
- if (cfsetospeed(&new_termios, B9600) != 0) {
- fprintf(stderr, "cfsetospeed(&new_termios, B9600) failed: %s\n", strerror(errno));
+ if (cfsetospeed(&new_termios, B1200) != 0) {
+ fprintf(stderr, "cfsetospeed(&new_termios, B1200) failed: %s\n", strerror(errno));
return 1;
}

1514
lib/hidflash/hid-libusb.c Normal file

File diff suppressed because it is too large Load Diff

1110
lib/hidflash/hid-mac.c Normal file

File diff suppressed because it is too large Load Diff

944
lib/hidflash/hid-win.c Normal file
View File

@@ -0,0 +1,944 @@
/*******************************************************
HIDAPI - Multi-Platform library for
communication with HID devices.
Alan Ott
Signal 11 Software
8/22/2009
Copyright 2009, All Rights Reserved.
At the discretion of the user of this library,
this software may be licensed under the terms of the
GNU General Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution.
These files may also be found in the public source
code repository located at:
http://github.com/signal11/hidapi .
********************************************************/
#include <windows.h>
#ifndef _NTDEF_
typedef LONG NTSTATUS;
#endif
#ifdef __MINGW32__
#include <ntdef.h>
#include <winbase.h>
#endif
#ifdef __CYGWIN__
#include <ntdef.h>
#define _wcsdup wcsdup
#endif
/* The maximum number of characters that can be passed into the
HidD_Get*String() functions without it failing.*/
#define MAX_STRING_WCHARS 0xFFF
/*#define HIDAPI_USE_DDK*/
#ifdef __cplusplus
extern "C" {
#endif
#include <setupapi.h>
#include <winioctl.h>
#ifdef HIDAPI_USE_DDK
#include <hidsdi.h>
#endif
/* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */
#define HID_OUT_CTL_CODE(id) \
CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
#ifdef __cplusplus
} /* extern "C" */
#endif
#include <stdio.h>
#include <stdlib.h>
#include "hidapi.h"
#undef MIN
#define MIN(x,y) ((x) < (y)? (x): (y))
#ifdef _MSC_VER
/* Thanks Microsoft, but I know how to use strncpy(). */
#pragma warning(disable:4996)
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef HIDAPI_USE_DDK
/* Since we're not building with the DDK, and the HID header
files aren't part of the SDK, we have to define all this
stuff here. In lookup_functions(), the function pointers
defined below are set. */
typedef struct _HIDD_ATTRIBUTES{
ULONG Size;
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
typedef USHORT USAGE;
typedef struct _HIDP_CAPS {
USAGE Usage;
USAGE UsagePage;
USHORT InputReportByteLength;
USHORT OutputReportByteLength;
USHORT FeatureReportByteLength;
USHORT Reserved[17];
USHORT fields_not_used_by_hidapi[10];
} HIDP_CAPS, *PHIDP_CAPS;
typedef void* PHIDP_PREPARSED_DATA;
#define HIDP_STATUS_SUCCESS 0x110000
typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib);
typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len);
typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length);
typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length);
typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len);
typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);
typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps);
typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers);
static HidD_GetAttributes_ HidD_GetAttributes;
static HidD_GetSerialNumberString_ HidD_GetSerialNumberString;
static HidD_GetManufacturerString_ HidD_GetManufacturerString;
static HidD_GetProductString_ HidD_GetProductString;
static HidD_SetFeature_ HidD_SetFeature;
static HidD_GetFeature_ HidD_GetFeature;
static HidD_GetIndexedString_ HidD_GetIndexedString;
static HidD_GetPreparsedData_ HidD_GetPreparsedData;
static HidD_FreePreparsedData_ HidD_FreePreparsedData;
static HidP_GetCaps_ HidP_GetCaps;
static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers;
static HMODULE lib_handle = NULL;
static BOOLEAN initialized = FALSE;
#endif /* HIDAPI_USE_DDK */
struct hid_device_ {
HANDLE device_handle;
BOOL blocking;
USHORT output_report_length;
size_t input_report_length;
void *last_error_str;
DWORD last_error_num;
BOOL read_pending;
char *read_buf;
OVERLAPPED ol;
};
static hid_device *new_hid_device()
{
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
dev->device_handle = INVALID_HANDLE_VALUE;
dev->blocking = TRUE;
dev->output_report_length = 0;
dev->input_report_length = 0;
dev->last_error_str = NULL;
dev->last_error_num = 0;
dev->read_pending = FALSE;
dev->read_buf = NULL;
memset(&dev->ol, 0, sizeof(dev->ol));
dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
return dev;
}
static void free_hid_device(hid_device *dev)
{
CloseHandle(dev->ol.hEvent);
CloseHandle(dev->device_handle);
LocalFree(dev->last_error_str);
free(dev->read_buf);
free(dev);
}
static void register_error(hid_device *device, const char *op)
{
WCHAR *ptr, *msg;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPVOID)&msg, 0/*sz*/,
NULL);
/* Get rid of the CR and LF that FormatMessage() sticks at the
end of the message. Thanks Microsoft! */
ptr = msg;
while (*ptr) {
if (*ptr == '\r') {
*ptr = 0x0000;
break;
}
ptr++;
}
/* Store the message off in the Device entry so that
the hid_error() function can pick it up. */
LocalFree(device->last_error_str);
device->last_error_str = msg;
}
#ifndef HIDAPI_USE_DDK
static int lookup_functions()
{
lib_handle = LoadLibraryA("hid.dll");
if (lib_handle) {
#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1;
RESOLVE(HidD_GetAttributes);
RESOLVE(HidD_GetSerialNumberString);
RESOLVE(HidD_GetManufacturerString);
RESOLVE(HidD_GetProductString);
RESOLVE(HidD_SetFeature);
RESOLVE(HidD_GetFeature);
RESOLVE(HidD_GetIndexedString);
RESOLVE(HidD_GetPreparsedData);
RESOLVE(HidD_FreePreparsedData);
RESOLVE(HidP_GetCaps);
RESOLVE(HidD_SetNumInputBuffers);
#undef RESOLVE
}
else
return -1;
return 0;
}
#endif
static HANDLE open_device(const char *path, BOOL enumerate)
{
HANDLE handle;
DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ);
DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
handle = CreateFileA(path,
desired_access,
share_mode,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/
0);
return handle;
}
int HID_API_EXPORT hid_init(void)
{
#ifndef HIDAPI_USE_DDK
if (!initialized) {
if (lookup_functions() < 0) {
hid_exit();
return -1;
}
initialized = TRUE;
}
#endif
return 0;
}
int HID_API_EXPORT hid_exit(void)
{
#ifndef HIDAPI_USE_DDK
if (lib_handle)
FreeLibrary(lib_handle);
lib_handle = NULL;
initialized = FALSE;
#endif
return 0;
}
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
BOOL res;
struct hid_device_info *root = NULL; /* return object */
struct hid_device_info *cur_dev = NULL;
/* Windows objects for interacting with the driver. */
GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} };
SP_DEVINFO_DATA devinfo_data;
SP_DEVICE_INTERFACE_DATA device_interface_data;
SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL;
HDEVINFO device_info_set = INVALID_HANDLE_VALUE;
int device_index = 0;
int i;
if (hid_init() < 0)
return NULL;
/* Initialize the Windows objects. */
memset(&devinfo_data, 0x0, sizeof(devinfo_data));
devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
/* Get information for all the devices belonging to the HID class. */
device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
/* Iterate over each device in the HID class, looking for the right one. */
for (;;) {
HANDLE write_handle = INVALID_HANDLE_VALUE;
DWORD required_size = 0;
HIDD_ATTRIBUTES attrib;
res = SetupDiEnumDeviceInterfaces(device_info_set,
NULL,
&InterfaceClassGuid,
device_index,
&device_interface_data);
if (!res) {
/* A return of FALSE from this function means that
there are no more devices. */
break;
}
/* Call with 0-sized detail size, and let the function
tell us how long the detail struct needs to be. The
size is put in &required_size. */
res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
&device_interface_data,
NULL,
0,
&required_size,
NULL);
/* Allocate a long enough structure for device_interface_detail_data. */
device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size);
device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
/* Get the detailed data for this device. The detail data gives us
the device path for this device, which is then passed into
CreateFile() to get a handle to the device. */
res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
&device_interface_data,
device_interface_detail_data,
required_size,
NULL,
NULL);
if (!res) {
/* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail");
Continue to the next device. */
goto cont;
}
/* Make sure this device is of Setup Class "HIDClass" and has a
driver bound to it. */
for (i = 0; ; i++) {
char driver_name[256];
/* Populate devinfo_data. This function will return failure
when there are no more interfaces left. */
res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data);
if (!res)
goto cont;
res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
if (!res)
goto cont;
if (strcmp(driver_name, "HIDClass") == 0) {
/* See if there's a driver bound. */
res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
if (res)
break;
}
}
//wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath);
/* Open a handle to the device */
write_handle = open_device(device_interface_detail_data->DevicePath, TRUE);
/* Check validity of write_handle. */
if (write_handle == INVALID_HANDLE_VALUE) {
/* Unable to open the device. */
//register_error(dev, "CreateFile");
goto cont_close;
}
/* Get the Vendor ID and Product ID for this device. */
attrib.Size = sizeof(HIDD_ATTRIBUTES);
HidD_GetAttributes(write_handle, &attrib);
//wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID);
/* Check the VID/PID to see if we should add this
device to the enumeration list. */
if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) &&
(product_id == 0x0 || attrib.ProductID == product_id)) {
#define WSTR_LEN 512
const char *str;
struct hid_device_info *tmp;
PHIDP_PREPARSED_DATA pp_data = NULL;
HIDP_CAPS caps;
BOOLEAN res;
NTSTATUS nt_res;
wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */
size_t len;
/* VID/PID match. Create the record. */
tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
if (cur_dev) {
cur_dev->next = tmp;
}
else {
root = tmp;
}
cur_dev = tmp;
/* Get the Usage Page and Usage for this device. */
res = HidD_GetPreparsedData(write_handle, &pp_data);
if (res) {
nt_res = HidP_GetCaps(pp_data, &caps);
if (nt_res == HIDP_STATUS_SUCCESS) {
cur_dev->usage_page = caps.UsagePage;
cur_dev->usage = caps.Usage;
}
HidD_FreePreparsedData(pp_data);
}
/* Fill out the record */
cur_dev->next = NULL;
str = device_interface_detail_data->DevicePath;
if (str) {
len = strlen(str);
cur_dev->path = (char*) calloc(len+1, sizeof(char));
strncpy(cur_dev->path, str, len+1);
cur_dev->path[len] = '\0';
}
else
cur_dev->path = NULL;
/* Serial Number */
res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr));
wstr[WSTR_LEN-1] = 0x0000;
if (res) {
cur_dev->serial_number = _wcsdup(wstr);
}
/* Manufacturer String */
res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr));
wstr[WSTR_LEN-1] = 0x0000;
if (res) {
cur_dev->manufacturer_string = _wcsdup(wstr);
}
/* Product String */
res = HidD_GetProductString(write_handle, wstr, sizeof(wstr));
wstr[WSTR_LEN-1] = 0x0000;
if (res) {
cur_dev->product_string = _wcsdup(wstr);
}
/* VID/PID */
cur_dev->vendor_id = attrib.VendorID;
cur_dev->product_id = attrib.ProductID;
/* Release Number */
cur_dev->release_number = attrib.VersionNumber;
/* Interface Number. It can sometimes be parsed out of the path
on Windows if a device has multiple interfaces. See
http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or
search for "Hardware IDs for HID Devices" at MSDN. If it's not
in the path, it's set to -1. */
cur_dev->interface_number = -1;
if (cur_dev->path) {
char *interface_component = strstr(cur_dev->path, "&mi_");
if (interface_component) {
char *hex_str = interface_component + 4;
char *endptr = NULL;
cur_dev->interface_number = strtol(hex_str, &endptr, 16);
if (endptr == hex_str) {
/* The parsing failed. Set interface_number to -1. */
cur_dev->interface_number = -1;
}
}
}
}
cont_close:
CloseHandle(write_handle);
cont:
/* We no longer need the detail data. It can be freed */
free(device_interface_detail_data);
device_index++;
}
/* Close the device information handle. */
SetupDiDestroyDeviceInfoList(device_info_set);
return root;
}
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
{
/* TODO: Merge this with the Linux version. This function is platform-independent. */
struct hid_device_info *d = devs;
while (d) {
struct hid_device_info *next = d->next;
free(d->path);
free(d->serial_number);
free(d->manufacturer_string);
free(d->product_string);
free(d);
d = next;
}
}
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
{
/* TODO: Merge this functions with the Linux version. This function should be platform independent. */
struct hid_device_info *devs, *cur_dev;
const char *path_to_open = NULL;
hid_device *handle = NULL;
devs = hid_enumerate(vendor_id, product_id);
cur_dev = devs;
while (cur_dev) {
if (cur_dev->vendor_id == vendor_id &&
cur_dev->product_id == product_id) {
if (serial_number) {
if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
path_to_open = cur_dev->path;
break;
}
}
else {
path_to_open = cur_dev->path;
break;
}
}
cur_dev = cur_dev->next;
}
if (path_to_open) {
/* Open the device */
handle = hid_open_path(path_to_open);
}
hid_free_enumeration(devs);
return handle;
}
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
{
hid_device *dev;
HIDP_CAPS caps;
PHIDP_PREPARSED_DATA pp_data = NULL;
BOOLEAN res;
NTSTATUS nt_res;
if (hid_init() < 0) {
return NULL;
}
dev = new_hid_device();
/* Open a handle to the device */
dev->device_handle = open_device(path, FALSE);
/* Check validity of write_handle. */
if (dev->device_handle == INVALID_HANDLE_VALUE) {
/* Unable to open the device. */
register_error(dev, "CreateFile");
goto err;
}
/* Set the Input Report buffer size to 64 reports. */
res = HidD_SetNumInputBuffers(dev->device_handle, 64);
if (!res) {
register_error(dev, "HidD_SetNumInputBuffers");
goto err;
}
/* Get the Input Report length for the device. */
res = HidD_GetPreparsedData(dev->device_handle, &pp_data);
if (!res) {
register_error(dev, "HidD_GetPreparsedData");
goto err;
}
nt_res = HidP_GetCaps(pp_data, &caps);
if (nt_res != HIDP_STATUS_SUCCESS) {
register_error(dev, "HidP_GetCaps");
goto err_pp_data;
}
dev->output_report_length = caps.OutputReportByteLength;
dev->input_report_length = caps.InputReportByteLength;
HidD_FreePreparsedData(pp_data);
dev->read_buf = (char*) malloc(dev->input_report_length);
return dev;
err_pp_data:
HidD_FreePreparsedData(pp_data);
err:
free_hid_device(dev);
return NULL;
}
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
{
DWORD bytes_written;
BOOL res;
OVERLAPPED ol;
unsigned char *buf;
memset(&ol, 0, sizeof(ol));
/* Make sure the right number of bytes are passed to WriteFile. Windows
expects the number of bytes which are in the _longest_ report (plus
one for the report number) bytes even if the data is a report
which is shorter than that. Windows gives us this value in
caps.OutputReportByteLength. If a user passes in fewer bytes than this,
create a temporary buffer which is the proper size. */
if (length >= dev->output_report_length) {
/* The user passed the right number of bytes. Use the buffer as-is. */
buf = (unsigned char *) data;
} else {
/* Create a temporary buffer and copy the user's data
into it, padding the rest with zeros. */
buf = (unsigned char *) malloc(dev->output_report_length);
memcpy(buf, data, length);
memset(buf + length, 0, dev->output_report_length - length);
length = dev->output_report_length;
}
res = WriteFile(dev->device_handle, buf, length, NULL, &ol);
if (!res) {
if (GetLastError() != ERROR_IO_PENDING) {
/* WriteFile() failed. Return error. */
register_error(dev, "WriteFile");
bytes_written = -1;
goto end_of_function;
}
}
/* Wait here until the write is done. This makes
hid_write() synchronous. */
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/);
if (!res) {
/* The Write operation failed. */
register_error(dev, "WriteFile");
bytes_written = -1;
goto end_of_function;
}
end_of_function:
if (buf != data)
free(buf);
return bytes_written;
}
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
{
DWORD bytes_read = 0;
size_t copy_len = 0;
BOOL res;
/* Copy the handle for convenience. */
HANDLE ev = dev->ol.hEvent;
if (!dev->read_pending) {
/* Start an Overlapped I/O read. */
dev->read_pending = TRUE;
memset(dev->read_buf, 0, dev->input_report_length);
ResetEvent(ev);
res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol);
if (!res) {
if (GetLastError() != ERROR_IO_PENDING) {
/* ReadFile() has failed.
Clean up and return error. */
CancelIo(dev->device_handle);
dev->read_pending = FALSE;
goto end_of_function;
}
}
}
if (milliseconds >= 0) {
/* See if there is any data yet. */
res = WaitForSingleObject(ev, milliseconds);
if (res != WAIT_OBJECT_0) {
/* There was no data this time. Return zero bytes available,
but leave the Overlapped I/O running. */
return 0;
}
}
/* Either WaitForSingleObject() told us that ReadFile has completed, or
we are in non-blocking mode. Get the number of bytes read. The actual
data has been copied to the data[] array which was passed to ReadFile(). */
res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/);
/* Set pending back to false, even if GetOverlappedResult() returned error. */
dev->read_pending = FALSE;
if (res && bytes_read > 0) {
if (dev->read_buf[0] == 0x0) {
/* If report numbers aren't being used, but Windows sticks a report
number (0x0) on the beginning of the report anyway. To make this
work like the other platforms, and to make it work more like the
HID spec, we'll skip over this byte. */
bytes_read--;
copy_len = length > bytes_read ? bytes_read : length;
memcpy(data, dev->read_buf+1, copy_len);
}
else {
/* Copy the whole buffer, report number and all. */
copy_len = length > bytes_read ? bytes_read : length;
memcpy(data, dev->read_buf, copy_len);
}
}
end_of_function:
if (!res) {
register_error(dev, "GetOverlappedResult");
return -1;
}
return copy_len;
}
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length)
{
return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
}
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock)
{
dev->blocking = !nonblock;
return 0; /* Success */
}
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
{
BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, length);
if (!res) {
register_error(dev, "HidD_SetFeature");
return -1;
}
return length;
}
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
{
BOOL res;
#if 0
res = HidD_GetFeature(dev->device_handle, data, length);
if (!res) {
register_error(dev, "HidD_GetFeature");
return -1;
}
return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */
#else
DWORD bytes_returned;
OVERLAPPED ol;
memset(&ol, 0, sizeof(ol));
res = DeviceIoControl(dev->device_handle,
IOCTL_HID_GET_FEATURE,
data, length,
data, length,
&bytes_returned, &ol);
if (!res) {
if (GetLastError() != ERROR_IO_PENDING) {
/* DeviceIoControl() failed. Return error. */
register_error(dev, "Send Feature Report DeviceIoControl");
return -1;
}
}
/* Wait here until the write is done. This makes
hid_get_feature_report() synchronous. */
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
if (!res) {
/* The operation failed. */
register_error(dev, "Send Feature Report GetOverLappedResult");
return -1;
}
/* bytes_returned does not include the first byte which contains the
report ID. The data buffer actually contains one more byte than
bytes_returned. */
bytes_returned++;
return bytes_returned;
#endif
}
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
{
if (!dev)
return;
CancelIo(dev->device_handle);
free_hid_device(dev);
}
int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
{
BOOL res;
res = HidD_GetManufacturerString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS));
if (!res) {
register_error(dev, "HidD_GetManufacturerString");
return -1;
}
return 0;
}
int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
{
BOOL res;
res = HidD_GetProductString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS));
if (!res) {
register_error(dev, "HidD_GetProductString");
return -1;
}
return 0;
}
int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
{
BOOL res;
res = HidD_GetSerialNumberString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS));
if (!res) {
register_error(dev, "HidD_GetSerialNumberString");
return -1;
}
return 0;
}
int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
{
BOOL res;
res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS));
if (!res) {
register_error(dev, "HidD_GetIndexedString");
return -1;
}
return 0;
}
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
{
return (wchar_t*)dev->last_error_str;
}
/*#define PICPGM*/
/*#define S11*/
#define P32
#ifdef S11
unsigned short VendorID = 0xa0a0;
unsigned short ProductID = 0x0001;
#endif
#ifdef P32
unsigned short VendorID = 0x04d8;
unsigned short ProductID = 0x3f;
#endif
#ifdef PICPGM
unsigned short VendorID = 0x04d8;
unsigned short ProductID = 0x0033;
#endif
#if 0
int __cdecl main(int argc, char* argv[])
{
int res;
unsigned char buf[65];
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
/* Set up the command buffer. */
memset(buf,0x00,sizeof(buf));
buf[0] = 0;
buf[1] = 0x81;
/* Open the device. */
int handle = open(VendorID, ProductID, L"12345");
if (handle < 0)
printf("> unable to open device\n");
/* Toggle LED (cmd 0x80) */
buf[1] = 0x80;
res = write(handle, buf, 65);
if (res < 0)
printf("> Unable to write()\n");
/* Request state (cmd 0x81) */
buf[1] = 0x81;
write(handle, buf, 65);
if (res < 0)
printf("> Unable to write() (2)\n");
/* Read requested state */
read(handle, buf, 65);
if (res < 0)
printf("> Unable to read()\n");
/* Print out the returned buffer. */
for (int i = 0; i < 4; i++)
printf("> buf[%d]: %d\n", i, buf[i]);
return 0;
}
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif

391
lib/hidflash/hidapi.h Normal file
View File

@@ -0,0 +1,391 @@
/*******************************************************
HIDAPI - Multi-Platform library for
communication with HID devices.
Alan Ott
Signal 11 Software
8/22/2009
Copyright 2009, All Rights Reserved.
At the discretion of the user of this library,
this software may be licensed under the terms of the
GNU General Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution.
These files may also be found in the public source
code repository located at:
http://github.com/signal11/hidapi .
********************************************************/
/** @file
* @defgroup API hidapi API
*/
#ifndef HIDAPI_H__
#define HIDAPI_H__
#include <wchar.h>
#ifdef _WIN32
#define HID_API_EXPORT __declspec(dllexport)
#define HID_API_CALL
#else
#define HID_API_EXPORT /**< API export macro */
#define HID_API_CALL /**< API call macro */
#endif
#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
#ifdef __cplusplus
extern "C" {
#endif
struct hid_device_;
typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
/** hidapi info structure */
struct hid_device_info {
/** Platform-specific device path */
char *path;
/** Device Vendor ID */
unsigned short vendor_id;
/** Device Product ID */
unsigned short product_id;
/** Serial Number */
wchar_t *serial_number;
/** Device Release Number in binary-coded decimal,
also known as Device Version Number */
unsigned short release_number;
/** Manufacturer String */
wchar_t *manufacturer_string;
/** Product string */
wchar_t *product_string;
/** Usage Page for this Device/Interface
(Windows/Mac only). */
unsigned short usage_page;
/** Usage for this Device/Interface
(Windows/Mac only).*/
unsigned short usage;
/** The USB interface which this logical device
represents. Valid on both Linux implementations
in all cases, and valid on the Windows implementation
only if the device contains more than one interface. */
int interface_number;
/** Pointer to the next device */
struct hid_device_info *next;
};
/** @brief Initialize the HIDAPI library.
This function initializes the HIDAPI library. Calling it is not
strictly necessary, as it will be called automatically by
hid_enumerate() and any of the hid_open_*() functions if it is
needed. This function should be called at the beginning of
execution however, if there is a chance of HIDAPI handles
being opened by different threads simultaneously.
@ingroup API
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_init(void);
/** @brief Finalize the HIDAPI library.
This function frees all of the static data associated with
HIDAPI. It should be called at the end of execution to avoid
memory leaks.
@ingroup API
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_exit(void);
/** @brief Enumerate the HID Devices.
This function returns a linked list of all the HID devices
attached to the system which match vendor_id and product_id.
If @p vendor_id is set to 0 then any vendor matches.
If @p product_id is set to 0 then any product matches.
If @p vendor_id and @p product_id are both set to 0, then
all HID devices will be returned.
@ingroup API
@param vendor_id The Vendor ID (VID) of the types of device
to open.
@param product_id The Product ID (PID) of the types of
device to open.
@returns
This function returns a pointer to a linked list of type
struct #hid_device, containing information about the HID devices
attached to the system, or NULL in the case of failure. Free
this linked list by calling hid_free_enumeration().
*/
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
/** @brief Free an enumeration Linked List
This function frees a linked list created by hid_enumerate().
@ingroup API
@param devs Pointer to a list of struct_device returned from
hid_enumerate().
*/
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
/** @brief Open a HID device using a Vendor ID (VID), Product ID
(PID) and optionally a serial number.
If @p serial_number is NULL, the first device with the
specified VID and PID is opened.
@ingroup API
@param vendor_id The Vendor ID (VID) of the device to open.
@param product_id The Product ID (PID) of the device to open.
@param serial_number The Serial Number of the device to open
(Optionally NULL).
@returns
This function returns a pointer to a #hid_device object on
success or NULL on failure.
*/
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
/** @brief Open a HID device by its path name.
The path name be determined by calling hid_enumerate(), or a
platform-specific path name can be used (eg: /dev/hidraw0 on
Linux).
@ingroup API
@param path The path name of the device to open
@returns
This function returns a pointer to a #hid_device object on
success or NULL on failure.
*/
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
/** @brief Write an Output report to a HID device.
The first byte of @p data[] must contain the Report ID. For
devices which only support a single report, this must be set
to 0x0. The remaining bytes contain the report data. Since
the Report ID is mandatory, calls to hid_write() will always
contain one more byte than the report contains. For example,
if a hid report is 16 bytes long, 17 bytes must be passed to
hid_write(), the Report ID (or 0x0, for devices with a
single report), followed by the report data (16 bytes). In
this example, the length passed in would be 17.
hid_write() will send the data on the first OUT endpoint, if
one exists. If it does not, it will send the data through
the Control Endpoint (Endpoint 0).
@ingroup API
@param device A device handle returned from hid_open().
@param data The data to send, including the report number as
the first byte.
@param length The length in bytes of the data to send.
@returns
This function returns the actual number of bytes written and
-1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
/** @brief Read an Input report from a HID device with timeout.
Input reports are returned
to the host through the INTERRUPT IN endpoint. The first byte will
contain the Report number if the device uses numbered reports.
@ingroup API
@param device A device handle returned from hid_open().
@param data A buffer to put the read data into.
@param length The number of bytes to read. For devices with
multiple reports, make sure to read an extra byte for
the report number.
@param milliseconds timeout in milliseconds or -1 for blocking wait.
@returns
This function returns the actual number of bytes read and
-1 on error. If no packet was available to be read within
the timeout period, this function returns 0.
*/
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
/** @brief Read an Input report from a HID device.
Input reports are returned
to the host through the INTERRUPT IN endpoint. The first byte will
contain the Report number if the device uses numbered reports.
@ingroup API
@param device A device handle returned from hid_open().
@param data A buffer to put the read data into.
@param length The number of bytes to read. For devices with
multiple reports, make sure to read an extra byte for
the report number.
@returns
This function returns the actual number of bytes read and
-1 on error. If no packet was available to be read and
the handle is in non-blocking mode, this function returns 0.
*/
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
/** @brief Set the device handle to be non-blocking.
In non-blocking mode calls to hid_read() will return
immediately with a value of 0 if there is no data to be
read. In blocking mode, hid_read() will wait (block) until
there is data to read before returning.
Nonblocking can be turned on and off at any time.
@ingroup API
@param device A device handle returned from hid_open().
@param nonblock enable or not the nonblocking reads
- 1 to enable nonblocking
- 0 to disable nonblocking.
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock);
/** @brief Send a Feature report to the device.
Feature reports are sent over the Control endpoint as a
Set_Report transfer. The first byte of @p data[] must
contain the Report ID. For devices which only support a
single report, this must be set to 0x0. The remaining bytes
contain the report data. Since the Report ID is mandatory,
calls to hid_send_feature_report() will always contain one
more byte than the report contains. For example, if a hid
report is 16 bytes long, 17 bytes must be passed to
hid_send_feature_report(): the Report ID (or 0x0, for
devices which do not use numbered reports), followed by the
report data (16 bytes). In this example, the length passed
in would be 17.
@ingroup API
@param device A device handle returned from hid_open().
@param data The data to send, including the report number as
the first byte.
@param length The length in bytes of the data to send, including
the report number.
@returns
This function returns the actual number of bytes written and
-1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length);
/** @brief Get a feature report from a HID device.
Set the first byte of @p data[] to the Report ID of the
report to be read. Make sure to allow space for this
extra byte in @p data[]. Upon return, the first byte will
still contain the Report ID, and the report data will
start in data[1].
@ingroup API
@param device A device handle returned from hid_open().
@param data A buffer to put the read data into, including
the Report ID. Set the first byte of @p data[] to the
Report ID of the report to be read, or set it to zero
if your device does not use numbered reports.
@param length The number of bytes to read, including an
extra byte for the report ID. The buffer can be longer
than the actual report.
@returns
This function returns the number of bytes read plus
one for the report ID (which is still in the first
byte), or -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);
/** @brief Close a HID device.
@ingroup API
@param device A device handle returned from hid_open().
*/
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device);
/** @brief Get The Manufacturer String from a HID device.
@ingroup API
@param device A device handle returned from hid_open().
@param string A wide string buffer to put the data into.
@param maxlen The length of the buffer in multiples of wchar_t.
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen);
/** @brief Get The Product String from a HID device.
@ingroup API
@param device A device handle returned from hid_open().
@param string A wide string buffer to put the data into.
@param maxlen The length of the buffer in multiples of wchar_t.
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen);
/** @brief Get The Serial Number String from a HID device.
@ingroup API
@param device A device handle returned from hid_open().
@param string A wide string buffer to put the data into.
@param maxlen The length of the buffer in multiples of wchar_t.
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen);
/** @brief Get a string from a HID device, based on its string index.
@ingroup API
@param device A device handle returned from hid_open().
@param string_index The index of the string to get.
@param string A wide string buffer to put the data into.
@param maxlen The length of the buffer in multiples of wchar_t.
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
/** @brief Get a string describing the last error which occurred.
@ingroup API
@param device A device handle returned from hid_open().
@returns
This function returns a string containing the last error
which occurred or NULL if none has occurred.
*/
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device);
#ifdef __cplusplus
}
#endif
#endif

280
lib/hidflash/main.c Normal file
View File

@@ -0,0 +1,280 @@
/*
* STM32 HID Bootloader - USB HID bootloader for STM32F10X
* Copyright (c) 2018 Bruno Freitas - bruno@brunofreitas.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*
* Modified 20 April 2018
* by Vassilis Serasidis <avrsite@yahoo.gr>
* This HID bootloader work with bluepill + STM32duino + Arduino IDE <http://www.stm32duino.com/>
*
* Modified 4/24/2020
* by Eric Callahan <arksine.code@gmail.com>
* This version of hid-flash has been modified to work with Klipper.
* The serial port argument is now optional. If entered and found this program
* will attempt to force Klipper jump to the bootloader by connecting at
* 1200 baud and enabling DTR.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include "rs232.h"
#include "hidapi.h"
#define SECTOR_SIZE 1024
#define HID_TX_SIZE 65
#define HID_RX_SIZE 9
#define VID 0x1209
#define PID 0xBEBA
#define FIRMWARE_VER 0x0300
#define MAX_PAGE_SIZE 2048
int serial_init(char *argument, uint8_t __timer);
static int usb_write(hid_device *device, uint8_t *buffer, int len) {
int retries = 20;
int retval;
while(((retval = hid_write(device, buffer, len)) < len) && --retries) {
if(retval < 0) {
usleep(100 * 1000); // No data has been sent here. Delay and retry.
} else {
return 0; // Partial data has been sent. Firmware will be corrupted. Abort process.
}
}
if(retries <= 0) {
return 0;
}
return 1;
}
int main(int argc, char *argv[]) {
uint8_t page_data[SECTOR_SIZE];
uint8_t hid_tx_buf[HID_TX_SIZE];
uint8_t hid_rx_buf[HID_RX_SIZE];
uint8_t CMD_RESET_PAGES[8] = {'B','T','L','D','C','M','D', 0x00};
uint8_t CMD_REBOOT_MCU[8] = {'B','T','L','D','C','M','D', 0x01};
hid_device *handle = NULL;
size_t read_bytes;
FILE *firmware_file = NULL;
int error = 0;
uint32_t n_bytes = 0;
int i;
setbuf(stdout, NULL);
uint8_t _timer = 0;
printf("\n+-----------------------------------------------------------------------+\n");
printf ("| HID-Flash v2.2.1 - STM32 HID Bootloader Flash Tool |\n");
printf ("| (c) 2018 - Bruno Freitas http://www.brunofreitas.com |\n");
printf ("| (c) 2018-2019 - Vassilis Serasidis https://www.serasidis.gr |\n");
printf ("| Customized for STM32duino ecosystem https://www.stm32duino.com |\n");
printf ("+-----------------------------------------------------------------------+\n\n");
// TODO: This really needs an option parser
if(argc < 2) {
printf("Usage: hid-flash <bin_firmware_file> <comport (optional)> <delay (optional)>\n");
return 1;
}else if(argc == 4){
_timer = atol(argv[3]);
}
firmware_file = fopen(argv[1], "rb");
if(!firmware_file) {
printf("> Error opening firmware file: %s\n", argv[1]);
return error;
}
if (argc > 2) {
if(serial_init(argv[2], _timer) == 0){ //Setting up Serial port
RS232_CloseComport();
}else{
printf("> Unable to open the [%s]\n",argv[2]);
}
}
hid_init();
printf("> Searching for [%04X:%04X] device...\n",VID,PID);
struct hid_device_info *devs, *cur_dev;
uint8_t valid_hid_devices = 0;
for(i=0;i<10;i++){ //Try up to 10 times to open the HID device.
devs = hid_enumerate(VID, PID);
cur_dev = devs;
while (cur_dev) { //Search for valid HID Bootloader USB devices
if((cur_dev->vendor_id == VID)&&(cur_dev->product_id == PID)){
valid_hid_devices++;
if(cur_dev->release_number < FIRMWARE_VER){ //The STM32 board has firmware lower than 3.00
printf("\nError - Please update the firmware to the latest version (v3.00+)");
goto exit;
}
}
cur_dev = cur_dev->next;
}
hid_free_enumeration(devs);
printf("#");
sleep(1);
if(valid_hid_devices > 0) break;
}
if (valid_hid_devices == 0){
printf("\nError - [%04X:%04X] device is not found :(",VID,PID);
error = 1;
goto exit;
}
handle = hid_open(VID, PID, NULL);
if (i == 10 && handle != NULL) {
printf("\n> Unable to open the [%04X:%04X] device.\n",VID,PID);
error = 1;
goto exit;
}
printf("\n> [%04X:%04X] device is found !\n",VID,PID);
// Send RESET PAGES command to put HID bootloader in initial stage...
memset(hid_tx_buf, 0, sizeof(hid_tx_buf)); //Fill the hid_tx_buf with zeros.
memcpy(&hid_tx_buf[1], CMD_RESET_PAGES, sizeof(CMD_RESET_PAGES));
printf("> Sending <reset pages> command...\n");
// Flash is unavailable when writing to it, so USB interrupt may fail here
if(!usb_write(handle, hid_tx_buf, HID_TX_SIZE)) {
printf("> Error while sending <reset pages> command.\n");
error = 1;
goto exit;
}
memset(hid_tx_buf, 0, sizeof(hid_tx_buf));
// Send Firmware File data
printf("> Flashing firmware...\n");
memset(page_data, 0, sizeof(page_data));
read_bytes = fread(page_data, 1, sizeof(page_data), firmware_file);
while(1) {
for(int i = 0; i < SECTOR_SIZE; i += HID_TX_SIZE - 1) {
memcpy(&hid_tx_buf[1], page_data + i, HID_TX_SIZE - 1);
if((i % 1024) == 0){
printf(".");
}
// Flash is unavailable when writing to it, so USB interrupt may fail here
if(!usb_write(handle, hid_tx_buf, HID_TX_SIZE)) {
printf("> Error while flashing firmware data.\n");
error = 1;
goto exit;
}
n_bytes += (HID_TX_SIZE - 1);
usleep(500);
}
printf(" %d Bytes\n", n_bytes);
do{
hid_read(handle, hid_rx_buf, 9);
usleep(500);
// Exit the loop if we recieve 0x02 or 0x03
}while((hid_rx_buf[7] & 0xFE) != 0x02);
memset(page_data, 0, sizeof(page_data));
read_bytes = fread(page_data, 1, sizeof(page_data), firmware_file);
// For stm32f1 high density devices (2K page size) will receive a
// 0x03 command acknowledgement above. In that case, we must
// make sure that we send a full 2K so the last page is written.
// Note that this issue does not affect STM32F4 devices with larger
// page sizes.
if (read_bytes == 0) {
if (hid_rx_buf[7] != 0x03 || (n_bytes % MAX_PAGE_SIZE) == 0)
break;
}
}
printf("\n> Done!\n");
// Send CMD_REBOOT_MCU command to reboot the microcontroller...
memset(hid_tx_buf, 0, sizeof(hid_tx_buf));
memcpy(&hid_tx_buf[1], CMD_REBOOT_MCU, sizeof(CMD_REBOOT_MCU));
printf("> Sending <reboot mcu> command...\n");
// Flash is unavailable when writing to it, so USB interrupt may fail here
if(!usb_write(handle, hid_tx_buf, HID_TX_SIZE)) {
printf("> Error while sending <reboot mcu> command.\n");
}
exit:
if(handle) {
hid_close(handle);
}
hid_exit();
if(firmware_file) {
fclose(firmware_file);
}
if (argc > 2) {
printf("> Searching for [%s] ...\n",argv[2]);
for(int i=0;i<5;i++){
if(RS232_OpenComport(argv[2]) == 0){
printf("> [%s] is found !\n",argv[2] );
break;
}
sleep(1);
}
if(i==5){
printf("> Comport is not found\n");
}
}
printf("> Finish\n");
return error;
}
int serial_init(char *argument, uint8_t __timer) {
printf("> Trying to open the [%s]...\n",argument);
if(RS232_OpenComport(argument)){
return(1);
}
printf("> Toggling DTR...\n");
RS232_disableRTS();
RS232_disableDTR();
usleep(200000L);
RS232_enableDTR();
usleep(200000L);
RS232_CloseComport();
//printf("A %i\n",__timer);
if (__timer > 0) {
usleep(__timer);
}
return 0;
}

314
lib/hidflash/rs232.c Normal file
View File

@@ -0,0 +1,314 @@
/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Teunis van Beelen
*
* Email: teuniz@gmail.com
*
***************************************************************************
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*
***************************************************************************
*/
/* Last revision: November 22, 2017 */
/* For more info and how to use this library, visit: http://www.teuniz.net/RS-232/ */
#include "rs232.h"
#include <string.h>
#include <stdio.h>
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) /* Linux & FreeBSD */
int tty_fd;
struct termios old_termios;
struct termios new_termios;
int RS232_OpenComport(char *comport) {
char str[64]= "/dev/";
strcat(str, comport);
tty_fd = open(str, O_RDWR | O_NOCTTY);
if (tty_fd < 0) {
fprintf(stderr, "error, counldn't open [%s]\n", str);
return 1;
}
if (tcgetattr(tty_fd, &old_termios) != 0) {
fprintf(stderr, "tcgetattr(fd, &old_termios) failed: %s\n", strerror(errno));
return 1;
}
memset(&new_termios, 0, sizeof(new_termios));
new_termios.c_iflag = IGNPAR;
new_termios.c_oflag = 0;
new_termios.c_cflag = CS8 | CREAD | CLOCAL | HUPCL;
new_termios.c_lflag = 0;
new_termios.c_cc[VINTR] = 0;
new_termios.c_cc[VQUIT] = 0;
new_termios.c_cc[VERASE] = 0;
new_termios.c_cc[VKILL] = 0;
new_termios.c_cc[VEOF] = 4;
new_termios.c_cc[VTIME] = 0;
new_termios.c_cc[VMIN] = 1;
//new_termios.c_cc[VSWTC] = 0;
new_termios.c_cc[VSTART] = 0;
new_termios.c_cc[VSTOP] = 0;
new_termios.c_cc[VSUSP] = 0;
new_termios.c_cc[VEOL] = 0;
new_termios.c_cc[VREPRINT] = 0;
new_termios.c_cc[VDISCARD] = 0;
new_termios.c_cc[VWERASE] = 0;
new_termios.c_cc[VLNEXT] = 0;
new_termios.c_cc[VEOL2] = 0;
if (cfsetispeed(&new_termios, B1200) != 0) {
fprintf(stderr, "cfsetispeed(&new_termios, B1200) failed: %s\n", strerror(errno));
return 1;
}
if (cfsetospeed(&new_termios, B1200) != 0) {
fprintf(stderr, "cfsetospeed(&new_termios, B1200) failed: %s\n", strerror(errno));
return 1;
}
if (tcsetattr(tty_fd, TCSANOW, &new_termios) != 0) {
fprintf(stderr, "tcsetattr(fd, TCSANOW, &new_termios) failed: %s\n", strerror(errno));
return 1;
}
return 0;
//======================================================================================
}
int RS232_SendByte(unsigned char byte) {
int n = write(tty_fd, &byte, 1);
if(n < 0) {
if(errno == EAGAIN) {
return 0;
} else {
return 1;
}
}
return(0);
}
/*
int RS232_ReadByte() {
unsigned char c;
if (read(tty_fd,&c,1)>0) {
return c;
}
return -1;
}
*/
void RS232_CloseComport() {
tcsetattr(tty_fd, TCSANOW, &old_termios);
close(tty_fd);
}
void RS232_enableDTR() {
int status;
if(ioctl(tty_fd, TIOCMGET, &status) == -1) {
perror("unable to get portstatus");
}
status |= TIOCM_DTR; /* turn on DTR */
if(ioctl(tty_fd, TIOCMSET, &status) == -1) {
perror("unable to set portstatus");
}
}
void RS232_disableDTR()
{
int status;
if(ioctl(tty_fd, TIOCMGET, &status) == -1) {
perror("unable to get portstatus");
}
status &= ~TIOCM_DTR; /* turn off DTR */
if(ioctl(tty_fd, TIOCMSET, &status) == -1) {
perror("unable to set portstatus");
}
}
void RS232_enableRTS()
{
int status;
if(ioctl(tty_fd, TIOCMGET, &status) == -1) {
perror("unable to get portstatus");
}
status |= TIOCM_RTS; /* turn on RTS */
if(ioctl(tty_fd, TIOCMSET, &status) == -1) {
perror("unable to set portstatus");
}
}
void RS232_disableRTS() {
int status;
if(ioctl(tty_fd, TIOCMGET, &status) == -1) {
perror("unable to get portstatus");
}
status &= ~TIOCM_RTS; /* turn off RTS */
if(ioctl(tty_fd, TIOCMSET, &status) == -1) {
perror("unable to set portstatus");
}
}
void RS232_send_magic(){
write(tty_fd,"1EAF",4);
}
#else /* windows */
HANDLE Cport;
char mode_str_2[] = "baud=9600 data=8 parity=n stop=1 dtr=off rts=off";
int RS232_OpenComport(char *comport)
{
//printf("%s\n %s\n %s\n %p\n", mode_str_2, comports[comport_number], comport, Cport);
char str[32] = "\\\\.\\";
strcat(str, comport);
//printf("%s\n", str);
Cport = CreateFileA(str,
GENERIC_READ|GENERIC_WRITE,
0, /* no share */
NULL, /* no security */
OPEN_EXISTING,
0, /* no threads */
NULL); /* no templates */
if(Cport==INVALID_HANDLE_VALUE)
{
//printf("> unable to open comport\n");
return(1);
}
DCB port_settings;
memset(&port_settings, 0, sizeof(port_settings)); /* clear the new struct */
port_settings.DCBlength = sizeof(port_settings);
if(!BuildCommDCBA(mode_str_2, &port_settings))
{
printf("> unable to set comport dcb settings\n");
CloseHandle(Cport);
return(1);
}
if(!SetCommState(Cport, &port_settings))
{
printf("> unable to set comport cfg settings\n");
CloseHandle(Cport);
return(1);
}
COMMTIMEOUTS Cptimeouts;
Cptimeouts.ReadIntervalTimeout = MAXDWORD;
Cptimeouts.ReadTotalTimeoutMultiplier = 0;
Cptimeouts.ReadTotalTimeoutConstant = 0;
Cptimeouts.WriteTotalTimeoutMultiplier = 0;
Cptimeouts.WriteTotalTimeoutConstant = 0;
if(!SetCommTimeouts(Cport, &Cptimeouts))
{
printf("> unable to set comport time-out settings\n");
CloseHandle(Cport);
return(1);
}
return(0);
}
int RS232_SendByte(unsigned char byte)
{
int n;
WriteFile(Cport, &byte, 1, (LPDWORD)((void *)&n), NULL);
if(n<0) return(1);
return(0);
}
void RS232_CloseComport()
{
CloseHandle(Cport);
}
void RS232_enableDTR()
{
EscapeCommFunction(Cport, SETDTR);
}
void RS232_disableDTR()
{
EscapeCommFunction(Cport, CLRDTR);
}
void RS232_enableRTS()
{
EscapeCommFunction(Cport, SETRTS);
}
void RS232_disableRTS()
{
EscapeCommFunction(Cport, CLRRTS);
}
void RS232_send_magic()
{
int n;
WriteFile(Cport, "1EAF", 4, (LPDWORD)((void *)&n), NULL);
}
#endif

83
lib/hidflash/rs232.h Normal file
View File

@@ -0,0 +1,83 @@
/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Teunis van Beelen
*
* Email: teuniz@gmail.com
*
***************************************************************************
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*
***************************************************************************
*/
/**
* This rs232 source code file is a customized version for HID Bootloader project
* (c) 10 May 2018 by Vassilis Serasidis http://www.serasidis.gr <avrsite@yahoo.gr>
*
*/
/* For more info and how to use this library, visit: http://www.teuniz.net/RS-232/ */
#ifndef rs232_INCLUDED
#define rs232_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <string.h>
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <sys/file.h>
#include <errno.h>
#else
#include <windows.h>
#endif
int RS232_OpenComport(char *);
int RS232_SendByte(unsigned char);
//int RS232_ReadByte();
void RS232_CloseComport();
void RS232_enableDTR();
void RS232_disableDTR();
void RS232_enableRTS();
void RS232_disableRTS();
void RS232_send_magic();
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

412
lib/hub-ctrl/hub-ctrl.c Normal file
View File

@@ -0,0 +1,412 @@
/*
* Copyright (C) 2006 Free Software Initiative of Japan
*
* Author: NIIBE Yutaka <gniibe at fsij.org>
*
* This file can be distributed under the terms and conditions of the
* GNU General Public License version 2 (or later).
*
*/
#include <errno.h>
#include <usb.h>
#include <stdio.h>
#include <string.h>
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
#define USB_PORT_FEAT_POWER 8
#define USB_PORT_FEAT_INDICATOR 22
#define USB_DIR_IN 0x80 /* to host */
#define COMMAND_SET_NONE 0
#define COMMAND_SET_LED 1
#define COMMAND_SET_POWER 2
#define HUB_LED_GREEN 2
static void
usage (const char *progname)
{
fprintf (stderr,
"Usage: %s [{-h HUBNUM | -b BUSNUM -d DEVNUM}] \\\n"
" [-P PORT] [{-p [VALUE]|-l [VALUE]}]\n", progname);
}
static void
exit_with_usage (const char *progname)
{
usage (progname);
exit (1);
}
#define HUB_CHAR_LPSM 0x0003
#define HUB_CHAR_PORTIND 0x0080
struct usb_hub_descriptor {
unsigned char bDescLength;
unsigned char bDescriptorType;
unsigned char bNbrPorts;
unsigned char wHubCharacteristics[2];
unsigned char bPwrOn2PwrGood;
unsigned char bHubContrCurrent;
unsigned char data[0];
};
#define CTRL_TIMEOUT 1000
#define USB_STATUS_SIZE 4
#define MAX_HUBS 128
struct hub_info {
int busnum, devnum;
struct usb_device *dev;
int nport;
int indicator_support;
};
static struct hub_info hubs[MAX_HUBS];
static int number_of_hubs_with_feature;
static void
hub_port_status (usb_dev_handle *uh, int nport)
{
int i;
printf(" Hub Port Status:\n");
for (i = 0; i < nport; i++)
{
char buf[USB_STATUS_SIZE];
int ret;
ret = usb_control_msg (uh,
USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_OTHER,
USB_REQ_GET_STATUS,
0, i + 1,
buf, USB_STATUS_SIZE,
CTRL_TIMEOUT);
if (ret < 0)
{
fprintf (stderr,
"cannot read port %d status, %s (%d)\n",
i + 1, strerror(errno), errno);
break;
}
printf(" Port %d: %02x%02x.%02x%02x", i + 1,
buf[3], buf [2],
buf[1], buf [0]);
printf("%s%s%s%s%s",
(buf[2] & 0x10) ? " C_RESET" : "",
(buf[2] & 0x08) ? " C_OC" : "",
(buf[2] & 0x04) ? " C_SUSPEND" : "",
(buf[2] & 0x02) ? " C_ENABLE" : "",
(buf[2] & 0x01) ? " C_CONNECT" : "");
printf("%s%s%s%s%s%s%s%s%s%s\n",
(buf[1] & 0x10) ? " indicator" : "",
(buf[1] & 0x08) ? " test" : "",
(buf[1] & 0x04) ? " highspeed" : "",
(buf[1] & 0x02) ? " lowspeed" : "",
(buf[1] & 0x01) ? " power" : "",
(buf[0] & 0x10) ? " RESET" : "",
(buf[0] & 0x08) ? " oc" : "",
(buf[0] & 0x04) ? " suspend" : "",
(buf[0] & 0x02) ? " enable" : "",
(buf[0] & 0x01) ? " connect" : "");
}
}
static int
usb_find_hubs (int listing, int verbose, int busnum, int devnum, int hub)
{
struct usb_bus *busses;
struct usb_bus *bus;
number_of_hubs_with_feature = 0;
busses = usb_get_busses();
if (busses == NULL)
{
perror ("failed to access USB");
return -1;
}
for (bus = busses; bus; bus = bus->next)
{
struct usb_device *dev;
for (dev = bus->devices; dev; dev = dev->next)
{
usb_dev_handle *uh;
int print = 0;
if (dev->descriptor.bDeviceClass != USB_CLASS_HUB)
continue;
if (listing
|| (verbose
&& ((atoi (bus->dirname) == busnum && dev->devnum == devnum)
|| hub == number_of_hubs_with_feature)))
print = 1;
uh = usb_open (dev);
if (uh != NULL)
{
char buf[1024];
int len;
int nport;
struct usb_hub_descriptor *uhd = (struct usb_hub_descriptor *)buf;
if ((len = usb_control_msg (uh, USB_DIR_IN | USB_RT_HUB,
USB_REQ_GET_DESCRIPTOR,
USB_DT_HUB << 8, 0,
buf, sizeof (buf), CTRL_TIMEOUT))
> sizeof (struct usb_hub_descriptor))
{
if (!(uhd->wHubCharacteristics[0] & HUB_CHAR_PORTIND)
&& (uhd->wHubCharacteristics[0] & HUB_CHAR_LPSM) >= 2)
continue;
if (print)
printf ("Hub #%d at %s:%03d\n",
number_of_hubs_with_feature,
bus->dirname, dev->devnum);
switch ((uhd->wHubCharacteristics[0] & HUB_CHAR_LPSM))
{
case 0:
if (print)
fprintf (stderr, " INFO: ganged switching.\n");
break;
case 1:
if (print)
fprintf (stderr, " INFO: individual power switching.\n");
break;
case 2:
case 3:
if (print)
fprintf (stderr, " WARN: No power switching.\n");
break;
}
if (print
&& !(uhd->wHubCharacteristics[0] & HUB_CHAR_PORTIND))
fprintf (stderr, " WARN: Port indicators are NOT supported.\n");
}
else
{
perror ("Can't get hub descriptor");
usb_close (uh);
continue;
}
nport = buf[2];
hubs[number_of_hubs_with_feature].busnum = atoi (bus->dirname);
hubs[number_of_hubs_with_feature].devnum = dev->devnum;
hubs[number_of_hubs_with_feature].dev = dev;
hubs[number_of_hubs_with_feature].indicator_support =
(uhd->wHubCharacteristics[0] & HUB_CHAR_PORTIND)? 1 : 0;
hubs[number_of_hubs_with_feature].nport = nport;
number_of_hubs_with_feature++;
if (verbose)
hub_port_status (uh, nport);
usb_close (uh);
}
}
}
return number_of_hubs_with_feature;
}
int
get_hub (int busnum, int devnum)
{
int i;
for (i = 0; i < number_of_hubs_with_feature; i++)
if (hubs[i].busnum == busnum && hubs[i].devnum == devnum)
return i;
return -1;
}
/*
* HUB-CTRL - program to control port power/led of USB hub
*
* # hub-ctrl // List hubs available
* # hub-ctrl -P 1 // Power off at port 1
* # hub-ctrl -P 1 -p 1 // Power on at port 1
* # hub-ctrl -P 2 -l // LED on at port 1
*
* Requirement: USB hub which implements port power control / indicator control
*
* Work fine:
* Elecom's U2H-G4S: www.elecom.co.jp (indicator depends on power)
* 04b4:6560
*
* Sanwa Supply's USB-HUB14GPH: www.sanwa.co.jp (indicators don't)
*
* Targus, Inc.'s PAUH212: www.targus.com (indicators don't)
* 04cc:1521
*
* Hawking Technology's UH214: hawkingtech.com (indicators don't)
*
*/
int
main (int argc, const char *argv[])
{
int busnum = 0, devnum = 0;
int cmd = COMMAND_SET_NONE;
int port = 1;
int value = 0;
int request, feature, index;
int result = 0;
int listing = 0;
int verbose = 0;
int hub = -1;
usb_dev_handle *uh = NULL;
int i;
if (argc == 1)
listing = 1;
for (i = 1; i < argc; i++)
if (argv[i][0] == '-')
switch (argv[i][1])
{
case 'h':
if (++i >= argc || busnum > 0 || devnum > 0)
exit_with_usage (argv[0]);
hub = atoi (argv[i]);
break;
case 'b':
if (++i >= argc || hub >= 0)
exit_with_usage (argv[0]);
busnum = atoi (argv[i]);
break;
case 'd':
if (++i >= argc || hub >= 0)
exit_with_usage (argv[0]);
devnum = atoi (argv[i]);
break;
case 'P':
if (++i >= argc)
exit_with_usage (argv[0]);
port = atoi (argv[i]);
break;
case 'l':
if (cmd != COMMAND_SET_NONE)
exit_with_usage (argv[0]);
if (++i < argc)
value = atoi (argv[i]);
else
value = HUB_LED_GREEN;
cmd = COMMAND_SET_LED;
break;
case 'p':
if (cmd != COMMAND_SET_NONE)
exit_with_usage (argv[0]);
if (++i < argc)
value = atoi (argv[i]);
else
value= 0;
cmd = COMMAND_SET_POWER;
break;
case 'v':
verbose = 1;
if (argc == 2)
listing = 1;
break;
default:
exit_with_usage (argv[0]);
}
else
exit_with_usage (argv[0]);
if ((busnum > 0 && devnum <= 0) || (busnum <= 0 && devnum > 0))
/* BUS is specified, but DEV is'nt, or ... */
exit_with_usage (argv[0]);
/* Default is the hub #0 */
if (hub < 0 && busnum == 0)
hub = 0;
/* Default is POWER */
if (cmd == COMMAND_SET_NONE)
cmd = COMMAND_SET_POWER;
usb_init ();
usb_find_busses ();
usb_find_devices ();
if (usb_find_hubs (listing, verbose, busnum, devnum, hub) <= 0)
{
fprintf (stderr, "No hubs found.\n");
exit (1);
}
if (listing)
exit (0);
if (hub < 0)
hub = get_hub (busnum, devnum);
if (hub >= 0 && hub < number_of_hubs_with_feature)
uh = usb_open (hubs[hub].dev);
if (uh == NULL)
{
fprintf (stderr, "Device not found.\n");
result = 1;
}
else
{
if (cmd == COMMAND_SET_POWER)
if (value)
{
request = USB_REQ_SET_FEATURE;
feature = USB_PORT_FEAT_POWER;
index = port;
}
else
{
request = USB_REQ_CLEAR_FEATURE;
feature = USB_PORT_FEAT_POWER;
index = port;
}
else
{
request = USB_REQ_SET_FEATURE;
feature = USB_PORT_FEAT_INDICATOR;
index = (value << 8) | port;
}
if (verbose)
printf ("Send control message (REQUEST=%d, FEATURE=%d, INDEX=%d)\n",
request, feature, index);
if (usb_control_msg (uh, USB_RT_PORT, request, feature, index,
NULL, 0, CTRL_TIMEOUT) < 0)
{
perror ("failed to control.\n");
result = 1;
}
if (verbose)
hub_port_status (uh, hubs[hub].nport);
usb_close (uh);
}
exit (result);
}

View File

@@ -0,0 +1,5 @@
Copyright (c) 2011-2019, Ulf Magnusson <ulfalizer@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Binary file not shown.

154
lib/kconfiglib/genconfig.py Normal file
View File

@@ -0,0 +1,154 @@
#!/usr/bin/env python3
# Copyright (c) 2018-2019, Ulf Magnusson
# SPDX-License-Identifier: ISC
"""
Generates a header file with #defines from the configuration, matching the
format of include/generated/autoconf.h in the Linux kernel.
Optionally, also writes the configuration output as a .config file. See
--config-out.
The --sync-deps, --file-list, and --env-list options generate information that
can be used to avoid needless rebuilds/reconfigurations.
Before writing a header or configuration file, Kconfiglib compares the old
contents of the file against the new contents. If there's no change, the write
is skipped. This avoids updating file metadata like the modification time, and
might save work depending on your build setup.
By default, the configuration is generated from '.config'. A different
configuration file can be passed in the KCONFIG_CONFIG environment variable.
A custom header string can be inserted at the beginning of generated
configuration and header files by setting the KCONFIG_CONFIG_HEADER and
KCONFIG_AUTOHEADER_HEADER environment variables, respectively (this also works
for other scripts). The string is not automatically made a comment (this is by
design, to allow anything to be added), and no trailing newline is added, so
add '/* */', '#', and newlines as appropriate.
See https://www.gnu.org/software/make/manual/make.html#Multi_002dLine for a
handy way to define multi-line variables in makefiles, for use with custom
headers. Remember to export the variable to the environment.
"""
import argparse
import os
import sys
import kconfiglib
DEFAULT_SYNC_DEPS_PATH = "deps/"
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=__doc__)
parser.add_argument(
"--header-path",
metavar="HEADER_FILE",
help="""
Path to write the generated header file to. If not specified, the path in the
environment variable KCONFIG_AUTOHEADER is used if it is set, and 'config.h'
otherwise.
""")
parser.add_argument(
"--config-out",
metavar="CONFIG_FILE",
help="""
Write the configuration to CONFIG_FILE. This is useful if you include .config
files in Makefiles, as the generated configuration file will be a full .config
file even if .config is outdated. The generated configuration matches what
olddefconfig would produce. If you use sync-deps, you can include
deps/auto.conf instead. --config-out is meant for cases where incremental build
information isn't needed.
""")
parser.add_argument(
"--sync-deps",
metavar="OUTPUT_DIR",
nargs="?",
const=DEFAULT_SYNC_DEPS_PATH,
help="""
Enable generation of symbol dependency information for incremental builds,
optionally specifying the output directory (default: {}). See the docstring of
Kconfig.sync_deps() in Kconfiglib for more information.
""".format(DEFAULT_SYNC_DEPS_PATH))
parser.add_argument(
"--file-list",
metavar="OUTPUT_FILE",
help="""
Write a list of all Kconfig files to OUTPUT_FILE, with one file per line. The
paths are relative to $srctree (or to the current directory if $srctree is
unset). Files appear in the order they're 'source'd.
""")
parser.add_argument(
"--env-list",
metavar="OUTPUT_FILE",
help="""
Write a list of all environment variables referenced in Kconfig files to
OUTPUT_FILE, with one variable per line. Each line has the format NAME=VALUE.
Only environment variables referenced with the preprocessor $(VAR) syntax are
included, and not variables referenced with the older $VAR syntax (which is
only supported for backwards compatibility).
""")
parser.add_argument(
"kconfig",
metavar="KCONFIG",
nargs="?",
default="Kconfig",
help="Top-level Kconfig file (default: Kconfig)")
args = parser.parse_args()
kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True)
kconf.load_config()
if args.header_path is None:
if "KCONFIG_AUTOHEADER" in os.environ:
kconf.write_autoconf()
else:
# Kconfiglib defaults to include/generated/autoconf.h to be
# compatible with the C tools. 'config.h' is used here instead for
# backwards compatibility. It's probably a saner default for tools
# as well.
kconf.write_autoconf("config.h")
else:
kconf.write_autoconf(args.header_path)
if args.config_out is not None:
kconf.write_config(args.config_out, save_old=False)
if args.sync_deps is not None:
kconf.sync_deps(args.sync_deps)
if args.file_list is not None:
with _open_write(args.file_list) as f:
for path in kconf.kconfig_filenames:
f.write(path + "\n")
if args.env_list is not None:
with _open_write(args.env_list) as f:
for env_var in kconf.env_vars:
f.write("{}={}\n".format(env_var, os.environ[env_var]))
def _open_write(path):
# Python 2/3 compatibility. io.open() is available on both, but makes
# write() expect 'unicode' strings on Python 2.
if sys.version_info[0] < 3:
return open(path, "w")
return open(path, "w", encoding="utf-8")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,147 @@
diff --git a/lib/kconfiglib/kconfiglib.py b/lib/kconfiglib/kconfiglib.py
index c67895ce..fb5e4b76 100644
--- a/lib/kconfiglib/kconfiglib.py
+++ b/lib/kconfiglib/kconfiglib.py
@@ -1475,8 +1475,8 @@ class Kconfig(object):
# instead, to avoid accessing the internal _write_to_conf variable
# (though it's likely to keep working).
val = sym.str_value
- if not sym._write_to_conf:
- continue
+ #if not sym._write_to_conf:
+ # continue
if sym.orig_type in _BOOL_TRISTATE:
if val == "y":
@@ -1485,6 +1485,9 @@ class Kconfig(object):
elif val == "m":
add("#define {}{}_MODULE 1\n"
.format(self.config_prefix, sym.name))
+ else:
+ add("#define {}{} 0\n"
+ .format(self.config_prefix, sym.name))
elif sym.orig_type is STRING:
add('#define {}{} "{}"\n'
@@ -1494,6 +1497,8 @@ class Kconfig(object):
if sym.orig_type is HEX and \
not val.startswith(("0x", "0X")):
val = "0x" + val
+ if not val:
+ val = "0"
add("#define {}{} {}\n"
.format(self.config_prefix, sym.name, val))
diff --git a/lib/kconfiglib/menuconfig.py b/lib/kconfiglib/menuconfig.py
index 7e765d36..900d88a1 100755
--- a/lib/kconfiglib/menuconfig.py
+++ b/lib/kconfiglib/menuconfig.py
@@ -259,10 +259,8 @@ _N_SCROLL_ARROWS = 14
# Lines of help text shown at the bottom of the "main" display
_MAIN_HELP_LINES = """
-[Space/Enter] Toggle/enter [ESC] Leave menu [S] Save
-[O] Load [?] Symbol info [/] Jump to symbol
-[F] Toggle show-help mode [C] Toggle show-name mode [A] Toggle show-all mode
-[Q] Quit (prompts for save) [D] Save minimal config (advanced)
+[Space/Enter] Toggle/enter [?] Help [/] Search
+[Q] Quit (prompts for save) [ESC] Leave menu
"""[1:-1].split("\n")
# Lines of help text shown at the bottom of the information dialog
@@ -890,17 +888,17 @@ def _menuconfig(stdscr):
else:
_leave_menu()
- elif c in ("o", "O"):
+ elif 0 and c in ("o", "O"):
_load_dialog()
- elif c in ("s", "S"):
+ elif 0 and c in ("s", "S"):
filename = _save_dialog(_kconf.write_config, _conf_filename,
"configuration")
if filename:
_conf_filename = filename
_conf_changed = False
- elif c in ("d", "D"):
+ elif 0 and c in ("d", "D"):
filename = _save_dialog(_kconf.write_min_config, _minconf_filename,
"minimal configuration")
if filename:
@@ -918,15 +916,15 @@ def _menuconfig(stdscr):
# dialog was open
_resize_main()
- elif c in ("f", "F"):
+ elif 0 and c in ("f", "F"):
_show_help = not _show_help
_set_style(_help_win, "show-help" if _show_help else "help")
_resize_main()
- elif c in ("c", "C"):
+ elif 0 and c in ("c", "C"):
_show_name = not _show_name
- elif c in ("a", "A"):
+ elif 0 and c in ("a", "A"):
_toggle_show_all()
elif c in ("q", "Q"):
@@ -2552,11 +2550,11 @@ def _info_str(node):
_prompt_info(sym) +
"Type: {}\n".format(TYPE_TO_STR[sym.type]) +
_value_info(sym) +
- _help_info(sym) +
- _direct_dep_info(sym) +
- _defaults_info(sym) +
- _select_imply_info(sym) +
- _kconfig_def_info(sym)
+ _help_info(sym)
+ #_direct_dep_info(sym) +
+ #_defaults_info(sym) +
+ #_select_imply_info(sym) +
+ #_kconfig_def_info(sym)
)
if isinstance(node.item, Choice):
@@ -2568,10 +2566,10 @@ def _info_str(node):
"Type: {}\n".format(TYPE_TO_STR[choice.type]) +
'Mode: {}\n'.format(choice.str_value) +
_help_info(choice) +
- _choice_syms_info(choice) +
- _direct_dep_info(choice) +
- _defaults_info(choice) +
- _kconfig_def_info(choice)
+ _choice_syms_info(choice)
+ #_direct_dep_info(choice) +
+ #_defaults_info(choice) +
+ #_kconfig_def_info(choice)
)
return _kconfig_def_info(node) # node.item in (MENU, COMMENT)
@@ -2588,10 +2586,12 @@ def _prompt_info(sc):
# Returns a string listing the prompts of 'sc' (Symbol or Choice)
s = ""
+ found = []
for node in sc.nodes:
- if node.prompt:
+ if node.prompt and node.prompt[0] not in found:
s += "Prompt: {}\n".format(node.prompt[0])
+ found.append(node.prompt[0])
return s
@@ -2632,6 +2632,9 @@ def _help_info(sc):
if node.help is not None:
s += "Help:\n\n{}\n\n".format(_indent(node.help, 2))
+ if s == "\n":
+ s = "\nHelp: (No help available)\n\n"
+
return s

7165
lib/kconfiglib/kconfiglib.py Normal file

File diff suppressed because it is too large Load Diff

3281
lib/kconfiglib/menuconfig.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
#!/usr/bin/env python3
# Copyright (c) 2018-2019, Ulf Magnusson
# SPDX-License-Identifier: ISC
"""
Updates an old .config file or creates a new one, by filling in default values
for all new symbols. This is the same as picking the default selection for all
symbols in oldconfig, or entering the menuconfig interface and immediately
saving.
The default input/output filename is '.config'. A different filename can be
passed in the KCONFIG_CONFIG environment variable.
When overwriting a configuration file, the old version is saved to
<filename>.old (e.g. .config.old).
"""
import kconfiglib
def main():
kconf = kconfiglib.standard_kconfig(__doc__)
print(kconf.load_config())
print(kconf.write_config())
if __name__ == "__main__":
main()

1035
lib/lpc176x/device/LPC17xx.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,581 @@
/**************************************************************************//**
* @file system_LPC17xx.c
* @brief CMSIS Cortex-M3 Device System Source File for
* NXP LPC17xx Device Series
* @version V1.11
* @date 21. June 2011
*
* @note
* Copyright (C) 2009-2011 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#include <stdint.h>
#include "LPC17xx.h"
/** @addtogroup LPC17xx_System
* @{
*/
/*
//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
*/
/*--------------------- Clock Configuration ----------------------------------
//
// <e> Clock Configuration
// <h> System Controls and Status Register (SCS)
// <o1.4> OSCRANGE: Main Oscillator Range Select
// <0=> 1 MHz to 20 MHz
// <1=> 15 MHz to 25 MHz
// <e1.5> OSCEN: Main Oscillator Enable
// </e>
// </h>
//
// <h> Clock Source Select Register (CLKSRCSEL)
// <o2.0..1> CLKSRC: PLL Clock Source Selection
// <0=> Internal RC oscillator
// <1=> Main oscillator
// <2=> RTC oscillator
// </h>
//
// <e3> PLL0 Configuration (Main PLL)
// <h> PLL0 Configuration Register (PLL0CFG)
// <i> F_cco0 = (2 * M * F_in) / N
// <i> F_in must be in the range of 32 kHz to 50 MHz
// <i> F_cco0 must be in the range of 275 MHz to 550 MHz
// <o4.0..14> MSEL: PLL Multiplier Selection
// <6-32768><#-1>
// <i> M Value
// <o4.16..23> NSEL: PLL Divider Selection
// <1-256><#-1>
// <i> N Value
// </h>
// </e>
//
// <e5> PLL1 Configuration (USB PLL)
// <h> PLL1 Configuration Register (PLL1CFG)
// <i> F_usb = M * F_osc or F_usb = F_cco1 / (2 * P)
// <i> F_cco1 = F_osc * M * 2 * P
// <i> F_cco1 must be in the range of 156 MHz to 320 MHz
// <o6.0..4> MSEL: PLL Multiplier Selection
// <1-32><#-1>
// <i> M Value (for USB maximum value is 4)
// <o6.5..6> PSEL: PLL Divider Selection
// <0=> 1
// <1=> 2
// <2=> 4
// <3=> 8
// <i> P Value
// </h>
// </e>
//
// <h> CPU Clock Configuration Register (CCLKCFG)
// <o7.0..7> CCLKSEL: Divide Value for CPU Clock from PLL0
// <1-256><#-1>
// </h>
//
// <h> USB Clock Configuration Register (USBCLKCFG)
// <o8.0..3> USBSEL: Divide Value for USB Clock from PLL0
// <0-15>
// <i> Divide is USBSEL + 1
// </h>
//
// <h> Peripheral Clock Selection Register 0 (PCLKSEL0)
// <o9.0..1> PCLK_WDT: Peripheral Clock Selection for WDT
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.2..3> PCLK_TIMER0: Peripheral Clock Selection for TIMER0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.4..5> PCLK_TIMER1: Peripheral Clock Selection for TIMER1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.6..7> PCLK_UART0: Peripheral Clock Selection for UART0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.8..9> PCLK_UART1: Peripheral Clock Selection for UART1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.12..13> PCLK_PWM1: Peripheral Clock Selection for PWM1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.14..15> PCLK_I2C0: Peripheral Clock Selection for I2C0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.16..17> PCLK_SPI: Peripheral Clock Selection for SPI
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.20..21> PCLK_SSP1: Peripheral Clock Selection for SSP1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.22..23> PCLK_DAC: Peripheral Clock Selection for DAC
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.24..25> PCLK_ADC: Peripheral Clock Selection for ADC
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.26..27> PCLK_CAN1: Peripheral Clock Selection for CAN1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 6
// <o9.28..29> PCLK_CAN2: Peripheral Clock Selection for CAN2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 6
// <o9.30..31> PCLK_ACF: Peripheral Clock Selection for ACF
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 6
// </h>
//
// <h> Peripheral Clock Selection Register 1 (PCLKSEL1)
// <o10.0..1> PCLK_QEI: Peripheral Clock Selection for the Quadrature Encoder Interface
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.2..3> PCLK_GPIO: Peripheral Clock Selection for GPIOs
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.4..5> PCLK_PCB: Peripheral Clock Selection for the Pin Connect Block
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.6..7> PCLK_I2C1: Peripheral Clock Selection for I2C1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.10..11> PCLK_SSP0: Peripheral Clock Selection for SSP0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.12..13> PCLK_TIMER2: Peripheral Clock Selection for TIMER2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.14..15> PCLK_TIMER3: Peripheral Clock Selection for TIMER3
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.16..17> PCLK_UART2: Peripheral Clock Selection for UART2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.18..19> PCLK_UART3: Peripheral Clock Selection for UART3
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.20..21> PCLK_I2C2: Peripheral Clock Selection for I2C2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.22..23> PCLK_I2S: Peripheral Clock Selection for I2S
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.26..27> PCLK_RIT: Peripheral Clock Selection for the Repetitive Interrupt Timer
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.28..29> PCLK_SYSCON: Peripheral Clock Selection for the System Control Block
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.30..31> PCLK_MC: Peripheral Clock Selection for the Motor Control PWM
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// </h>
//
// <h> Power Control for Peripherals Register (PCONP)
// <o11.1> PCTIM0: Timer/Counter 0 power/clock enable
// <o11.2> PCTIM1: Timer/Counter 1 power/clock enable
// <o11.3> PCUART0: UART 0 power/clock enable
// <o11.4> PCUART1: UART 1 power/clock enable
// <o11.6> PCPWM1: PWM 1 power/clock enable
// <o11.7> PCI2C0: I2C interface 0 power/clock enable
// <o11.8> PCSPI: SPI interface power/clock enable
// <o11.9> PCRTC: RTC power/clock enable
// <o11.10> PCSSP1: SSP interface 1 power/clock enable
// <o11.12> PCAD: A/D converter power/clock enable
// <o11.13> PCCAN1: CAN controller 1 power/clock enable
// <o11.14> PCCAN2: CAN controller 2 power/clock enable
// <o11.15> PCGPIO: GPIOs power/clock enable
// <o11.16> PCRIT: Repetitive interrupt timer power/clock enable
// <o11.17> PCMC: Motor control PWM power/clock enable
// <o11.18> PCQEI: Quadrature encoder interface power/clock enable
// <o11.19> PCI2C1: I2C interface 1 power/clock enable
// <o11.21> PCSSP0: SSP interface 0 power/clock enable
// <o11.22> PCTIM2: Timer 2 power/clock enable
// <o11.23> PCTIM3: Timer 3 power/clock enable
// <o11.24> PCUART2: UART 2 power/clock enable
// <o11.25> PCUART3: UART 3 power/clock enable
// <o11.26> PCI2C2: I2C interface 2 power/clock enable
// <o11.27> PCI2S: I2S interface power/clock enable
// <o11.29> PCGPDMA: GP DMA function power/clock enable
// <o11.30> PCENET: Ethernet block power/clock enable
// <o11.31> PCUSB: USB interface power/clock enable
// </h>
//
// <h> Clock Output Configuration Register (CLKOUTCFG)
// <o12.0..3> CLKOUTSEL: Selects clock source for CLKOUT
// <0=> CPU clock
// <1=> Main oscillator
// <2=> Internal RC oscillator
// <3=> USB clock
// <4=> RTC oscillator
// <o12.4..7> CLKOUTDIV: Selects clock divider for CLKOUT
// <1-16><#-1>
// <o12.8> CLKOUT_EN: CLKOUT enable control
// </h>
//
// </e>
*/
/** @addtogroup LPC17xx_System_Defines LPC17xx System Defines
@{
*/
#define CLOCK_SETUP 1
#define SCS_Val 0x00000020
#define CLKSRCSEL_Val 0x00000001
#define PLL0_SETUP 1
#include "autoconf.h" // CONFIG_MACH_LPC1769
#if CONFIG_MACH_LPC1769
# define PLL0CFG_Val 0x0000000E
#else
# define PLL0CFG_Val 0x00010018
#endif
#define PLL1_SETUP 1
#define PLL1CFG_Val 0x00000023
#define CCLKCFG_Val 0x00000002
#define USBCLKCFG_Val 0x00000000
#define PCLKSEL0_Val 0x55515155
#define PCLKSEL1_Val 0x54555455
#define PCONP_Val 0x042887DE
#define CLKOUTCFG_Val 0x00000000
/*--------------------- Flash Accelerator Configuration ----------------------
//
// <e> Flash Accelerator Configuration
// <o1.12..15> FLASHTIM: Flash Access Time
// <0=> 1 CPU clock (for CPU clock up to 20 MHz)
// <1=> 2 CPU clocks (for CPU clock up to 40 MHz)
// <2=> 3 CPU clocks (for CPU clock up to 60 MHz)
// <3=> 4 CPU clocks (for CPU clock up to 80 MHz)
// <4=> 5 CPU clocks (for CPU clock up to 100 MHz)
// <5=> 6 CPU clocks (for any CPU clock)
// </e>
*/
#define FLASH_SETUP 1
#define FLASHCFG_Val 0x0000303A
/*
//-------- <<< end of configuration section >>> ------------------------------
*/
/*----------------------------------------------------------------------------
Check the register settings
*----------------------------------------------------------------------------*/
#define CHECK_RANGE(val, min, max) ((val < min) || (val > max))
#define CHECK_RSVD(val, mask) (val & mask)
/* Clock Configuration -------------------------------------------------------*/
#if (CHECK_RSVD((SCS_Val), ~0x00000030))
#error "SCS: Invalid values of reserved bits!"
#endif
#if (CHECK_RANGE((CLKSRCSEL_Val), 0, 2))
#error "CLKSRCSEL: Value out of range!"
#endif
#if (CHECK_RSVD((PLL0CFG_Val), ~0x00FF7FFF))
#error "PLL0CFG: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PLL1CFG_Val), ~0x0000007F))
#error "PLL1CFG: Invalid values of reserved bits!"
#endif
#if (PLL0_SETUP) /* if PLL0 is used */
#if (CCLKCFG_Val < 2) /* CCLKSEL must be greater then 1 */
#error "CCLKCFG: CCLKSEL must be greater then 1 if PLL0 is used!"
#endif
#endif
#if (CHECK_RANGE((CCLKCFG_Val), 2, 255))
#error "CCLKCFG: Value out of range!"
#endif
#if (CHECK_RSVD((USBCLKCFG_Val), ~0x0000000F))
#error "USBCLKCFG: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PCLKSEL0_Val), 0x000C0C00))
#error "PCLKSEL0: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PCLKSEL1_Val), 0x03000300))
#error "PCLKSEL1: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PCONP_Val), 0x10100821))
#error "PCONP: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((CLKOUTCFG_Val), ~0x000001FF))
#error "CLKOUTCFG: Invalid values of reserved bits!"
#endif
/* Flash Accelerator Configuration -------------------------------------------*/
#if (CHECK_RSVD((FLASHCFG_Val), ~0x0000F07F))
#error "FLASHCFG: Invalid values of reserved bits!"
#endif
/*----------------------------------------------------------------------------
DEFINES
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
Define clocks
*----------------------------------------------------------------------------*/
#define XTAL (12000000UL) /* Oscillator frequency */
#define OSC_CLK ( XTAL) /* Main oscillator frequency */
#define RTC_CLK ( 32000UL) /* RTC oscillator frequency */
#define IRC_OSC ( 4000000UL) /* Internal RC oscillator frequency */
/* F_cco0 = (2 * M * F_in) / N */
#define __M (((PLL0CFG_Val ) & 0x7FFF) + 1)
#define __N (((PLL0CFG_Val >> 16) & 0x00FF) + 1)
#define __FCCO(__F_IN) ((2ULL * __M * __F_IN) / __N)
#define __CCLK_DIV (((CCLKCFG_Val ) & 0x00FF) + 1)
/* Determine core clock frequency according to settings */
#if (PLL0_SETUP)
#if ((CLKSRCSEL_Val & 0x03) == 1)
#define __CORE_CLK (__FCCO(OSC_CLK) / __CCLK_DIV)
#elif ((CLKSRCSEL_Val & 0x03) == 2)
#define __CORE_CLK (__FCCO(RTC_CLK) / __CCLK_DIV)
#else
#define __CORE_CLK (__FCCO(IRC_OSC) / __CCLK_DIV)
#endif
#else
#if ((CLKSRCSEL_Val & 0x03) == 1)
#define __CORE_CLK (OSC_CLK / __CCLK_DIV)
#elif ((CLKSRCSEL_Val & 0x03) == 2)
#define __CORE_CLK (RTC_CLK / __CCLK_DIV)
#else
#define __CORE_CLK (IRC_OSC / __CCLK_DIV)
#endif
#endif
/**
* @}
*/
/** @addtogroup LPC17xx_System_Public_Variables LPC17xx System Public Variables
@{
*/
/*----------------------------------------------------------------------------
Clock Variable definitions
*----------------------------------------------------------------------------*/
uint32_t SystemCoreClock = __CORE_CLK;/*!< System Clock Frequency (Core Clock)*/
/**
* @}
*/
/** @addtogroup LPC17xx_System_Public_Functions LPC17xx System Public Functions
@{
*/
/**
* Update SystemCoreClock variable
*
* @param none
* @return none
*
* @brief Updates the SystemCoreClock with current core Clock
* retrieved from cpu registers.
*/void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */
{
/* Determine clock frequency according to clock register values */
if (((LPC_SC->PLL0STAT >> 24) & 3) == 3) { /* If PLL0 enabled and connected */
switch (LPC_SC->CLKSRCSEL & 0x03) {
case 0: /* Int. RC oscillator => PLL0 */
case 3: /* Reserved, default to Int. RC */
SystemCoreClock = (IRC_OSC *
((2ULL * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1) /
((LPC_SC->CCLKCFG & 0xFF)+ 1));
break;
case 1: /* Main oscillator => PLL0 */
SystemCoreClock = (OSC_CLK *
((2ULL * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1) /
((LPC_SC->CCLKCFG & 0xFF)+ 1));
break;
case 2: /* RTC oscillator => PLL0 */
SystemCoreClock = (RTC_CLK *
((2ULL * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1) /
((LPC_SC->CCLKCFG & 0xFF)+ 1));
break;
}
} else {
switch (LPC_SC->CLKSRCSEL & 0x03) {
case 0: /* Int. RC oscillator => PLL0 */
case 3: /* Reserved, default to Int. RC */
SystemCoreClock = IRC_OSC / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
break;
case 1: /* Main oscillator => PLL0 */
SystemCoreClock = OSC_CLK / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
break;
case 2: /* RTC oscillator => PLL0 */
SystemCoreClock = RTC_CLK / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
break;
}
}
}
/**
* Initialize the system
*
* @param none
* @return none
*
* @brief Setup the microcontroller system.
* Initialize the System.
*/
void SystemInit (void)
{
#if (CLOCK_SETUP) /* Clock Setup */
LPC_SC->SCS = SCS_Val;
if (LPC_SC->SCS & (1 << 5)) { /* If Main Oscillator is enabled */
while ((LPC_SC->SCS & (1<<6)) == 0);/* Wait for Oscillator to be ready */
}
LPC_SC->CCLKCFG = CCLKCFG_Val; /* Setup Clock Divider */
/* Periphral clock must be selected before PLL0 enabling and connecting
* - according errata.lpc1768-16.March.2010 -
*/
LPC_SC->PCLKSEL0 = PCLKSEL0_Val; /* Peripheral Clock Selection */
LPC_SC->PCLKSEL1 = PCLKSEL1_Val;
#if (PLL0_SETUP)
LPC_SC->CLKSRCSEL = CLKSRCSEL_Val; /* Select Clock Source for PLL0 */
LPC_SC->PLL0CFG = PLL0CFG_Val; /* configure PLL0 */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
LPC_SC->PLL0CON = 0x01; /* PLL0 Enable */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0 */
LPC_SC->PLL0CON = 0x03; /* PLL0 Enable & Connect */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
while (!(LPC_SC->PLL0STAT & ((1<<25) | (1<<24))));/* Wait for PLLC0_STAT & PLLE0_STAT */
#endif
#if (PLL1_SETUP)
LPC_SC->PLL1CFG = PLL1CFG_Val;
LPC_SC->PLL1FEED = 0xAA;
LPC_SC->PLL1FEED = 0x55;
LPC_SC->PLL1CON = 0x01; /* PLL1 Enable */
LPC_SC->PLL1FEED = 0xAA;
LPC_SC->PLL1FEED = 0x55;
while (!(LPC_SC->PLL1STAT & (1<<10)));/* Wait for PLOCK1 */
LPC_SC->PLL1CON = 0x03; /* PLL1 Enable & Connect */
LPC_SC->PLL1FEED = 0xAA;
LPC_SC->PLL1FEED = 0x55;
while (!(LPC_SC->PLL1STAT & ((1<< 9) | (1<< 8))));/* Wait for PLLC1_STAT & PLLE1_STAT */
#else
LPC_SC->USBCLKCFG = USBCLKCFG_Val; /* Setup USB Clock Divider */
#endif
LPC_SC->PCONP = PCONP_Val; /* Power Control for Peripherals */
LPC_SC->CLKOUTCFG = CLKOUTCFG_Val; /* Clock Output Configuration */
#endif
#if (FLASH_SETUP == 1) /* Flash Accelerator Setup */
LPC_SC->FLASHCFG = (LPC_SC->FLASHCFG & ~0x0000F000) | FLASHCFG_Val;
#endif
}
/**
* @}
*/
/**
* @}
*/

View File

@@ -0,0 +1,60 @@
/******************************************************************************
* @file: system_LPC17xx.h
* @purpose: CMSIS Cortex-M3 Device Peripheral Access Layer Header File
* for the NXP LPC17xx Device Series
* @version: V1.02
* @date: 27. July 2009
*----------------------------------------------------------------------------
*
* Copyright (C) 2009 ARM Limited. All rights reserved.
*
* ARM Limited (ARM) is supplying this software for use with Cortex-M3
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __SYSTEM_LPC17xx_H
#define __SYSTEM_LPC17xx_H
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
/**
* Initialize the system
*
* @param none
* @return none
*
* @brief Setup the microcontroller system.
* Initialize the System and update the SystemCoreClock variable.
*/
extern void SystemInit (void);
/**
* Update SystemCoreClock variable
*
* @param none
* @return none
*
* @brief Updates the SystemCoreClock with current core Clock
* retrieved from cpu registers.
*/
extern void SystemCoreClockUpdate (void);
#ifdef __cplusplus
}
#endif
#endif /* __SYSTEM_LPC17xx_H */

35
lib/lpc176x/lpc176x.patch Normal file
View File

@@ -0,0 +1,35 @@
--- device/system_LPC17xx.c 2018-05-02 12:23:57.292132454 -0400
+++ device/system_LPC17xx.c 2021-05-04 10:08:17.637502030 -0400
@@ -297,22 +297,19 @@
#define CLKSRCSEL_Val 0x00000001
#define PLL0_SETUP 1
-#ifdef MCB1700
-# define PLL0CFG_Val 0x00050063
-# define PLL1_SETUP 1
-# define PLL1CFG_Val 0x00000023
-# define CCLKCFG_Val 0x00000003
-# define USBCLKCFG_Val 0x00000000
+#include "autoconf.h" // CONFIG_MACH_LPC1769
+#if CONFIG_MACH_LPC1769
+# define PLL0CFG_Val 0x0000000E
#else
-# define PLL0CFG_Val 0x0000000B
-# define PLL1_SETUP 0
-# define PLL1CFG_Val 0x00000000
-# define CCLKCFG_Val 0x00000002
-# define USBCLKCFG_Val 0x00000005
+# define PLL0CFG_Val 0x00010018
#endif
+#define PLL1_SETUP 1
+#define PLL1CFG_Val 0x00000023
+#define CCLKCFG_Val 0x00000002
+#define USBCLKCFG_Val 0x00000000
-#define PCLKSEL0_Val 0x00000000
-#define PCLKSEL1_Val 0x00000000
+#define PCLKSEL0_Val 0x55515155
+#define PCLKSEL1_Val 0x54555455
#define PCONP_Val 0x042887DE
#define CLKOUTCFG_Val 0x00000000

View File

@@ -0,0 +1,25 @@
Programmable Real-time Unit (PRU) Software Support Package
------------------------------------------------------------
============================================================
INCLUDE
============================================================
DESCRIPTION
This directory provides header files for PRU firmware.
For more details about these header files, visit:
http://processors.wiki.ti.com/index.php/PRU-ICSS_Header_Files
ADDITIONAL RESOURCES
For more information about the PRU, visit:
PRU-ICSS Wiki - http://processors.wiki.ti.com/index.php/PRU-ICSS
PRU Training Slides - http://www.ti.com/sitarabootcamp
PRU Evaluation Hardware - http://www.ti.com/tool/PRUCAPE
Support - http://e2e.ti.com

View File

@@ -0,0 +1,249 @@
/*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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.
*/
#ifndef _PRU_CFG_H_
#define _PRU_CFG_H_
/* PRU_CFG register set */
typedef struct {
/* PRU_CFG_REVID register bit field */
union {
volatile uint32_t REVID;
volatile struct {
unsigned REVID : 32;
} REVID_bit;
}; // 0x0
/* PRU_CFG_SYSCFG register bit field */
union {
volatile uint32_t SYSCFG;
volatile struct {
unsigned IDLE_MODE : 2;
unsigned STANDBY_MODE : 2;
unsigned STANDBY_INIT : 1;
unsigned SUB_MWAIT : 1;
unsigned rsvd6 : 26;
} SYSCFG_bit;
}; // 0x4
/* PRU_CFG_GPCFG0 register bit field */
union {
volatile uint32_t GPCFG0;
volatile struct {
unsigned PRU0_GPI_MODE : 2; // 1:0
unsigned PRU0_GPI_CLK_MODE : 1; // 2
unsigned PRU0_GPI_DIV0 : 5; // 7:3
unsigned PRU0_GPI_DIV1 : 5; // 12:8
unsigned PRU0_GPI_SB : 1; // 13
unsigned PRU0_GPO_MODE : 1; // 14
unsigned PRU0_GPO_DIV0 : 5; // 19:15
unsigned PRU0_GPO_DIV1 : 5; // 24:20
unsigned PRU0_GPO_SH_SEL : 1; // 25
unsigned rsvd26 : 6; // 31:26
} GPCFG0_bit;
}; // 0x8
/* PRU_CFG_GPCFG1 register bit field */
union {
volatile uint32_t GPCFG1;
volatile struct {
unsigned PRU1_GPI_MODE : 2; // 1:0
unsigned PRU1_GPI_CLK_MODE : 1; // 2
unsigned PRU1_GPI_DIV0 : 5; // 7:3
unsigned PRU1_GPI_DIV1 : 5; // 12:8
unsigned PRU1_GPI_SB : 1; // 13
unsigned PRU1_GPO_MODE : 1; // 14
unsigned PRU1_GPO_DIV0 : 5; // 19:15
unsigned PRU1_GPO_DIV1 : 5; // 24:20
unsigned PRU1_GPO_SH_SEL : 1; // 25
unsigned rsvd26 : 6; // 31:26
} GPCFG1_bit;
}; // 0xC
/* PRU_CFG_CGR register bit field */
union {
volatile uint32_t CGR;
volatile struct {
unsigned PRU0_CLK_STOP_REQ : 1; // 0
unsigned PRU0_CLK_STOP_ACK : 1; // 1
unsigned PRU0_CLK_EN : 1; // 2
unsigned PRU1_CLK_STOP_REQ : 1; // 3
unsigned PRU1_CLK_STOP_ACK : 1; // 4
unsigned PRU1_CLK_EN : 1; // 5
unsigned INTC_CLK_STOP_REQ : 1; // 6
unsigned INTC_CLK_STOP_ACK : 1; // 7
unsigned INTC_CLK_EN : 1; // 8
unsigned UART_CLK_STOP_REQ : 1; // 9
unsigned UART_CLK_STOP_ACK : 1; // 10
unsigned UART_CLK_EN : 1; // 11
unsigned ECAP_CLK_STOP_REQ : 1; // 12
unsigned ECAP_CLK_STOP_ACK : 1; // 13
unsigned ECAP_CLK_EN : 1; // 14
unsigned IEP_CLK_STOP_REQ : 1; // 15
unsigned IEP_CLK_STOP_ACK : 1; // 16
unsigned IEP_CLK_EN : 1; // 17
unsigned rsvd18 : 14; // 31:18
} CGR_bit;
}; // 0x10
/* PRU_CFG_ISRP register bit field */
union {
volatile uint32_t ISRP;
volatile struct {
unsigned PRU0_IMEM_PE_RAW : 4; // 3:0
unsigned PRU0_DMEM_PE_RAW : 4; // 7:4
unsigned PRU1_IMEM_PE_RAW : 4; // 11:8
unsigned PRU1_DMEM_PE_RAW : 4; // 15:12
unsigned RAM_PE_RAW : 4; // 19:16
unsigned rsvd20 : 12; // 31:20
} ISRP_bit;
}; // 0x14
/* PRU_CFG_ISP register bit field */
union {
volatile uint32_t ISP;
volatile struct {
unsigned PRU0_IMEM_PE : 4; // 3:0
unsigned PRU0_DMEM_PE : 4; // 7:4
unsigned PRU1_IMEM_PE : 4; // 11:8
unsigned PRU1_DMEM_PE : 4; // 15:12
unsigned RAM_PE : 4; // 19:16
unsigned rsvd20 : 12; // 31:20
} ISP_bit;
}; // 0x18
/* PRU_CFG_IESP register bit field */
union {
volatile uint32_t IESP;
volatile struct {
unsigned PRU0_IMEM_PE_SET : 4; // 3:0
unsigned PRU0_DMEM_PE_SET : 4; // 7:4
unsigned PRU1_IMEM_PE_SET : 4; // 11:8
unsigned PRU1_DMEM_PE_SET : 4; // 15:12
unsigned RAM_PE_SET : 4; // 19:16
unsigned rsvd20 : 12; // 31:20
} IESP_bit;
}; // 0x1C
/* PRU_CFG_IECP register bit field */
union {
volatile uint32_t IECP;
volatile struct {
unsigned PRU0_IMEM_PE_CLR : 4; // 3:0
unsigned PRU0_DMEM_PE_CLR : 4; // 7:4
unsigned PRU1_IMEM_PE_CLR : 4; // 11:8
unsigned PRU1_DMEM_PE_CLR : 4; // 15:12
unsigned rsvd16 : 16; // 31:16
} IECP_bit;
}; // 0x20
uint32_t rsvd24; // 0x24
/* PRU_CFG_PMAO register bit field */
union {
volatile uint32_t PMAO;
volatile struct {
unsigned PMAO_PRU0 : 1; // 0
unsigned PMAO_PRU1 : 1; // 1
unsigned rsvd2 : 30; // 31:2
} PMAO_bit;
}; // 0x28
uint32_t rsvd2c[1]; // 0x2C
/* PRU_CFG_IEPCLK register bit field */
union {
volatile uint32_t IEPCLK;
volatile struct {
unsigned OCP_EN : 1; // 0
unsigned rsvd1 : 31; // 31:1
} IEPCLK_bit;
}; // 0x30
/* PRU_CFG_SPP register bit field */
union {
volatile uint32_t SPP;
volatile struct {
unsigned PRU1_PAD_HP_EN : 1; // 0
unsigned XFR_SHIFT_EN : 1; // 1
unsigned rsvd2 : 30; // 31:2
} SPP_bit;
}; // 0x34
uint32_t rsvd38[2]; // 0x38 - 0x3C
union {
volatile uint32_t PIN_MX;
volatile struct {
unsigned PIN_MUX_SEL : 8; // 7:0
unsigned rsvd2 : 24; // 31:8
} PIN_MX_bit;
}; //0x40
} pruCfg;
#ifdef __GNUC__
static volatile pruCfg *__CT_CFG = (void *)0x00026000;
#define CT_CFG (*__CT_CFG)
#else
volatile __far pruCfg CT_CFG __attribute__((cregister("PRU_CFG", near), peripheral));
#endif
#endif /* _PRU_CFG_H_ */

View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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.
*/
#ifndef _PRU_CTRL_H_
#define _PRU_CTRL_H_
/* PRU_CTRL register set */
typedef struct {
/* PRU_CTRL_CTRL register bit field */
union {
volatile uint32_t CTRL;
volatile struct {
unsigned SOFT_RST_N : 1;
unsigned EN : 1;
unsigned SLEEPING : 1;
unsigned CTR_EN : 1;
unsigned rsvd4 : 4;
unsigned SINGLE_STEP : 1;
unsigned rsvd9 : 6;
unsigned RUNSTATE : 1;
unsigned PCTR_RST_VAL : 16;
} CTRL_bit;
}; // 0x0
/* PRU_CTRL_STS register bit field */
union {
volatile uint32_t STS;
volatile struct {
unsigned PCTR : 16;
unsigned rsvd16 : 16;
} STS_bit;
}; // 0x4
/* PRU_CTRL_WAKEUP_EN register bit field */
union {
volatile uint32_t WAKEUP_EN;
volatile struct {
unsigned BITWISE_ENS : 32;
} WAKEUP_EN_bit;
}; // 0x8
/* PRU_CTRL_CYCLE register bit field */
union {
volatile uint32_t CYCLE;
volatile struct {
unsigned CYCLECOUNT : 32;
} CYCLE_bit;
}; // 0xC
/* PRU_CTRL_STALL register bit field */
union {
volatile uint32_t STALL;
volatile struct {
unsigned STALLCOUNT : 32;
} STALL_bit;
}; // 0x10
uint32_t rsvd14[3]; // 0x14 - 0x1C
/* PRU_CTRL_CTBIR0 register bit field */
union {
volatile uint32_t CTBIR0;
volatile struct {
unsigned C24_BLK_IDX : 8;
unsigned rsvd8 : 8;
unsigned C25_BLK_IDX : 8;
unsigned rsvd24 : 8;
} CTBIR0_bit;
}; // 0x20
/* PRU_CTRL_CTBIR1 register bit field */
union {
volatile uint32_t CTBIR1;
volatile struct {
unsigned C26_BLK_IDX : 8;
unsigned rsvd8 : 8;
unsigned C27_BLK_IDX : 8;
unsigned rsvd24 : 8;
} CTBIR1_bit;
}; // 0x24
/* PRU_CTRL_CTPPR0 register bit field */
union {
volatile uint32_t CTPPR0;
volatile struct {
unsigned C28_BLK_POINTER : 16;
unsigned C29_BLK_POINTER : 16;
} CTPPR0_bit;
}; // 0x28
/* PRU_CTRL_CTPPR1 register bit field */
union {
volatile uint32_t CTPPR1;
volatile struct {
unsigned C30_BLK_POINTER : 16;
unsigned C31_BLK_POINTER : 16;
} CTPPR1_bit;
}; // 0x2C
} pruCtrl;
/* Definition of control register structures. */
#define PRU0_CTRL (*((volatile pruCtrl*)0x22000))
#define PRU1_CTRL (*((volatile pruCtrl*)0x24000))
#endif /* _PRU_CTRL_H_ */

View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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.
*/
#ifndef _PRU_ECAP_H_
#define _PRU_ECAP_H_
/* PRU_ECAP register set */
typedef struct {
/* PRU_ECAP_TSCTR register bit field */
union {
volatile uint32_t TSCTR;
volatile struct {
unsigned TSCTR : 32; //31:0
} TSCTR_bit;
}; // 0x0
/* PRU_ECAP_CTRPHS register bit field */
union {
volatile uint32_t CTRPHS;
volatile struct {
unsigned CTRPHS : 32; //31:0
} CTRPHS_bit;
}; // 0x4
/* PRU_ECAP_CAP1 register bit field */
union {
volatile uint32_t CAP1;
volatile struct {
unsigned CAP1 : 32; //31:0
} CAP1_bit;
}; // 0x8
/* PRU_ECAP_CAP2 register bit field */
union {
volatile uint32_t CAP2;
volatile struct {
unsigned CAP2 : 32; //31:0
} CAP2_bit;
}; // 0xC
/* PRU_ECAP_CAP3 register bit field */
union {
volatile uint32_t CAP3;
volatile struct {
unsigned CAP3 : 32; //31:0
} CAP3_bit;
}; // 0x10
/* PRU_ECAP_CAP4 register bit field */
union {
volatile uint32_t CAP4;
volatile struct {
unsigned CAP4 : 32; //31:0
} CAP4_bit;
}; // 0x14
uint32_t rsvd118[4]; // 0x118 - 0x124
/* PRU_ECAP_ECCTL1 register bit field */
volatile uint16_t ECCTL1; // 0x28
/* PRU_ECAP_ECCTL2 register bit field */
volatile uint16_t ECCTL2; // 0x2A
/* PRU_ECAP_ECEINT register bit field */
volatile uint16_t ECEINT; // 0x2C
/* PRU_ECAP_ECFLG register bit field */
volatile uint16_t ECFLG; // 0x2E
/* PRU_ECAP_ECCLR register bit field */
volatile uint16_t ECCLR; // 0x30
/* PRU_ECAP_ECFRC register bit field */
volatile uint16_t ECFRC; // 0x32
uint32_t rsvd34[10]; // 0x34 - 0x58
/* PRU_ECAP_REVID register bit field */
union {
volatile uint32_t REVID;
volatile struct {
unsigned REV : 32; //31:0
} REVID_bit;
}; // 0x5C
} pruEcap;
volatile __far pruEcap CT_ECAP __attribute__((cregister("PRU_ECAP", near), peripheral));
#endif /* _PRU_ECAP_H_ */

View File

@@ -0,0 +1,261 @@
/*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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.
*/
#ifndef _PRU_IEP_H_
#define _PRU_IEP_H_
/* PRU IEP register set */
typedef struct {
/* PRU_IEP_TMR_GLB_CFG register bit field */
union {
volatile uint32_t TMR_GLB_CFG;
volatile struct {
unsigned CNT_EN : 1; // 0
unsigned rsvd1 : 3; // 3:1
unsigned DEFAULT_INC : 4; // 7:4
unsigned CMP_INC : 12; // 19:8
unsigned rsvd12 : 12; // 31:20
} TMR_GLB_CFG_bit;
}; // 0x0
/* PRU_IEP_TMR_GLB_STS register bit field */
union {
volatile uint32_t TMR_GLB_STS;
volatile struct {
unsigned CNT_OVF : 1; // 0
unsigned rsvd1 : 31; // 31:1
} TMR_GLB_STS_bit;
}; // 0x4
/* PRU_IEP_TMR_COMPEN register bit field */
union {
volatile uint32_t TMR_COMPEN;
volatile struct {
unsigned COMPEN_CNT : 24; // 23:0
unsigned rsvd24 : 8; // 31:24
} TMR_COMPEN_bit;
}; // 0x8
/* PRU_IEP_TMR_CNT register bit field */
union {
volatile uint32_t TMR_CNT;
volatile struct {
unsigned COUNT : 32; // 31:0
} TMR_CNT_bit;
}; // 0xC
uint32_t rsvd10[12]; // 0x10 - 0x3C
/* PRU_IEP_TMR_CMP_CFG register bit field */
union {
volatile uint32_t TMR_CMP_CFG;
volatile struct {
unsigned CMP0_RST_CNT_EN : 1; // 0
unsigned CMP_EN : 8; // 8:1
unsigned rsvd9 : 23; // 31:9
} TMR_CMP_CFG_bit;
}; // 0x40
/* PRU_IEP_TMR_CMP_STS register bit field */
union {
volatile uint32_t TMR_CMP_STS;
volatile struct {
unsigned CMP_HIT : 8; // 7:0
unsigned rsvd8 : 24; // 31:8
} TMR_CMP_STS_bit;
}; // 0x44
/* PRU_IEP_TMR_CMP0 register bit field */
union {
volatile uint32_t TMR_CMP0;
volatile struct {
unsigned CMP0 : 32; // 31:0
} TMR_CMP0_bit;
}; // 0x48
/* PRU_IEP_TMR_CMP1 register bit field */
union {
volatile uint32_t TMR_CMP1;
volatile struct {
unsigned CMP1 : 32; // 31:0
} TMR_CMP1_bit;
}; // 0x4C
/* PRU_IEP_TMR_CMP2 register bit field */
union {
volatile uint32_t TMR_CMP2;
volatile struct {
unsigned CMP2 : 32; // 31:0
} TMR_CMP2_bit;
}; // 0x50
/* PRU_IEP_TMR_CMP3 register bit field */
union {
volatile uint32_t TMR_CMP3;
volatile struct {
unsigned CMP3 : 32; // 31:0
} TMR_CMP3_bit;
}; // 0x54
/* PRU_IEP_TMR_CMP4 register bit field */
union {
volatile uint32_t TMR_CMP4;
volatile struct {
unsigned CMP4 : 32; // 31:0
} TMR_CMP4_bit;
}; // 0x58
/* PRU_IEP_TMR_CMP5 register bit field */
union {
volatile uint32_t TMR_CMP5;
volatile struct {
unsigned CMP5 : 32; // 31:0
} TMR_CMP5_bit;
}; // 0x5C
/* PRU_IEP_TMR_CMP6 register bit field */
union {
volatile uint32_t TMR_CMP6;
volatile struct {
unsigned CMP6 : 32; // 31:0
} TMR_CMP6_bit;
}; // 0x60
/* PRU_IEP_TMR_CMP7 register bit field */
union {
volatile uint32_t TMR_CMP7;
volatile struct {
unsigned CMP7 : 32; // 31:0
} TMR_CMP7_bit;
}; // 0x64
uint32_t rsvd68[166]; // 0x68 - 0x2FF
/* PRU_IEP_DIGIO_CTRL register bit field */
union {
volatile uint32_t DIGIO_CTRL;
volatile struct {
unsigned RESERVED0 : 4; // 3:0
unsigned IN_MODE : 1; // 4
unsigned RESERVED5 : 27; // 31:5
} DIGIO_CTRL_bit;
}; // 0x300
uint32_t rsvd304[1]; // 0x304
/* PRU_IEP_DIGIO_DATA_IN register bit field */
union {
volatile uint32_t DIGIO_DATA_IN;
volatile struct {
unsigned DATA_IN : 32; // 31:0
} DIGIO_DATA_IN_bit;
}; // 0x308
/* PRU_IEP_DIGIO_DATA_IN_RAW register bit field */
union {
volatile uint32_t DIGIO_DATA_IN_RAW;
volatile struct {
unsigned DATA_IN_RAW : 32; // 31:0
} DIGIO_DATA_IN_RAW_bit;
}; // 0x30C
/* PRU_IEP_DIGIO_DATA_OUT register bit field */
union {
volatile uint32_t DIGIO_DATA_OUT;
volatile struct {
unsigned DATA_OUT : 32; // 31:0
} DIGIO_DATA_OUT_bit;
}; // 0x310
/* PRU_IEP_DIGIO_DATA_OUT_EN register bit field */
union {
volatile uint32_t DIGIO_DATA_OUT_EN;
volatile struct {
unsigned DATA_OUT_EN : 32; // 31:0
} DIGIO_DATA_OUT_EN_bit;
}; // 0x314
/* PRU_IEP_DIGIO_EXP register bit field */
union {
volatile uint32_t DIGIO_EXP;
volatile struct {
unsigned SW_DATA_OUT_UPDATE : 1; // 0
unsigned OUTVALID_OVR_EN : 1; // 1
unsigned RESERVED2 : 30; // 31:2
} DIGIO_EXP_bit;
}; // 0x318
} pruIep;
#ifdef __GNUC__
static volatile pruIep *__CT_IEP = (void *)0x0002e000;
#define CT_IEP (*__CT_IEP)
#else
volatile __far pruIep CT_IEP __attribute__((cregister("PRU_IEP", far), peripheral));
#endif
#endif /* _PRU_IEP_H_ */

View File

@@ -0,0 +1,912 @@
/*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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.
*/
#ifndef _PRU_INTC_H_
#define _PRU_INTC_H_
/* PRU INTC register set */
typedef struct {
/* PRU_INTC_REVID register bit field */
union {
volatile uint32_t REVID;
volatile struct {
unsigned REV_MINOR : 6; // 5:0
unsigned REV_CUSTOM : 2; // 7:6
unsigned REV_MAJOR : 3; // 10:8
unsigned REV_RTL : 5; // 15:11
unsigned REV_MODULE : 12; // 27:16
unsigned rsvd28 : 2; // 29:28
unsigned REV_SCHEME : 2; // 31:30
} REVID_bit;
}; // 0x0
/* PRU_INTC_CR register bit field */
union {
volatile uint32_t CR;
volatile struct {
unsigned rsvd0 : 2; // 1:0
unsigned NEST_MODE : 2; // 3:2
unsigned rsvd4 : 28; // 31:4
} CR_bit;
}; // 0x4
uint32_t rsvd8[2]; // 0x8 - 0xC
/* PRU_INTC_GER register bit field */
union {
volatile uint32_t GER;
volatile struct {
unsigned EN_HINT_ANY : 1; // 0
unsigned rsvd1 : 31; // 31:1
} GER_bit;
}; // 0x10
uint32_t rsvd14[2]; // 0x14 - 0x18
/* PRU_INTC_GNLR register bit field */
union {
volatile uint32_t GNLR;
volatile struct {
unsigned GLB_NEST_LEVEL : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} GNLR_bit;
}; // 0x1C
/* PRU_INTC_SISR register bit field */
union {
volatile uint32_t SISR;
volatile struct {
unsigned STS_SET_IDX : 10; // 9:0
unsigned rsvd10 : 22; // 31:10
} SISR_bit;
}; // 0x20
/* PRU_INTC_SICR register bit field */
union {
volatile uint32_t SICR;
volatile struct {
unsigned STS_CLR_IDX : 10; // 9:0
unsigned rsvd10 : 22; // 31:10
} SICR_bit;
}; // 0x24
/* PRU_INTC_EISR register bit field */
union {
volatile uint32_t EISR;
volatile struct {
unsigned EN_SET_IDX : 10; // 9:0
unsigned rsvd10 : 22; // 31:10
} EISR_bit;
}; // 0x28
/* PRU_INTC_EICR register bit field */
union {
volatile uint32_t EICR;
volatile struct {
unsigned EN_CLR_IDX : 10; // 9:0
unsigned rsvd10 : 22; // 31:10
} EICR_bit;
}; // 0x2C
uint32_t rsvd30; // 0x30
/* PRU_INTC_HIEISR register bit field */
union {
volatile uint32_t HIEISR;
volatile struct {
unsigned HINT_EN_SET_IDX : 4; // 3:0
unsigned rsvd4 : 28; // 31:4
} HIEISR_bit;
}; // 0x34
/* PRU_INTC_HIDISR register bit field */
union {
volatile uint32_t HIDISR;
volatile struct {
unsigned HINT_EN_CLR_IDX : 4; // 3:0
unsigned rsvd4 : 28; // 31:4
} HIDISR_bit;
}; // 0x38
uint32_t rsvd3C[17]; // 0x3C - 0x7C
/* PRU_INTC_GPIR register bit field */
union {
volatile uint32_t GPIR;
volatile struct {
unsigned GLB_PRI_INTR : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned GLB_NONE : 1; // 31
} GPIR_bit;
}; // 0x80
uint32_t rsvd84[95]; // 0x84 - 0x1FC
/* PRU_INTC_SRSR0 register bit field */
union {
volatile uint32_t SRSR0;
volatile struct {
unsigned RAW_STS_31_0 : 32; // 31:0
} SRSR0_bit;
}; // 0x200
/* PRU_INTC_SRSR1 register bit field */
union {
volatile uint32_t SRSR1;
volatile struct {
unsigned RAW_STS_63_32 : 32; // 31:0
} SRSR1_bit;
}; // 0x204
uint32_t rsvd208[30]; // 0x208 - 0x27C
/* PRU_INTC_SECR0 register bit field */
union {
volatile uint32_t SECR0;
volatile struct {
unsigned ENA_STS_31_0 : 32; // 31:0
} SECR0_bit;
}; // 0x280
/* PRU_INTC_SECR1 register bit field */
union {
volatile uint32_t SECR1;
volatile struct {
unsigned ENA_STS_63_32 : 32; // 31:0
} SECR1_bit;
}; // 0x284
uint32_t rsvd288[30]; // 0x288 - 0x2FC
/* PRU_INTC_ESR0 register bit field */
union {
volatile uint32_t ESR0;
volatile struct {
unsigned EN_SET_31_0 : 32; // 31:0
} ESR0_bit;
}; // 0x300
/* PRU_INTC_ESR1 register bit field */
union {
volatile uint32_t ESR1;
volatile struct {
unsigned EN_SET_63_32 : 32; // 31:0
} ESR1_bit;
}; // 0x304
uint32_t rsvd308[30]; // 0x308 - 0x37C
/* PRU_INTC_ECR0 register bit field */
union {
volatile uint32_t ECR0;
volatile struct {
unsigned EN_CLR_31_0 : 32; // 31:0
} ECR0_bit;
}; // 0x380
/* PRU_INTC_ECR1 register bit field */
union {
volatile uint32_t ECR1;
volatile struct {
unsigned EN_CLR_63_32 : 32; // 31:0
} ECR1_bit;
}; // 0x384
uint32_t rsvd388[30]; // 0x388 - 0x3FC
/* PRU_INTC_CMR0 register bit field */
union {
volatile uint32_t CMR0;
volatile struct {
unsigned CH_MAP_0 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_1 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_2 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_3 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR0_bit;
}; // 0x400
/* PRU_INTC_CMR1 register bit field */
union {
volatile uint32_t CMR1;
volatile struct {
unsigned CH_MAP_4 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_5 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_6 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_7 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR1_bit;
}; // 0x404
/* PRU_INTC_CMR2 register bit field */
union {
volatile uint32_t CMR2;
volatile struct {
unsigned CH_MAP_8 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_9 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_10 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_11 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR2_bit;
}; // 0x408
/* PRU_INTC_CMR3 register bit field */
union {
volatile uint32_t CMR3;
volatile struct {
unsigned CH_MAP_12 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_13 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_14 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_15 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR3_bit;
}; // 0x40C
/* PRU_INTC_CMR4 register bit field */
union {
volatile uint32_t CMR4;
volatile struct {
unsigned CH_MAP_16 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_17 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_18 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_19 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR4_bit;
}; // 0x410
/* PRU_INTC_CMR5 register bit field */
union {
volatile uint32_t CMR5;
volatile struct {
unsigned CH_MAP_20 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_21 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_22 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_23 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR5_bit;
}; // 0x414
/* PRU_INTC_CMR6 register bit field */
union {
volatile uint32_t CMR6;
volatile struct {
unsigned CH_MAP_24 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_25 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_26 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_27 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR6_bit;
}; // 0x418
/* PRU_INTC_CMR7 register bit field */
union {
volatile uint32_t CMR7;
volatile struct {
unsigned CH_MAP_28 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_29 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_30 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_31 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR7_bit;
}; // 0x41C
/* PRU_INTC_CMR8 register bit field */
union {
volatile uint32_t CMR8;
volatile struct {
unsigned CH_MAP_32 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_33 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_34 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_35 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR8_bit;
}; // 0x420
/* PRU_INTC_CMR9 register bit field */
union {
volatile uint32_t CMR9;
volatile struct {
unsigned CH_MAP_36 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_37 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_38 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_39 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR9_bit;
}; // 0x424
/* PRU_INTC_CMR10 register bit field */
union {
volatile uint32_t CMR10;
volatile struct {
unsigned CH_MAP_40 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_41 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_42 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_43 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR10_bit;
}; // 0x428
/* PRU_INTC_CMR11 register bit field */
union {
volatile uint32_t CMR11;
volatile struct {
unsigned CH_MAP_44 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_45 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_46 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_47 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR11_bit;
}; // 0x42C
/* PRU_INTC_CMR12 register bit field */
union {
volatile uint32_t CMR12;
volatile struct {
unsigned CH_MAP_48 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_49 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_50 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_51 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR12_bit;
}; // 0x430
/* PRU_INTC_CMR13 register bit field */
union {
volatile uint32_t CMR13;
volatile struct {
unsigned CH_MAP_52 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_53 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_54 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_55 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR13_bit;
}; // 0x434
/* PRU_INTC_CMR14 register bit field */
union {
volatile uint32_t CMR14;
volatile struct {
unsigned CH_MAP_56 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_57 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_58 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_59 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR14_bit;
}; // 0x438
/* PRU_INTC_CMR15 register bit field */
union {
volatile uint32_t CMR15;
volatile struct {
unsigned CH_MAP_60 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned CH_MAP_61 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned CH_MAP_62 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned CH_MAP_63 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} CMR15_bit;
}; // 0x43C
uint32_t rsvd440[240]; // 0x440 - 0x7FC
/* PRU_INTC_HMR0 register bit field */
union {
volatile uint32_t HMR0;
volatile struct {
unsigned HINT_MAP_0 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned HINT_MAP_1 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned HINT_MAP_2 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned HINT_MAP_3 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} HMR0_bit;
}; // 0x800
/* PRU_INTC_HMR1 register bit field */
union {
volatile uint32_t HMR1;
volatile struct {
unsigned HINT_MAP_4 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned HINT_MAP_5 : 4; // 11:8
unsigned rsvd12 : 4; // 15:12
unsigned HINT_MAP_6 : 4; // 19:16
unsigned rsvd20 : 4; // 23:20
unsigned HINT_MAP_7 : 4; // 27:24
unsigned rsvd28 : 4; // 31:28
} HMR1_bit;
}; // 0x804
/* PRU_INTC_HMR2 register bit field */
union {
volatile uint32_t HMR2;
volatile struct {
unsigned HINT_MAP_8 : 4; // 3:0
unsigned rsvd4 : 4; // 7:4
unsigned HINT_MAP_9 : 4; // 11:8
unsigned rsvd12 : 20; // 31:12
} HMR2_bit;
}; // 0x808
uint32_t rsvd80C[61]; // 0x80C - 0x8FC
/* PRU_INTC_HIPIR0 register bit field */
union {
volatile uint32_t HIPIR0;
volatile struct {
unsigned PRI_HINT_0 : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned NONE_HINT_0 : 1; // 31
} HIPIR0_bit;
}; // 0x900
/* PRU_INTC_HIPIR1 register bit field */
union {
volatile uint32_t HIPIR1;
volatile struct {
unsigned PRI_HINT_1 : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned NONE_HINT_1 : 1; // 31
} HIPIR1_bit;
}; // 0x904
/* PRU_INTC_HIPIR2 register bit field */
union {
volatile uint32_t HIPIR2;
volatile struct {
unsigned PRI_HINT_2 : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned NONE_HINT_2 : 1; // 31
} HIPIR2_bit;
}; // 0x908
/* PRU_INTC_HIPIR3 register bit field */
union {
volatile uint32_t HIPIR3;
volatile struct {
unsigned PRI_HINT_3 : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned NONE_HINT_3 : 1; // 31
} HIPIR3_bit;
}; // 0x90C
/* PRU_INTC_HIPIR4 register bit field */
union {
volatile uint32_t HIPIR4;
volatile struct {
unsigned PRI_HINT_4 : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned NONE_HINT_4 : 1; // 31
} HIPIR4_bit;
}; // 0x910
/* PRU_INTC_HIPIR5 register bit field */
union {
volatile uint32_t HIPIR5;
volatile struct {
unsigned PRI_HINT_5 : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned NONE_HINT_5 : 1; // 31
} HIPIR5_bit;
}; // 0x914
/* PRU_INTC_HIPIR6 register bit field */
union {
volatile uint32_t HIPIR6;
volatile struct {
unsigned PRI_HINT_6 : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned NONE_HINT_6 : 1; // 31
} HIPIR6_bit;
}; // 0x918
/* PRU_INTC_HIPIR7 register bit field */
union {
volatile uint32_t HIPIR7;
volatile struct {
unsigned PRI_HINT_7 : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned NONE_HINT_7 : 1; // 31
} HIPIR7_bit;
}; // 0x91C
/* PRU_INTC_HIPIR8 register bit field */
union {
volatile uint32_t HIPIR8;
volatile struct {
unsigned PRI_HINT_8 : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned NONE_HINT_8 : 1; // 31
} HIPIR8_bit;
}; // 0x920
/* PRU_INTC_HIPIR9 register bit field */
union {
volatile uint32_t HIPIR9;
volatile struct {
unsigned PRI_HINT_9 : 10; // 9:0
unsigned rsvd10 : 21; // 30:10
unsigned NONE_HINT_9 : 1; // 31
} HIPIR9_bit;
}; // 0x924
uint32_t rsvd928[246]; // 0x928 - 0xCFC
/* PRU_INTC_SIPR0 register bit field */
union {
volatile uint32_t SIPR0;
volatile struct {
unsigned POLARITY_31_0 : 32; // 31:0
} SIPR0_bit;
}; // 0xD00
/* PRU_INTC_SIPR1 register bit field */
union {
volatile uint32_t SIPR1;
volatile struct {
unsigned POLARITY_63_32 : 32; // 31:0
} SIPR1_bit;
}; // 0xD04
uint32_t rsvdD08[30]; // 0xD08 - 0xD7C
/* PRU_INTC_SITR0 register bit field */
union {
volatile uint32_t SITR0;
volatile struct {
unsigned TYPE_31_0 : 32; // 31:0
} SITR0_bit;
}; // 0xD80
/* PRU_INTC_SITR1 register bit field */
union {
volatile uint32_t SITR1;
volatile struct {
unsigned TYPE_63_32 : 32; // 31:0
} SITR1_bit;
}; // 0xD84
uint32_t rsvdD84[222]; // 0xD88 - 0x10FC
/* PRU_INTC_HINLR0 register bit field */
union {
volatile uint32_t HINLR0;
volatile struct {
unsigned NEST_HINT_0 : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} HINLR0_bit;
}; // 0x1100
/* PRU_INTC_HINLR1 register bit field */
union {
volatile uint32_t HINLR1;
volatile struct {
unsigned NEST_HINT_1 : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} HINLR1_bit;
}; // 0x1104
/* PRU_INTC_HINLR2 register bit field */
union {
volatile uint32_t HINLR2;
volatile struct {
unsigned NEST_HINT_2 : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} HINLR2_bit;
}; // 0x1108
/* PRU_INTC_HINLR3 register bit field */
union {
volatile uint32_t HINLR3;
volatile struct {
unsigned NEST_HINT_3 : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} HINLR3_bit;
}; // 0x110C
/* PRU_INTC_HINLR4 register bit field */
union {
volatile uint32_t HINLR4;
volatile struct {
unsigned NEST_HINT_4 : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} HINLR4_bit;
}; // 0x1110
/* PRU_INTC_HINLR5 register bit field */
union {
volatile uint32_t HINLR5;
volatile struct {
unsigned NEST_HINT_5 : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} HINLR5_bit;
}; // 0x1114
/* PRU_INTC_HINLR6 register bit field */
union {
volatile uint32_t HINLR6;
volatile struct {
unsigned NEST_HINT_6 : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} HINLR6_bit;
}; // 0x1118
/* PRU_INTC_HINLR7 register bit field */
union {
volatile uint32_t HINLR7;
volatile struct {
unsigned NEST_HINT_7 : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} HINLR7_bit;
}; // 0x111C
/* PRU_INTC_HINLR8 register bit field */
union {
volatile uint32_t HINLR8;
volatile struct {
unsigned NEST_HINT_8 : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} HINLR8_bit;
}; // 0x1120
/* PRU_INTC_HINLR9 register bit field */
union {
volatile uint32_t HINLR9;
volatile struct {
unsigned NEST_HINT_9 : 9; // 8:0
unsigned rsvd9 : 22; // 30:9
unsigned AUTO_OVERRIDE : 1; // 31
} HINLR9_bit;
}; // 0x1124
uint32_t rsvd1128[246]; // 0x1128 - 0x14FC
/* PRU_INTC_HIER register bit field */
union {
volatile uint32_t HIER;
volatile struct {
unsigned EN_HINT : 10; // 9:0
unsigned rsvd9 : 22; // 31:10
} HIER_bit;
}; // 0x1500
} pruIntc;
#ifdef __GNUC__
static volatile pruIntc *__CT_INTC = (void *)0x00020000;
#define CT_INTC (*__CT_INTC)
#else
volatile __far pruIntc CT_INTC __attribute__((cregister("PRU_INTC", far), peripheral));
#endif
#endif /* _PRU_INTC_H_ */

View File

@@ -0,0 +1,285 @@
/*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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.
*/
#ifndef _PRU_UART_H_
#define _PRU_UART_H_
/* UART Register set */
typedef struct {
/*
* RBR and THR register pair
* This is a unique register pair in that RBR and THR
* share the same address. RBR is read-only while THR is
* write-only.
*
* Additionally, RBR and THR share an address with DLL. To
* read/write RBR/THR write 0 to the DLAB bit in the LCR
* register. To modify DLL write a 1.
*
* DLL also has a dedicated
* address which does not require toggling the DLAB bit.
*/
union {
/* PRU_UART_RBR register bit field */
union {
volatile uint32_t RBR;
volatile struct {
unsigned DATA : 8; // 7:0
unsigned rsvd8 : 24; // 31:8
} RBR_bit;
};
/* PRU_UART_THR register bit field */
union {
volatile uint32_t THR;
volatile struct {
unsigned DATA : 8; // 7:0
unsigned rsvd8 : 24; // 31:8
} THR_bit;
};
}; // 0x0
/* PRU_UART_IER register bit field */
/*
* IER shares an address with DLH. To modify IER write 0
* to the DLAB bit in the LCR register. To modify DLH write a 1.
*
* DLH also has a dedicated address which does not require
* toggling the DLAB bit.
*/
union {
volatile uint32_t IER;
volatile struct {
unsigned ERBI : 1; // 0
unsigned ETBEI : 1; // 1
unsigned ELSI : 1; // 2
unsigned EDSSI : 1; // 3
unsigned rsvd4 : 28; // 31:4
} IER_bit;
}; // 0x4
/*
* IIR and FCR register pair
* This is a unique register pair in that IIR and FCR
* share the same address. IIR is read-only while FCR is
* write-only.
*/
union {
/* PRU_UART_IIR register bit field */
union {
volatile uint32_t IIR;
volatile struct {
unsigned IPEND : 1; // 0
unsigned INTID : 3; // 3:1
unsigned rsvd4 : 2; // 5:4
unsigned FIFOEN : 2; // 7:6
unsigned rsvd8 : 24; // 31:8
} IIR_bit;
};
/* PRU_UART_FCR register bit field */
union {
volatile uint32_t FCR;
volatile struct {
unsigned FIFOEN : 1; // 0
unsigned RXCLR : 1; // 1
unsigned TXCLR : 1; // 2
unsigned DMAMODE1 : 1; // 3
unsigned rsvd4 : 2; // 5:4
unsigned RXFIFTL : 2; // 7:6
unsigned rsvd8 : 24; // 31:8
} FCR_bit;
};
}; // 0x8
/* PRU_UART_LCR register bit field */
union {
volatile uint32_t LCR;
volatile struct {
unsigned WLS : 2; // 1:0
unsigned STB : 1; // 2
unsigned PEN : 1; // 3
unsigned EPS : 1; // 4
unsigned SP : 1; // 5
unsigned BC : 1; // 6
unsigned DLAB : 1; // 7
unsigned rsvd8 : 24; // 31:8
} LCR_bit;
}; // 0xC
/* PRU_UART_MCR register bit field */
union {
volatile uint32_t MCR;
volatile struct {
unsigned rsvd0 : 1; // 0
unsigned RTS : 1; // 1
unsigned OUT1 : 1; // 2
unsigned OUT2 : 1; // 3
unsigned LOOP : 1; // 4
unsigned AFE : 1; // 5
unsigned rsvd8 : 26; // 31:6
} MCR_bit;
}; // 0x10
/* PRU_UART_LSR register bit field */
union {
volatile uint32_t LSR;
volatile struct {
unsigned DR : 1; // 0
unsigned OE : 1; // 1
unsigned PE : 1; // 2
unsigned FE : 1; // 3
unsigned BI : 1; // 4
unsigned THRE : 1; // 5
unsigned TEMT : 1; // 6
unsigned RXFIFOE : 1; // 7
unsigned rsvd8 : 24; // 31:8
} LSR_bit;
}; // 0x14
/* PRU_UART_MSR register bit field */
union {
volatile uint32_t MSR;
volatile struct {
unsigned DCTS : 1; // 0
unsigned DDSR : 1; // 1
unsigned TERI : 1; // 2
unsigned DCD : 1; // 3
unsigned CTS : 1; // 4
unsigned DSR : 1; // 5
unsigned RI : 1; // 6
unsigned CD : 1; // 7
unsigned rsvd8 : 24; // 31:8
} MSR_bit;
}; // 0x18
/* PRU_UART_SCR register bit field */
union {
volatile uint32_t SCR;
volatile struct {
unsigned SCR : 8; // 7:0
unsigned rsvd8 : 24; // 31:8
} SCR_bit;
}; // 0x1C
/* PRU_UART_DLL register bit field */
union {
volatile uint32_t DLL;
volatile struct {
unsigned DLL : 8; // 7:0
unsigned rsvd8 : 24; // 31:8
} DLL_bit;
}; // 0x20
/* PRU_UART_DLH register bit field */
union {
volatile uint32_t DLH;
volatile struct {
unsigned DLH : 8; // 7:0
unsigned rsvd8 : 24; // 31:8
} DLH_bit;
}; // 0x24
/* PRU_UART_REVID1 register bit field */
union {
volatile uint32_t REVID1;
volatile struct {
unsigned REVID1 : 32; // 31:0
} REVID1_bit;
}; // 0x28
/* PRU_UART_REVID2 register bit field */
union {
volatile uint32_t REVID2;
volatile struct {
unsigned REVID2 : 8; // 7:0
unsigned rsvd8 : 24; // 31:8
} REVID2_bit;
}; // 0x2C
/* PRU_UART_PWREMU_MGMT register bit field */
union {
volatile uint32_t PWREMU_MGMT;
volatile struct {
unsigned FREE : 1; // 0
unsigned rsvd1 : 12; // 12:1
unsigned URRST : 1; // 13
unsigned UTRST : 1; // 14
unsigned rsvd15 : 17; // 31:15
} PWREMU_MGMT_bit;
}; // 0x30
/* PRU_UART_MDR register bit field */
union {
volatile uint32_t MDR;
volatile struct {
unsigned OSM_SEL : 1; // 0
unsigned rsvd1 : 31; // 31:1
} MDR_bit;
}; // 0x34
} pruUart;
volatile __far pruUart CT_UART __attribute__((cregister("PRU_UART", near), peripheral));
#endif /* _PRU_UART_H_ */

View File

@@ -0,0 +1,210 @@
/*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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.
*/
#ifndef _SYS_MAILBOX_H_
#define _SYS_MAILBOX_H_
/* SYS_MAILBOX register set */
typedef struct {
/* SYS_MAILBOX_REVISION register bit field */
union {
volatile uint32_t REVISION;
volatile struct {
unsigned MINOR : 6; //5:0
unsigned CUSTOM : 2; //7:6
unsigned MAJOR : 3; //10:8
unsigned RTL : 5; //15:11
unsigned FUNC : 12; //27:16
unsigned rsvd28 : 2; //29:28
unsigned SCHEME : 2; //31:30
} REVISION_bit;
}; // 0x0
uint32_t rsvd4[3]; // 0x4 - 0xC
/* SYS_MAILBOX_SYSCONFIG register bit field */
union {
volatile uint32_t SYSCONFIG;
volatile struct {
unsigned SOFTRESET : 1; //0
unsigned rsvd : 1; //1
unsigned SLIDLEMODE : 2; //3:2
unsigned rsvd1 : 28; //31:4
} SYSCONFIG_bit;
}; // 0x10
uint32_t rsvd14[11]; // 0x14 - 0x3C
/* SYS_MAILBOX_MESSAGE register bit fields */
union {
volatile uint32_t MESSAGE[8];
volatile struct {
unsigned MESSAGE : 32; //31:0
} MESSAGE_bit[8];
}; // 0x40-0x5C
uint32_t rsvd60[8]; // 0x60 - 0x7C
/* SYS_MAILBOX_FIFOSTATUS register bit fields */
union {
volatile uint32_t FIFOSTATUS[8];
volatile struct {
unsigned FIFOFULL : 1; //0
unsigned rsvd : 31; //31:1
} FIFOSTATUS_bit[8];
}; // 0x80-0x9C
uint32_t rsvdA0[8]; // 0xA0 - 0xBC
/* SYS_MAILBOX_MSGSTATUS register bit fields */
union {
volatile uint32_t MSGSTATUS[8];
volatile struct {
unsigned NBOFMSG : 3; //2:0
unsigned rsvd : 29; //31:3
} MSGSTATUS_bit[8];
}; // 0xC0-DC
uint32_t rsvdE0[8]; // 0xE0 - 0xFC
volatile struct {
union {
volatile uint32_t STATUS_RAW;
volatile struct {
unsigned NEWMSGSTATUSMB0 : 1; //0
unsigned NOTFULLSTATUSMB0 : 1; //1
unsigned NEWMSGSTATUSMB1 : 1; //2
unsigned NOTFULLSTATUSMB1 : 1; //3
unsigned NEWMSGSTATUSMB2 : 1; //4
unsigned NOTFULLSTATUSMB2 : 1; //5
unsigned NEWMSGSTATUSMB3 : 1; //6
unsigned NOTFULLSTATUSMB3 : 1; //7
unsigned NEWMSGSTATUSMB4 : 1; //8
unsigned NOTFULLSTATUSMB4 : 1; //9
unsigned NEWMSGSTATUSMB5 : 1; //10
unsigned NOTFULLSTATUSMB5 : 1; //11
unsigned NEWMSGSTATUSMB6 : 1; //12
unsigned NOTFULLSTATUSMB6 : 1; //13
unsigned NEWMSGSTATUSMB7 : 1; //14
unsigned NOTFULLSTATUSMB7 : 1; //15
unsigned rsvd : 16; //31:16
} STATUS_RAW_bit;
};
union {
volatile uint32_t STATUS_CLR;
volatile struct {
unsigned NEWMSGSTATUSMB0 : 1; //0
unsigned NOTFULLSTATUSMB0 : 1; //1
unsigned NEWMSGSTATUSMB1 : 1; //2
unsigned NOTFULLSTATUSMB1 : 1; //3
unsigned NEWMSGSTATUSMB2 : 1; //4
unsigned NOTFULLSTATUSMB2 : 1; //5
unsigned NEWMSGSTATUSMB3 : 1; //6
unsigned NOTFULLSTATUSMB3 : 1; //7
unsigned NEWMSGSTATUSMB4 : 1; //8
unsigned NOTFULLSTATUSMB4 : 1; //9
unsigned NEWMSGSTATUSMB5 : 1; //10
unsigned NOTFULLSTATUSMB5 : 1; //11
unsigned NEWMSGSTATUSMB6 : 1; //12
unsigned NOTFULLSTATUSMB6 : 1; //13
unsigned NEWMSGSTATUSMB7 : 1; //14
unsigned NOTFULLSTATUSMB7 : 1; //15
unsigned rsvd : 16; //31:16
} STATUS_CLR_bit;
};
union {
volatile uint32_t ENABLE_SET;
volatile struct {
unsigned NEWMSGSTATUSMB0 : 1; //0
unsigned NOTFULLSTATUSMB0 : 1; //1
unsigned NEWMSGSTATUSMB1 : 1; //2
unsigned NOTFULLSTATUSMB1 : 1; //3
unsigned NEWMSGSTATUSMB2 : 1; //4
unsigned NOTFULLSTATUSMB2 : 1; //5
unsigned NEWMSGSTATUSMB3 : 1; //6
unsigned NOTFULLSTATUSMB3 : 1; //7
unsigned NEWMSGSTATUSMB4 : 1; //8
unsigned NOTFULLSTATUSMB4 : 1; //9
unsigned NEWMSGSTATUSMB5 : 1; //10
unsigned NOTFULLSTATUSMB5 : 1; //11
unsigned NEWMSGSTATUSMB6 : 1; //12
unsigned NOTFULLSTATUSMB6 : 1; //13
unsigned NEWMSGSTATUSMB7 : 1; //14
unsigned NOTFULLSTATUSMB7 : 1; //15
unsigned rsvd : 16; //31:16
} ENABLE_SET_bit;
};
union {
volatile uint32_t ENABLE_CLR;
volatile struct {
unsigned NEWMSGSTATUSMB0 : 1; //0
unsigned NOTFULLSTATUSMB0 : 1; //1
unsigned NEWMSGSTATUSMB1 : 1; //2
unsigned NOTFULLSTATUSMB1 : 1; //3
unsigned NEWMSGSTATUSMB2 : 1; //4
unsigned NOTFULLSTATUSMB2 : 1; //5
unsigned NEWMSGSTATUSMB3 : 1; //6
unsigned NOTFULLSTATUSMB3 : 1; //7
unsigned NEWMSGSTATUSMB4 : 1; //8
unsigned NOTFULLSTATUSMB4 : 1; //9
unsigned NEWMSGSTATUSMB5 : 1; //10
unsigned NOTFULLSTATUSMB5 : 1; //11
unsigned NEWMSGSTATUSMB6 : 1; //12
unsigned NOTFULLSTATUSMB6 : 1; //13
unsigned NEWMSGSTATUSMB7 : 1; //14
unsigned NOTFULLSTATUSMB7 : 1; //15
unsigned rsvd : 16; //31:16
} ENABLE_CLR_bit;
};
} IRQ[4];
} sysMailbox;
#ifdef __GNUC__
static volatile sysMailbox *__CT_MBX = (void *)0x480C8000;
#define CT_MBX (*__CT_MBX)
#else
volatile __far sysMailbox CT_MBX __attribute__((cregister("MBX0", far), peripheral));
#endif
#endif /* _SYS_MAILBOX_H_ */

View File

@@ -0,0 +1,446 @@
/*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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.
*/
#ifndef _SYS_PWMSS_H_
#define _SYS_PWMSS_H_
/* SYS_PWMSS register set */
typedef struct {
/***************************/
/* PWM Subsystem Registers */
/***************************/
/* SYS_PWMSS_IDVER register bit field */
union {
volatile uint32_t IDVER;
volatile struct {
unsigned Y_MINOR : 6; //5:0
unsigned CUSTOM : 2; //7:6
unsigned X_MAJOR : 3; //10:8
unsigned R_RTL : 5; //15:11
unsigned FUNC : 12; //27:16
unsigned rsvd28 : 2; //29:28
unsigned SCHEME : 2; //31:30
} IDVER_bit;
}; // 0x0
/* SYS_PWMSS_SYSCONFIG register bit field */
union {
volatile uint32_t SYSCONFIG;
volatile struct {
unsigned SOFTRESET : 1; //0
unsigned FREEEMU : 1; //1
unsigned IDLEMODE : 2; //3:2
unsigned STANDBYMODE : 2; //5:4
unsigned rsvd6 : 26; //31:6
} SYSCONFIG_bit;
}; // 0x4
/* SYS_PWMSS_CLKCONFIG register bit field */
union {
volatile uint32_t CLKCONFIG;
volatile struct {
unsigned ECAPCLK_EN : 1; //0
unsigned ECAPCLKSTOP_REQ : 1; //1
unsigned rsvd2 : 2; //3:2
unsigned EQEPCLK_EN : 1; //4
unsigned EQEPCLKSTOP_REQ : 1; //5
unsigned rsvd6 : 2; //7:6
unsigned EPWMCLK_EN : 1; //8
unsigned EPWMCLKSTOP_REQ : 1; //9
unsigned rsvd10 : 22; //31:10
} CLKCONFIG_bit;
}; // 0x8
/* SYS_PWMSS_CLKSTATUS register bit field */
union {
volatile uint32_t CLKSTATUS;
volatile struct {
unsigned ECAPCLK_EN_ACK : 1; //0
unsigned ECAPCLKSTOP_ACK : 1; //1
unsigned rsvd2 : 2; //3:2
unsigned EQEPCLK_EN_ACK : 1; //4
unsigned EQEPCLKSTOP_ACK : 1; //5
unsigned rsvd6 : 2; //7:6
unsigned EPWMCLK_EN_ACK : 1; //8
unsigned EPWMCLKSTOP_ACK : 1; //9
unsigned rsvd10 : 22; //31:10
} CLKSTATUS_bit;
}; // 0xC
uint32_t rsvd10[60]; // 0x10 - 0xFC
/*************************/
/* eCAP Module Registers */
/*************************/
/* SYS_PWMSS_ECAP_TSCTR register bit field */
union {
volatile uint32_t ECAP_TSCTR;
volatile struct {
unsigned TSCTR : 32; //31:0
} ECAP_TSCTR_bit;
}; // 0x100
/* SYS_PWMSS_ECAP_CTRPHS register bit field */
union {
volatile uint32_t ECAP_CTRPHS;
volatile struct {
unsigned CTRPHS : 32; //31:0
} ECAP_CTRPHS_bit;
}; // 0x104
/* SYS_PWMSS_ECAP_CAP1 register bit field */
union {
volatile uint32_t ECAP_CAP1;
volatile struct {
unsigned CAP1 : 32; //31:0
} ECAP_CAP1_bit;
}; // 0x108
/* SYS_PWMSS_ECAP_CAP2 register bit field */
union {
volatile uint32_t ECAP_CAP2;
volatile struct {
unsigned CAP2 : 32; //31:0
} ECAP_CAP2_bit;
}; // 0x10C
/* SYS_PWMSS_ECAP_CAP3 register bit field */
union {
volatile uint32_t ECAP_CAP3;
volatile struct {
unsigned CAP3 : 32; //31:0
} ECAP_CAP3_bit;
}; // 0x110
/* SYS_PWMSS_ECAP_CAP4 register bit field */
union {
volatile uint32_t ECAP_CAP4;
volatile struct {
unsigned CAP4 : 32; //31:0
} ECAP_CAP4_bit;
}; // 0x114
uint32_t rsvd118[4]; // 0x118 - 0x124
/* SYS_PWMSS_ECAP_ECCTL1 register bit field */
volatile uint16_t ECAP_ECCTL1; // 0x128
/* SYS_PWMSS_ECAP_ECCTL2 register bit field */
volatile uint16_t ECAP_ECCTL2; // 0x12A
/* SYS_PWMSS_ECAP_ECEINT register bit field */
volatile uint16_t ECAP_ECEINT; // 0x12C
/* SYS_PWMSS_ECAP_ECFLG register bit field */
volatile uint16_t ECAP_ECFLG; // 0x12E
/* SYS_PWMSS_ECAP_ECCLR register bit field */
volatile uint16_t ECAP_ECCLR; // 0x130
/* SYS_PWMSS_ECAP_ECFRC register bit field */
volatile uint16_t ECAP_ECFRC; // 0x132
uint32_t rsvd134[10]; // 0x134 - 0x158
/* SYS_PWMSS_ECAP_REVID register bit field */
union {
volatile uint32_t ECAP_REVID;
volatile struct {
unsigned REV : 32; //31:0
} ECAP_REVID_bit;
}; // 0x15C
uint32_t rsvd160[8]; // 0x160 - 0x17C
/*************************/
/* eQEP Module Registers */
/*************************/
/* SYS_PWMSS_EQEP_QPOSCNT register bit field */
union {
volatile uint32_t EQEP_QPOSCNT;
volatile struct {
unsigned QPOSCNT : 32; //31:0
} EQEP_QPOSCNT_bit;
}; // 0x180
/* SYS_PWMSS_EQEP_QPOSINIT register bit field */
union {
volatile uint32_t EQEP_QPOSINIT;
volatile struct {
unsigned QPOSINIT : 32; //31:0
} EQEP_QPOSINIT_bit;
}; // 0x184
/* SYS_PWMSS_EQEP_QPOSMAX register bit field */
union {
volatile uint32_t EQEP_QPOSMAX;
volatile struct {
unsigned QPOSMAX : 32; //31:0
} EQEP_QPOSMAX_bit;
}; // 0x188
/* SYS_PWMSS_EQEP_QPOSCMP register bit field */
union {
volatile uint32_t EQEP_QPOSCMP;
volatile struct {
unsigned QPOSCMP : 32; //31:0
} EQEP_QPOSCMP_bit;
}; // 0x18C
/* SYS_PWMSS_EQEP_QPOSILAT register bit field */
union {
volatile uint32_t EQEP_QPOSILAT;
volatile struct {
unsigned QPOSILAT : 32; //31:0
} EQEP_QPOSILAT_bit;
}; // 0x190
/* SYS_PWMSS_EQEP_QPOSSLAT register bit field */
union {
volatile uint32_t EQEP_QPOSSLAT;
volatile struct {
unsigned QPOSSLAT : 32; //31:0
} EQEP_QPOSSLAT_bit;
}; // 0x194
/* SYS_PWMSS_EQEP_QPOSLAT register bit field */
union {
volatile uint32_t EQEP_QPOSLAT;
volatile struct {
unsigned QPOSLAT : 32; //31:0
} EQEP_QPOSLAT_bit;
}; // 0x198
/* SYS_PWMSS_EQEP_QUTMR register bit field */
union {
volatile uint32_t EQEP_QUTMR;
volatile struct {
unsigned QUTMR : 32; //31:0
} EQEP_QUTMR_bit;
}; // 0x19C
/* SYS_PWMSS_EQEP_QUPRD register bit field */
union {
volatile uint32_t EQEP_QUPRD;
volatile struct {
unsigned QUPRD : 32; //31:0
} EQEP_QUPRD_bit;
}; // 0x1A0
/* SYS_PWMSS_EQEP_QWDTMR register bit field */
volatile uint16_t EQEP_QWDTMR; // 0x1A4
/* SYS_PWMSS_EQEP_QWDPRD register bit field */
volatile uint16_t EQEP_QWDPRD; // 0x1A6
/* SYS_PWMSS_EQEP_QDECCTL register bit field */
volatile uint16_t EQEP_QDECCTL; // 0x1A8
/* SYS_PWMSS_EQEP_QEPCTL register bit field */
volatile uint16_t EQEP_QEPCTL; // 0x1AA
/* SYS_PWMSS_EQEP_QCAPCTL register bit field */
volatile uint16_t EQEP_QCAPCTL; // 0x1AC
/* SYS_PWMSS_EQEP_QPOSCTL register bit field */
volatile uint16_t EQEP_QPOSCTL; // 0x1AE
/* SYS_PWMSS_EQEP_QEINT register bit field */
volatile uint16_t EQEP_QEINT; // 0x1B0
/* SYS_PWMSS_EQEP_QFLG register bit field */
volatile uint16_t EQEP_QFLG; // 0x1B2
/* SYS_PWMSS_EQEP_QCLR register bit field */
volatile uint16_t EQEP_QCLR; // 0x1B4
/* SYS_PWMSS_EQEP_QFRC register bit field */
volatile uint16_t EQEP_QFRC; // 0x1B6
/* SYS_PWMSS_EQEP_QEPSTS register bit field */
volatile uint16_t EQEP_QEPSTS; // 0x1B8
/* SYS_PWMSS_EQEP_QCTMR register bit field */
volatile uint16_t EQEP_QCTMR; // 0x1BA
/* SYS_PWMSS_EQEP_QCPRD register bit field */
volatile uint16_t EQEP_QCPRD; // 0x1BC
/* SYS_PWMSS_EQEP_QCTMRLAT register bit field */
volatile uint16_t EQEP_QCTMRLAT; // 0x1BE
/* SYS_PWMSS_EQEP_QCPRDLAT register bit field */
volatile uint16_t EQEP_QCPRDLAT; // 0x1C0
uint16_t rsvd1C2[1]; // 0x1C2 - 0x1C3
uint32_t rsvd1C4[6]; // 0x1C4 - 0x1D8
/* SYS_PWMSS_EQEP_REVID register bit field */
union {
volatile uint32_t EQEP_REVID;
volatile struct {
unsigned REVID : 32; //31:0
} EQEP_REVID_bit;
}; // 0x1DC
uint32_t rsvd1E0[8]; // 0x1E0 - 0x1FC
/*************************/
/* ePWM Module Registers */
/*************************/
/* SYS_PWMSS_EPWM_TBCTL register bit field */
volatile uint16_t EPWM_TBCTL; // 0x200
/* SYS_PWMSS_EPWM_TBSTS register bit field */
volatile uint16_t EPWM_TBSTS; // 0x202
/* SYS_PWMSS_EPWM_TBPHSHR register bit field */
volatile uint16_t EPWM_TBPHSHR; // 0x204
/* SYS_PWMSS_EPWM_TBPHS register bit field */
volatile uint16_t EPWM_TBPHS; // 0x206
/* SYS_PWMSS_EPWM_TBCNT register bit field */
volatile uint16_t EPWM_TBCNT; // 0x208
/* SYS_PWMSS_EPWM_TBPRD register bit field */
volatile uint16_t EPWM_TBPRD; // 0x20A
uint16_t rsvd20C[1]; // 0x20C - 0x20D
/* SYS_PWMSS_EPWM_CMPCTL register bit field */
volatile uint16_t EPWM_CMPCTL; // 0x20E
/* SYS_PWMSS_EPWM_CMPAHR register bit field */
volatile uint16_t EPWM_CMPAHR; // 0x210
/* SYS_PWMSS_EPWM_CMPA register bit field */
volatile uint16_t EPWM_CMPA; // 0x212
/* SYS_PWMSS_EPWM_CMPB register bit field */
volatile uint16_t EPWM_CMPB; // 0x214
/* SYS_PWMSS_EPWM_AQCTLA register bit field */
volatile uint16_t EPWM_AQCTLA; // 0x216
/* SYS_PWMSS_EPWM_AQCTLB register bit field */
volatile uint16_t EPWM_AQCTLB; // 0x218
/* SYS_PWMSS_EPWM_AQSFRC register bit field */
volatile uint16_t EPWM_AQSFRC; // 0x21A
/* SYS_PWMSS_EPWM_AQCSFRC register bit field */
volatile uint16_t EPWM_AQCSFRC; // 0x21C
/* SYS_PWMSS_EPWM_DBCTL register bit field */
volatile uint16_t EPWM_DBCTL; // 0x21E
/* SYS_PWMSS_EPWM_DBRED register bit field */
volatile uint16_t EPWM_DBRED; // 0x220
/* SYS_PWMSS_EPWM_DBFED register bit field */
volatile uint16_t EPWM_DBFED; // 0x222
/* SYS_PWMSS_EPWM_TZSEL register bit field */
volatile uint16_t EPWM_TZSEL; // 0x224
uint16_t rsvd226[1]; // 0x226 - 0x227
/* SYS_PWMSS_EPWM_TZCTL register bit field */
volatile uint16_t EPWM_TZCTL; // 0x228
/* SYS_PWMSS_EPWM_TZEINT register bit field */
volatile uint16_t EPWM_TZEINT; // 0x22A
/* SYS_PWMSS_EPWM_TZFLG register bit field */
volatile uint16_t EPWM_TZFLG; // 0x22C
/* SYS_PWMSS_EPWM_TZCLR register bit field */
volatile uint16_t EPWM_TZCLR; // 0x22E
/* SYS_PWMSS_EPWM_TZFRC register bit field */
volatile uint16_t EPWM_TZFRC; // 0x230
/* SYS_PWMSS_EPWM_ETSEL register bit field */
volatile uint16_t EPWM_ETSEL; // 0x232
/* SYS_PWMSS_EPWM_ETPS register bit field */
volatile uint16_t EPWM_ETPS; // 0x234
/* SYS_PWMSS_EPWM_ETFLG register bit field */
volatile uint16_t EPWM_ETFLG; // 0x236
/* SYS_PWMSS_EPWM_ETCLR register bit field */
volatile uint16_t EPWM_ETCLR; // 0x238
/* SYS_PWMSS_EPWM_ETFRC register bit field */
volatile uint16_t EPWM_ETFRC; // 0x23A
/* SYS_PWMSS_EPWM_PCCTL register bit field */
volatile uint16_t EPWM_PCCTL; // 0x23C
uint16_t rsvd23E[1]; // 0x23E - 0x23F
uint32_t rsvd240[32]; // 0x240 - 0x2BC
/* SYS_PWMSS_EPWM_HRCNGF register bit field */
volatile uint16_t EPWM_HRCNGF; // 0x2C0
} sysPwmss;
volatile __far sysPwmss PWMSS0 __attribute__((cregister("PWMSS0", far), peripheral));
volatile __far sysPwmss PWMSS1 __attribute__((cregister("PWMSS1", far), peripheral));
volatile __far sysPwmss PWMSS2 __attribute__((cregister("PWMSS2", far), peripheral));
#endif /* _SYS_PWMSS_H_ */

View File

@@ -0,0 +1,268 @@
/*
* Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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 : pru_rpmsg.h
*
* Summary : An RPMsg interface for the PRU to use while communicating with
* the ARM host.
*
* Notes :
* - This file creates a structure (pru_rpmsg_transport) that contains
* pointers to two pru_virtqueue structures. This structure is used as the
* underlying transport layer of all RPMsg communication. Only one
* pru_rpmsg_transport structure is needed because multiple logical channels
* can use the same underlying transport.
* - This pru_rpmsg interface is meant to sit on top of the pru_virtqueue
* interface and abstract the communication even further away from the
* underlying data structures. The goal is to make the communication as
* simple as possible at the user application level.
* - The logic for the PRU side is summarized below:
*
* PRU Slave:
* - To receive buffer from the ARM host:
* pru_rpmsg_receive(*transport, *src, *dst, *data, *len);
* - To send buffer to the host:
* pru_rpmsg_send(*transport, src, dst, *data, len);
*/
#ifndef _PRU_RPMSG_H_
#define _PRU_RPMSG_H_
#include <pru_virtqueue.h>
#include <pru_virtio_ring.h>
/* Return value indicating no kick was sent */
#define PRU_RPMSG_NO_KICK 1
/* Return value indicating success */
#define PRU_RPMSG_SUCCESS 0
/* Return value indicating there were no available buffers */
#define PRU_RPMSG_NO_BUF_AVAILABLE -1
/* Return value indicating that the buffer from the virtqueue was too small */
#define PRU_RPMSG_BUF_TOO_SMALL -2
/* Return value indicating that an invalid head index was given */
#define PRU_RPMSG_INVALID_HEAD -3
/* Return value indication that an invalid event number was given */
#define PRU_RPMSG_INVALID_EVENT -4
/* Max PRU-ICSS system event number for pru_mst_intr */
#define MAX_VALID_EVENT 31
/* Min PRU-ICSS system event number for pru_mst_intr */
#define MIN_VALID_EVENT 16
/* The maximum size of the channel name and description */
#define RPMSG_NAME_SIZE 32
/* The maximum size of the buffer (including the header) */
#define RPMSG_BUF_SIZE 512
enum pru_rpmsg_ns_flags {
RPMSG_NS_CREATE = 0,
RPMSG_NS_DESTROY = 1
};
/**
* Summary : pru_rpmsg_transport is a structure that groups together the
* two pru_virtqueues that are needed for two-way communication
* with the ARM. This structure provides a logical wrapper for
* the transport layer of the application. NOTE: Multiple
* (logical) channels can be implemented on top of the same
* transport layer.
*
* Variables : virtqueue0: contains the pru_virtqueue that is used for the
* PRU->ARM communication
* virtqueue1: contains the pru_virtqueue that is used for
* the ARM->PRU communication
*/
struct pru_rpmsg_transport {
struct pru_virtqueue virtqueue0;
struct pru_virtqueue virtqueue1;
};
/**
* Summary : pru_rpmsg_init initializes the underlying transport layer
* data structures.
*
* Parameters : transport: a pointer to the transport data structure that
* contains the underlying data structures to be
* initialized
* vring0: a pointer to vring0 which is provided by the ARM
* core through the resource table
* vring1: a pointer to vring1 which is provided by the ARM
* core through the resource table
* to_arm_event: the number of the PRU-ICSS system event
* that is specified in the device tree that
* is used to 'kick' the ARM core
* from_arm_event: the number of the PRU-ICSS system event
* that is specified in the device tree
* that is used to receive 'kicks' from the
* ARM core
*
* Description : pru_rpmsg_init takes the vrings and the events provided
* through the resource table and initializes the transport
* layer. Once this function call is successful RPMsg
* channels can be created and used.
*
* Return Value : Returns PRU_RPMSG_INVALID_EVENT if the values provided
* in to_arm_event or from_arm_event are outside of the
* allowable range of events. Returns PRU_RPMSG_SUCCESS
* if the initialization is successful.
*/
int16_t pru_rpmsg_init(
struct pru_rpmsg_transport *transport,
struct fw_rsc_vdev_vring *vring0,
struct fw_rsc_vdev_vring *vring1,
uint32_t to_arm_event,
uint32_t from_arm_event
);
/**
* Summary : pru_rpmsg_receive receives a message, if available, from
* the ARM host.
*
* Parameters : transport: a pointer to the transport layer from which the
* message should be received
* src: a pointer that is populated with the source address
* where the message originated
* dst: a pointer that is populated with the destination
* address where the message was sent (can help determine
* for which channel the message is intended on the PRU)
* data: a pointer that is populated with a local data buffer
* containing the message payload
* len: a pointer that is populated with the length of the
* message payload
*
* Description : pru_rpmsg_receive uses the pru_virtqueue interface to get
* an available buffer, copy the buffer into local memory,
* add the buffer as a used buffer to the vring, and then kick
* the remote processor if necessary. The src, dst, data, and
* len pointers are populated with the information about the
* message and local buffer data if the reception is
* successful.
*
* Return Value : Returns PRU_RPMSG_NO_BUF_AVAILABLE if there is currently no
* buffer available for receive. Returns PRU_RPMSG_INVALID_HEAD
* if the head index returned for the available buffer is
* invalid. Returns PRU_RPMSG_SUCCESS if the message is
* successfully received.
*/
int16_t pru_rpmsg_receive(
struct pru_rpmsg_transport *transport,
uint16_t *src,
uint16_t *dst,
void *data,
uint16_t *len
);
/**
* Summary : pru_rpmsg_send sends a message to the ARM host using the
* virtqueues in the pru_rpmsg_transport structure. The
* source and destination address of the message are passed
* in as parameters to the function. The data to be sent and
* its length are passed in the data and len parameters.
*
* Parameters : transport: a pointer to the transport layer from which the
* message should be sent
* src: the source address where this message will originate
* dst: the destination address where the message will be sent
* data: a pointer to a local data buffer containing the
* message payload
* len: the length of the message payload
*
* Description : pru_rpmsg_send sends a message to the src parameter and
* from the dst parameter. The transport structure defines the
* underlying transport mechanism that will be used. The
* data parameter is a pointer to a local buffer that should
* be sent to the destination address and the len parameter is
* the length of that buffer.
*
* Return Value : Returns PRU_RPMSG_NO_BUF_AVAILABLE if there is currently no
* buffer available for send. Returns PRU_RPMSG_BUF_TOO_SMALL
* if the buffer from the vring is too small to hold the
* message payload being sent. Returns PRU_RPMSG_INVALID_HEAD
* if the head index returned for the send buffer is invalid.
* Returns PRU_RPMSG_SUCCESS if the message is successfully
* sent.
*/
int16_t pru_rpmsg_send(
struct pru_rpmsg_transport *transport,
uint32_t src,
uint32_t dst,
void *data,
uint16_t len
);
/**
* Summary : pru_rpmsg_channel uses an RPMsg Name Service Announcment
* to either create or destroy an RPMsg channel depending on
* the pru_rpmsg_ns_flags parameter that is specified.
*
* Parameters : flags: an enum that is used to create (RPMSG_NS_CREATE) or
* destroy (RPMSG_NS_DESTROY) an RPMsg channel
* transport: a pointer to the transport layer on which this
* Name Service Announcement will be sent
* name: the name of the channel being created or destroyed
* ******* The name of the channel is very important as
* ******* it is the method that Linux on the ARM uses
* ******* to connect a PRU firmware with a corresponding
* ******* Linux driver
* desc: the description of the RPMsg channel being created
* or destroyed
* port: the local source address of the RPMsg channel. This
* is the address where PRU messages destined for the
* ARM host will originate
*
* Description : pru_rpmsg_channel sends a message letting the ARM
* host know that a channel is to be created or destroyed. If
* a channel is to be created then this message will notify
* the name server on the ARM host to create a new channel. If
* a channel is to be destroyed this will tear down this
* logical channel of communication between the PRU and the
* ARM host.
*
* Return Value : Returns PRU_RPMSG_NO_BUF_AVAILABLE if there is currently no
* buffer available for send. Returns PRU_RPMSG_BUF_TOO_SMALL
* if the buffer from the vring is too small to hold the
* message payload being sent. Returns PRU_RPMSG_INVALID_HEAD
* if the head index returned for the send buffer is invalid.
* Returns PRU_RPMSG_SUCCESS if the message is successfully
* sent.
*/
int16_t pru_rpmsg_channel(
enum pru_rpmsg_ns_flags flags,
struct pru_rpmsg_transport *transport,
char *name,
char *desc,
int32_t port
);
#endif /* _PRU_RPMSG_H_ */

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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.
*/
#ifndef _PRU_TYPES_H_
#define _PRU_TYPES_H_
/* Custom Resource info: Must match drivers/remoteproc/pru_rproc.h */
#define TYPE_PRU_INTS 1
/**
* struct ch_map - sysevts-to-channel mapping
*
* @evt: the number of the sysevt
* @ch: channel number assigned to a given @sysevt
*
* PRU system events are mapped to channels, and these channels are mapped to
* hosts. Events can be mapped to channels in a one-to-one or many-to-one ratio
* (multiple events per channel), and channels can be mapped to hosts in a
* one-to-one or many-to-one ratio (multiple events per channel).
*
* @evt is the number of the sysevt, and @ch is the number of the channel to be
* mapped.
*/
struct ch_map {
uint8_t evt;
uint8_t ch;
};
/**
* struct fw_rsc_custom_ints - custom resource to define PRU interrupts
* @version: revision number of the custom ints type
* @channel_host: assignment of PRU channels to hosts
* @num_evts: device address of INTC
* @event_channel: mapping of sysevts to channels
*
* PRU system events are mapped to channels, and these channels are mapped to
* hosts. Events can be mapped to channels in a one-to-one or many-to-one ratio
* (multiple events per channel), and channels can be mapped to hosts in a
* one-to-one or many-to-one ratio (multiple events per channel).
*
* @da is the device address of the interrupt controller, @channel_map is
* used to specify to which channel, if any, an event is mapped, and @host_map
* specifies to which host, if any, a channel is mapped.
*/
struct fw_rsc_custom_ints {
uint16_t version;
uint8_t channel_host[10];
uint32_t num_evts;
struct ch_map *event_channel;
};
#endif /* _PRU_TYPES_H_ */

View File

@@ -0,0 +1,42 @@
#ifndef _LINUX_VIRTIO_IDS_H
#define _LINUX_VIRTIO_IDS_H
/*
* Virtio IDs
*
* This header is BSD licensed so anyone can use the definitions to implement
* compatible drivers/servers.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of IBM nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS 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. */
#define VIRTIO_ID_NET 1 /* virtio net */
#define VIRTIO_ID_BLOCK 2 /* virtio block */
#define VIRTIO_ID_CONSOLE 3 /* virtio console */
#define VIRTIO_ID_RNG 4 /* virtio rng */
#define VIRTIO_ID_BALLOON 5 /* virtio balloon */
#define VIRTIO_ID_RPMSG 7 /* virtio remote processor messaging */
#define VIRTIO_ID_SCSI 8 /* virtio scsi */
#define VIRTIO_ID_9P 9 /* 9p virtio console */
#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
#endif /* _LINUX_VIRTIO_IDS_H */

View File

@@ -0,0 +1,163 @@
#ifndef _UAPI_LINUX_VIRTIO_RING_H
#define _UAPI_LINUX_VIRTIO_RING_H
/* An interface for efficient virtio implementation, currently for use by KVM
* and lguest, but hopefully others soon. Do NOT change this since it will
* break existing servers and clients.
*
* This header is BSD licensed so anyone can use the definitions to implement
* compatible drivers/servers.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of IBM nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS 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.
*
* Copyright Rusty Russell IBM Corporation 2007. */
#include <stdint.h>
/* This marks a buffer as continuing via the next field. */
#define VRING_DESC_F_NEXT 1
/* This marks a buffer as write-only (otherwise read-only). */
#define VRING_DESC_F_WRITE 2
/* This means the buffer contains a list of buffer descriptors. */
#define VRING_DESC_F_INDIRECT 4
/* The Host uses this in used->flags to advise the Guest: don't kick me when
* you add a buffer. It's unreliable, so it's simply an optimization. Guest
* will still kick if it's out of buffers. */
#define VRING_USED_F_NO_NOTIFY 1
/* The Guest uses this in avail->flags to advise the Host: don't interrupt me
* when you consume a buffer. It's unreliable, so it's simply an
* optimization. */
#define VRING_AVAIL_F_NO_INTERRUPT 1
/* We support indirect buffer descriptors */
#define VIRTIO_RING_F_INDIRECT_DESC 28
/* The Guest publishes the used index for which it expects an interrupt
* at the end of the avail ring. Host should ignore the avail->flags field. */
/* The Host publishes the avail index for which it expects a kick
* at the end of the used ring. Guest should ignore the used->flags field. */
#define VIRTIO_RING_F_EVENT_IDX 29
/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
struct vring_desc {
/* Address (guest-physical). */
uint64_t addr;
/* Length. */
uint32_t len;
/* The flags as indicated above. */
uint16_t flags;
/* We chain unused descriptors via this, too */
uint16_t next;
};
struct vring_avail {
uint16_t flags;
uint16_t idx;
uint16_t ring[];
};
/* u32 is used here for ids for padding reasons. */
struct vring_used_elem {
/* Index of start of used descriptor chain. */
uint32_t id;
/* Total length of the descriptor chain which was used (written to) */
uint32_t len;
};
struct vring_used {
uint16_t flags;
uint16_t idx;
struct vring_used_elem ring[];
};
struct vring {
uint32_t num;
struct vring_desc *desc;
struct vring_avail *avail;
struct vring_used *used;
};
/* The standard layout for the ring is a continuous chunk of memory which looks
* like this. We assume num is a power of 2.
*
* struct vring
* {
* // The actual descriptors (16 bytes each)
* struct vring_desc desc[num];
*
* // A ring of available descriptor heads with free-running index.
* __u16 avail_flags;
* __u16 avail_idx;
* __u16 available[num];
* __u16 used_event_idx;
*
* // Padding to the next align boundary.
* char pad[];
*
* // A ring of used descriptor heads with free-running index.
* __u16 used_flags;
* __u16 used_idx;
* struct vring_used_elem used[num];
* __u16 avail_event_idx;
* };
*/
/* We publish the used event index at the end of the available ring, and vice
* versa. They are at the end for backwards compatibility. */
#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num])
#define vring_avail_event(vr) (*(__u16 *)&(vr)->used->ring[(vr)->num])
static inline void vring_init(struct vring *vr, uint32_t num, void *p,
uint64_t align)
{
vr->num = num;
vr->desc = p;
vr->avail = (void *)((char *)p + num*sizeof(struct vring_desc));
vr->used = (void *)(uintptr_t)(((uintptr_t)&vr->avail->ring[num]
+ sizeof(uint16_t) + align-1) & ~(align - 1));
}
static inline unsigned vring_size(uint16_t num, uint64_t align)
{
return ((sizeof(struct vring_desc) * num + sizeof(uint16_t) * (3 + num)
+ align - 1) & ~(align - 1))
+ sizeof(uint16_t) * 3 + sizeof(struct vring_used_elem) * num;
}
/* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */
/* Assuming a given event_idx value from the other size, if
* we have just incremented index from old to new_idx,
* should we trigger an event? */
static inline int vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old)
{
/* Note: Xen has similar logic for notification hold-off
* in include/xen/interface/io/ring.h with req_event and req_prod
* corresponding to event_idx + 1 and new_idx respectively.
* Note also that req_event and req_prod in Xen start at 1,
* event indexes in virtio start at 0. */
return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
}
#endif /* _UAPI_LINUX_VIRTIO_RING_H */

View File

@@ -0,0 +1,211 @@
/*
* Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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 : pru_virtqueue.h
*
* Summary : A virtual queue interface to simplify vring usage.
*
* Notes :
* - This file implements the vring functions needed by the PRU core
* - The PRU core is considered the slave and the ARM core is considered the
* host
* - The ARM host always adds *available* buffers to send/receive, while the
* PRU slave always adds *used* buffers to send/receive.
* - The logic for the PRU side is summarized below:
*
* PRU Slave:
* - To receive buffer from the ARM host:
* virtqueue_getAvailBuf(vq_slave);
* >> empty data from buf <<
* virtqueue_addUsedBuf(vq_slave);
* virtqueue_kick(vq_slave);
* - To send buffer to the host:
* virtqueue_getAvailBuf(vq_host);
* >> copy data into buf <<
* virtqueue_addUsedBuf(vq_host);
* virtqueue_kick(vq_host);
*/
#ifndef _PRU_VIRTQUEUE_H_
#define _PRU_VIRTQUEUE_H_
#include <rsc_types.h>
#include <pru_virtio_ring.h>
/* Return value indicating no kick was sent */
#define PRU_VIRTQUEUE_NO_KICK 1
/* Return value indicating success */
#define PRU_VIRTQUEUE_SUCCESS 0
/* Return value indicating there were no available buffers */
#define PRU_VIRTQUEUE_NO_BUF_AVAILABLE -1
/* Return value indicating that an invalid head index was given */
#define PRU_VIRTQUEUE_INVALID_HEAD -2
/**
* Summary : pru_virtqueue is a structure that encapsulates everything
* needed for a 'virtual queue'. This structure wraps a vring
* with extra information that is needed by the application
* in order to use the vring.
*
* Variables : id: The notification ID of the vring.
* to_arm_event: The PRU-ICSS system event that signals the ARM.
* from_arm_event: The PRU-ICSS system event that the ARM uses to
* signal the PRU.
* last_avail_idx: A local running counter that is used by the
* PRU to determine whether or not a new
* available buffer has been added to the
* vring.
* vring: The underlying virtio structure that is being used
* to pass buffers back and forth between the ARM and
* PRU. See pru_virtio_ring.h.
*/
struct pru_virtqueue {
uint32_t id;
uint32_t to_arm_event;
uint32_t from_arm_event;
uint16_t last_avail_idx;
struct vring vring;
};
/**
* Summary : pru_virtqueue_init initializes the pru_virtqueue structure
* with values from the resource table.
*
* Parameters : vq: a pointer to a pru_virtqueue structure that will be
* initialized
* vring: a pointer to a vring that is populated and returned
* by the ARM host through the resource table (the id,
* number of descriptors, address of the vring, and
* alignment information are contained in this vring
* pointer's structure
* to_arm_event: the PRU-ICSS system event to trigger in order to
* 'kick' the ARM host when sending data
* from_arm_event: the PRU-ICSS system event to check
* for data arriving from the ARM host
*
* Description : This function initializes the pru_virtqueue (vq) with input
* values from the vring in the resource table. This function
* should be called once for each virtqueue/vring. After
* initialization the pru_virtqueue pointer, vq, should be
* passed to the other functions in this header file.
*
* Return Value : No return value.
*/
void pru_virtqueue_init(
struct pru_virtqueue *vq,
struct fw_rsc_vdev_vring *vring,
uint32_t to_arm_event,
uint32_t from_arm_event
);
/**
* Summary : pru_virtqueue_get_avail_buf - gets the next available
* buffer from the pru_virtqueue specified in vq.
*
* Parameters : vq: pointer to the pru_virtqueue from which the available
* buffer should be retrieved
* buf: pointer to be filled with the address of the available
* buffer
* len: pointer to be filled with the length of the available
* buffer
*
* Description : This function compares our last_avail_idx running counter
* against the vring.avail->idx value to see if there is a
* buffer available that we have not used. If our last
* available index running counter matches the vring.avail->idx
* value then there have been no new available buffers added
* by the host. If the two indices do not match then the host
* has added new buffers and and we can set @buf to point to
* the available buffer and @len to match the available buffers
* length. If an available buffer is found we increment out
* last_avail_idx to show that we used another buffer.
*
* Return Value : PRU_VIRTQUEUE_NO_BUF_AVAILABLE if no buffer available.
* Returns the vring.desc index of the available buffer
* otherwise.
*/
int16_t pru_virtqueue_get_avail_buf(
struct pru_virtqueue *vq,
void **buf,
uint32_t *len
);
/**
* Summary : pru_virtqueue_add_used_buf adds a used buffer to the
* pru_virtqueue specified in vq.
*
* Parameters : vq: pointer to the pru_virtqueue where the used buffer
* should be added
* head: vring.desc[] index of the used buffer
* len: length of the used buffer being added
*
* Description : This function makes sure that the head vring.desc index
* (head) is a valid index. If the index is valid, then the
* buffer is added to the used list in the vring contained by
* the pru_virtqueue (vq).
*
* Return Value : PRU_VIRTQUEUE_INVALID_HEAD if head is an invalid index for
* the vring.desc array. Returns PRU_VIRTQUEUE_SUCCESS
* otherwise.
*/
int16_t pru_virtqueue_add_used_buf(
struct pru_virtqueue *vq,
int16_t head,
uint32_t len
);
/**
* Summary : pru_virtqueue_kick sends a notification to the remote
* processor that the PRU has added a buffer to the
* pru_virtqueue.
*
* Parameters : vq: pointer to the pru_virtqueue that is to be kicked
*
* Description : This function is used by the PRU to notify the ARM host in
* two situations:
* 1. That the PRU has consumed a buffer that the ARM
* host sent through the slave pru_virtqueue
* 2. That the PRU has sent a buffer to the ARM through
* the host pru_virtqueue
* If the pru_virtqueue's VRING_AVAIL_F_NO_INTERRUPT flag is
* set then the pru does not kick the pru_virtqueue.
*
* Return Value : PRU_VIRTQUEUE_NO_KICK if the VRING_AVAIL_F_NO_INTERRUPT
* flag is set or PRU_VIRTQUEUE_SUCCESS otherwise.
*/
int16_t pru_virtqueue_kick(
struct pru_virtqueue *vq
);
#endif /* _PRU_VIRTQUEUE_H_ */

View File

@@ -0,0 +1,347 @@
/*
* Copyright(c) 2011 Texas Instruments, Inc.
* Copyright(c) 2011 Google, Inc.
* 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 following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Texas Instruments nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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.
*/
#ifndef _RSC_TYPES_H_
#define _RSC_TYPES_H_
#include <stdint.h>
#include <pru_types.h>
/* Size constants must match those used on host */
#define SZ_4K (0x00001000)
#define SZ_8K (0x00002000)
/* Resource info: Must match include/linux/remoteproc.h: */
#define TYPE_CARVEOUT 0
#define TYPE_DEVMEM 1
#define TYPE_TRACE 2
#define TYPE_VDEV 3
#define TYPE_INTMEM 4
#define TYPE_CUSTOM 5
union fw_custom {
/* add custom resources here */
struct fw_rsc_custom_ints pru_ints;
/* maintain reserved as the last element */
uint32_t reserved;
};
/* Common Resource Structure Types */
/**
* struct resource_table - firmware resource table header
* @ver: version number
* @num: number of resource entries
* @reserved: reserved (must be zero)
*
* A resource table is essentially a list of system resources required
* by the remote processor. It may also include configuration entries.
* If needed, the remote processor firmware should contain this table
* as a dedicated ".resource_table" ELF section.
*
* Some resources entries are mere announcements, where the host is informed
* of specific remoteproc configuration. Other entries require the host to
* do something (e.g. allocate a system resource). Sometimes a negotiation
* is expected, where the firmware requests a resource, and once allocated,
* the host should provide back its details (e.g. address of an allocated
* memory region).
*
* The header of the resource table, as expressed by this structure,
* contains a version number (should we need to change this format in the
* future), the number of available resource entries, and their offsets
* in the table.
*
* Immediately following this header are the resource entries themselves,
* each of which begins with a resource entry header (as described below).
*/
struct resource_table {
uint32_t ver;
uint32_t num;
uint32_t reserved[2];
};
/**
* struct fw_rsc_carveout - physically contiguous memory request
* @type: type of resource
* @da: device address
* @pa: physical address
* @len: length (in bytes)
* @flags: iommu protection flags
* @reserved: reserved (must be zero)
* @name: human-readable name of the requested memory region
*
* This resource entry requests the host to allocate a physically contiguous
* memory region.
*
* These request entries should precede other firmware resource entries,
* as other entries might request placing other data objects inside
* these memory regions (e.g. data/code segments, trace resource entries, ...).
*
* Allocating memory this way helps utilizing the reserved physical memory
* (e.g. CMA) more efficiently, and also minimizes the number of TLB entries
* needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
* pressure is important; it may have a substantial impact on performance.
*
* If the firmware is compiled with static addresses, then @da should specify
* the expected device address of this memory region. If @da is set to
* FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then
* overwrite @da with the dynamically allocated address.
*
* We will always use @da to negotiate the device addresses, even if it
* isn't using an iommu. In that case, though, it will obviously contain
* physical addresses.
*
* Some remote processors needs to know the allocated physical address
* even if they do use an iommu. This is needed, e.g., if they control
* hardware accelerators which access the physical memory directly (this
* is the case with OMAP4 for instance). In that case, the host will
* overwrite @pa with the dynamically allocated physical address.
* Generally we don't want to expose physical addresses if we don't have to
* (remote processors are generally _not_ trusted), so we might want to
* change this to happen _only_ when explicitly required by the hardware.
*
* @flags is used to provide IOMMU protection flags, and @name should
* (optionally) contain a human readable name of this carveout region
* (mainly for debugging purposes).
*/
struct fw_rsc_carveout {
uint32_t type;
uint32_t da;
uint32_t pa;
uint32_t len;
uint32_t flags;
uint32_t reserved;
uint8_t name[32];
};
/**
* struct fw_rsc_devmem - iommu mapping request
* @type: type of resource
* @da: device address
* @pa: physical address
* @len: length (in bytes)
* @flags: iommu protection flags
* @reserved: reserved (must be zero)
* @name: human-readable name of the requested region to be mapped
*
* This resource entry requests the host to iommu map a physically contiguous
* memory region. This is needed in case the remote processor requires
* access to certain memory-based peripherals; _never_ use it to access
* regular memory.
*
* This is obviously only needed if the remote processor is accessing memory
* via an iommu.
*
* @da should specify the required device address, @pa should specify
* the physical address we want to map, @len should specify the size of
* the mapping and @flags is the IOMMU protection flags. As always, @name may
* (optionally) contain a human readable name of this mapping (mainly for
* debugging purposes).
*
* Note: at this point we just "trust" those devmem entries to contain valid
* physical addresses, but this isn't safe and will be changed: eventually we
* want remoteproc implementations to provide us ranges of physical addresses
* the firmware is allowed to request, and not allow firmwares to request
* access to physical addresses that are outside those ranges.
*/
struct fw_rsc_devmem {
uint32_t type;
uint32_t da;
uint32_t pa;
uint32_t len;
uint32_t flags;
uint32_t reserved;
uint8_t name[32];
};
/**
* struct fw_rsc_trace - trace buffer declaration
* @type: type of resource
* @da: device address
* @len: length (in bytes)
* @reserved: reserved (must be zero)
* @name: human-readable name of the trace buffer
*
* This resource entry provides the host information about a trace buffer
* into which the remote processor will write log messages.
*
* @da specifies the device address of the buffer, @len specifies
* its size, and @name may contain a human readable name of the trace buffer.
*
* After booting the remote processor, the trace buffers are exposed to the
* user via debugfs entries (called trace0, trace1, etc..).
*/
struct fw_rsc_trace {
uint32_t type;
uint32_t da;
uint32_t len;
uint32_t reserved;
uint8_t name[32];
};
/**
* struct fw_rsc_vdev_vring - vring descriptor entry
* @da: device address
* @align: the alignment between the consumer and producer parts of the vring
* @num: num of buffers supported by this vring (must be power of two)
* @notifyid is a unique rproc-wide notify index for this vring. This notify
* index is used when kicking a remote processor, to let it know that this
* vring is triggered.
* @reserved: reserved (must be zero)
*
* This descriptor is not a resource entry by itself; it is part of the
* vdev resource type (see below).
*
* Note that @da should either contain the device address where
* the remote processor is expecting the vring, or indicate that
* dynamically allocation of the vring's device address is supported.
*/
struct fw_rsc_vdev_vring {
uint32_t da;
uint32_t align;
uint32_t num;
uint32_t notifyid;
uint32_t reserved;
};
/**
* struct fw_rsc_vdev - virtio device header
* @type: type of resource
* @id: virtio device id (as in virtio_ids.h)
* @notifyid is a unique rproc-wide notify index for this vdev. This notify
* index is used when kicking a remote processor, to let it know that the
* status/features of this vdev have changes.
* @dfeatures specifies the virtio device features supported by the firmware
* @gfeatures is a place holder used by the host to write back the
* negotiated features that are supported by both sides.
* @config_len is the size of the virtio config space of this vdev. The config
* space lies in the resource table immediate after this vdev header.
* @status is a place holder where the host will indicate its virtio progress.
* @num_of_vrings indicates how many vrings are described in this vdev header
* @reserved: reserved (must be zero)
* @vring is an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'.
*
* This resource is a virtio device header: it provides information about
* the vdev, and is then used by the host and its peer remote processors
* to negotiate and share certain virtio properties.
*
* By providing this resource entry, the firmware essentially asks remoteproc
* to statically allocate a vdev upon registration of the rproc (dynamic vdev
* allocation is not yet supported).
*
* Note: unlike virtualization systems, the term 'host' here means
* the Linux side which is running remoteproc to control the remote
* processors. We use the name 'gfeatures' to comply with virtio's terms,
* though there isn't really any virtualized guest OS here: it's the host
* which is responsible for negotiating the final features.
* Yeah, it's a bit confusing.
*
* Note: immediately following this structure is the virtio config space for
* this vdev (which is specific to the vdev; for more info, read the virtio
* spec). the size of the config space is specified by @config_len.
*/
struct fw_rsc_vdev {
uint32_t type;
uint32_t id;
uint32_t notifyid;
uint32_t dfeatures;
uint32_t gfeatures;
uint32_t config_len;
uint8_t status;
uint8_t num_of_vrings;
uint8_t reserved[2];
struct fw_rsc_vdev_vring vring[0];
};
/**
* struct fw_rsc_intmem - internal memory publishing request
* @type: type of resource
* @da: device address
* @pa: physical address
* @len: length (in bytes)
* @reserved: reserved (must be zero)
* @name: human-readable name of the region being published
*
* This resource entry allows a remote processor to publish an internal
* memory region to the host. This resource type allows a remote processor
* to publish the whole or just a portion of certain internal memories,
* while it owns and manages any unpublished portion (eg: a shared L1
* memory that can be split configured as RAM and/or cache). This is
* primarily provided to allow a host to load code/data into internal
* memories, the memory for which is neither allocated nor required to
* be mapped into an iommu.
*
* @da should specify the required address as accessible by the device
* without going through an iommu, @pa should specify the physical address
* for the region as seen on the bus, @len should specify the size of the
* memory region. As always, @name may (optionally) contain a human readable
* name of this mapping (mainly for debugging purposes).
*
* Note: at this point we just "trust" these intmem entries to contain valid
* physical bus addresses. these are not currently intended to be managed
* as host-controlled heaps, as it is much better to do that from the remote
* processor side.
*/
struct fw_rsc_intmem {
uint32_t type;
uint32_t da;
uint32_t pa;
uint32_t len;
uint32_t reserved[2];
char name[32];
};
/**
* struct fw_rsc_custom - used for custom resource types
* @type: type of resource
* @sub_type: type of custom resource
* @rsc_size: size of @rsc (in bytes)
* @rsc: the custom resource
*
* This resource allows for custom resources specific to an architecture or
* device.
*
* @type is the generic CUSTOM type, @sub_type is the specific custom resource,
* @rsc_size is the length of @rsc (in bytes), and @rsc is the actual
* parameters. These will be interpreted by the host-side device-specific
* driver.
*/
struct fw_rsc_custom {
uint32_t type;
uint32_t sub_type;
uint32_t rsc_size;
union fw_custom rsc;
};
#endif /* _RSC_TYPES_H_ */

View File

@@ -0,0 +1,18 @@
/*
* types.h - standard redefined types
*/
#ifndef _TYPES_H_
#define _TYPES_H_
typedef uint8_t __u8;
typedef uint16_t __u16;
typedef uint32_t __u32;
typedef uint64_t __u64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
#endif /* _TYPES_H_ */

186
lib/pru_rpmsg/pru_rpmsg.c Normal file
View File

@@ -0,0 +1,186 @@
/*
* Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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 following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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 : pru_rpmsg.c
*
* Summary : An RPMsg implementation for the PRU to use while communicating
* with the ARM host.
*
* Notes :
* - Implementaion of the interface described in "pru_rpmsg.h"
*/
#include <string.h>
#include <pru_rpmsg.h>
struct pru_rpmsg_hdr {
uint32_t src;
uint32_t dst;
uint32_t reserved;
uint16_t len;
uint16_t flags;
uint8_t data[0];
};
struct pru_rpmsg_ns_msg {
char name[RPMSG_NAME_SIZE];
char desc[RPMSG_NAME_SIZE];
uint32_t addr;
uint32_t flags;
};
int16_t pru_rpmsg_init(
struct pru_rpmsg_transport *transport,
struct fw_rsc_vdev_vring *vring0,
struct fw_rsc_vdev_vring *vring1,
uint32_t to_arm_event,
uint32_t from_arm_event
)
{
if (to_arm_event > MAX_VALID_EVENT || to_arm_event < MIN_VALID_EVENT)
return PRU_RPMSG_INVALID_EVENT;
if (from_arm_event > MAX_VALID_EVENT || from_arm_event < MIN_VALID_EVENT)
return PRU_RPMSG_INVALID_EVENT;
pru_virtqueue_init(&transport->virtqueue0, vring0, to_arm_event, from_arm_event);
pru_virtqueue_init(&transport->virtqueue1, vring1, to_arm_event, from_arm_event);
return PRU_RPMSG_SUCCESS;
}
int16_t pru_rpmsg_send(
struct pru_rpmsg_transport *transport,
uint32_t src,
uint32_t dst,
void *data,
uint16_t len
)
{
struct pru_rpmsg_hdr *msg;
uint32_t msg_len;
int16_t head;
struct pru_virtqueue *virtqueue;
/*
* The length of our payload is larger than the maximum RPMsg buffer size
* allowed
*/
if (len > (RPMSG_BUF_SIZE - sizeof(struct pru_rpmsg_hdr)))
return PRU_RPMSG_BUF_TOO_SMALL;
virtqueue = &transport->virtqueue0;
/* Get an available buffer */
head = pru_virtqueue_get_avail_buf(virtqueue, (void **)&msg, &msg_len);
if (head < 0)
return PRU_RPMSG_NO_BUF_AVAILABLE;
/* Copy local data buffer to the descriptor buffer address */
memcpy(msg->data, data, len);
msg->len = len;
msg->dst = dst;
msg->src = src;
msg->flags = 0;
msg->reserved = 0;
/* Add the used buffer */
if (pru_virtqueue_add_used_buf(virtqueue, head, msg_len) < 0)
return PRU_RPMSG_INVALID_HEAD;
/* Kick the ARM host */
pru_virtqueue_kick(virtqueue);
return PRU_RPMSG_SUCCESS;
}
int16_t pru_rpmsg_receive(
struct pru_rpmsg_transport *transport,
uint16_t *src,
uint16_t *dst,
void *data,
uint16_t *len
)
{
int16_t head;
struct pru_rpmsg_hdr *msg;
uint32_t msg_len;
struct pru_virtqueue *virtqueue;
virtqueue = &transport->virtqueue1;
/* Get an available buffer */
head = pru_virtqueue_get_avail_buf(virtqueue, (void **)&msg, &msg_len);
if (head < 0)
return PRU_RPMSG_NO_BUF_AVAILABLE;
/* Copy the message payload to the local data buffer provided */
memcpy(data, msg->data, msg->len);
*src = msg->src;
*dst = msg->dst;
*len = msg->len;
/* Add the used buffer */
if (pru_virtqueue_add_used_buf(virtqueue, head, msg_len) < 0)
return PRU_RPMSG_INVALID_HEAD;
/* Kick the ARM host */
pru_virtqueue_kick(virtqueue);
return PRU_RPMSG_SUCCESS;
}
int16_t pru_rpmsg_channel(
enum pru_rpmsg_ns_flags flags,
struct pru_rpmsg_transport *transport,
char *name,
char *desc,
int32_t port
)
{
struct pru_rpmsg_ns_msg ns_msg;
uint8_t i;
for (i = 0; i < RPMSG_NAME_SIZE; i++) {
ns_msg.name[i] = name[i];
ns_msg.desc[i] = desc[i];
}
ns_msg.addr = port;
ns_msg.flags = flags;
return pru_rpmsg_send(transport, port, 53, &ns_msg, sizeof(ns_msg));
}

View File

@@ -0,0 +1,16 @@
diff --git a/lib/pru_rpmsg/include/am335x/pru_iep.h b/lib/pru_rpmsg/include/am335x/pru_iep.h
index d877ddd..064fb42 100644
--- a/lib/pru_rpmsg/include/am335x/pru_iep.h
+++ b/lib/pru_rpmsg/include/am335x/pru_iep.h
@@ -251,6 +251,11 @@ typedef struct {
} pruIep;
+#ifdef __GNUC__
+static volatile pruIntc *__CT_IEP = (void *)0x0002e000;
+#define CT_IEP (*__CT_INTC)
+#else
volatile __far pruIep CT_IEP __attribute__((cregister("PRU_IEP", far), peripheral));
+#endif
#endif /* _PRU_IEP_H_ */

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