diff --git a/.gitignore b/.gitignore index 7740f2c..294aae5 100644 --- a/.gitignore +++ b/.gitignore @@ -40,12 +40,15 @@ # Debug files *.dSYM/ +.cache/ # Generated robcmp -bison.hpp run_test/out/* -src/Language_y.output +src/*_y.output +src/*_gen_*.* +src/*_gen.y +src/*_l.cpp .vscode/** *.tar.gz *.bin @@ -58,3 +61,15 @@ llvm-objcopy llvm-ranlib avr-ld .vscode +refdatasheets +build +test/general/out +test/general/temp.spec +test/atmega328p/out +test/atmega1284p/out +test/stm32f1/out +platformio/toolchain-robcmp/bin +platformio/toolchain-robcmp/lib +platformio/avr-gdb-build +Documentation +hack diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b7d0622 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.20.0) +cmake_policy(SET CMP0054 NEW) + +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE) +set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -fno-exceptions") +set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -fno-exceptions") +add_compile_definitions() + +project(robcmp) + +set(CMAKE_CXX_STANDARD 17) + +message(STATUS "CC Compiler used: ${CC}") + +find_package(LLVM REQUIRED CONFIG) +find_package(FLEX 2.6 REQUIRED) +find_package(BISON 3.8 REQUIRED) + +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include_directories(${LLVM_INCLUDE_DIRS} ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) +separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) +add_definitions(${LLVM_DEFINITIONS_LIST}) + +file(GLOB robcmp_SRC CONFIGURE_DEPENDS + "src/*.cpp" + "src/**/*.cpp" +) + +flex_target(lexer "${CMAKE_CURRENT_SOURCE_DIR}/src/Language.l" "${CMAKE_BINARY_DIR}/Language_l.cpp") + +bison_target(scanner_main + "${CMAKE_BINARY_DIR}/Language_gen.y" + "${CMAKE_BINARY_DIR}/Language_gen.cpp" + DEFINES_FILE "${CMAKE_BINARY_DIR}/Language_gen_y.hpp" + COMPILE_FLAGS "-Wall -Wno-deprecated") +bison_target(scanner_use + "${CMAKE_BINARY_DIR}/LanguageUse_gen.y" + "${CMAKE_BINARY_DIR}/LanguageUse_gen.cpp" + COMPILE_FLAGS "-Wall -Wno-deprecated") + +# Language_gen.y +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/Language_gen.y + COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageHeader.y ${CMAKE_CURRENT_SOURCE_DIR}/src/Language.y > ${CMAKE_BINARY_DIR}/Language_gen.y + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageHeader.y ${CMAKE_CURRENT_SOURCE_DIR}/src/Language.y +) +# LanguageUse_gen.y +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/LanguageUse_gen.y + COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageHeader.y ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageUse.y > ${CMAKE_BINARY_DIR}/LanguageUse_gen.y + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageHeader.y ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageUse.y +) +add_custom_target(parsers + DEPENDS ${CMAKE_BINARY_DIR}/Language_gen.y ${CMAKE_BINARY_DIR}/LanguageUse_gen.y) + +add_executable(robcmp + ${FLEX_lexer_OUTPUTS} + ${BISON_scanner_main_OUTPUTS} ${BISON_scanner_use_OUTPUTS} + ${robcmp_SRC}) + +add_flex_bison_dependency(lexer scanner_main) +add_flex_bison_dependency(lexer scanner_use) +add_dependencies(robcmp parsers) + +find_library(LLVM_MONOLITHIC_LIBRARY LLVM HINTS ${LLVM_LIBRARY_DIRS}) + +if (LLVM_MONOLITHIC_LIBRARY) + message(STATUS "LLVM is using monolithic libLLVM.so") + target_link_libraries(robcmp LLVM) +else() + llvm_map_components_to_libnames(llvm_libs support core irreader passes + armasmparser armcodegen + avrasmparser avrcodegen + x86asmparser x86codegen) + + target_link_libraries(robcmp ${llvm_libs}) +endif() + +set_target_properties(robcmp PROPERTIES + VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + VS_DEBUGGER_COMMAND_ARGUMENTS "-a atmega328p -Oz ../platformio/samples/atmega328p-blink/src/main.rob") diff --git a/Documentation/info b/Documentation/info deleted file mode 100644 index 393d4da..0000000 --- a/Documentation/info +++ /dev/null @@ -1,123 +0,0 @@ -ArrayElements - ArrayElements(); - vector elements - append (ArrayElement& e) - - getArraySize () - getStructSize () - getElementCount (int position) - getStructElement (int position) - getArrayType() - -AttachInterrupt - AttachInterrupt(int port, string name, int event) - -BinaryOp - BinaryOp (Node *l, int op, Node *r) - accept (Visitor &v) - getOperator () - -Capsule - Capsule (Node *n) - -CmpOp - CmpOp (Node *l, int op, Node *r) - accept (Visitor &v) - getOperator () - -Coercion - Convert (Value *v, Type *destty, BasicBlock *block, bool unsig = false) - -Delay - Delay (Node *mseg) - accept (Visitor &v) - -Float - Float (float n) - -FunctionCall - FunctionCall (string name) - -FunctionDecl - FunctionDecl (string name, Node *stmts) - - bool isFunctionDecl() - -If - If (Node *e, Node *tst, Node *est) - accept (Visitor& v) - -InPort - InPort (const char *p) - -Int8 - Int8 (char n) - getNumber () - accept (Visitor &v) - -Int16 - Int16 (short n) - getNumber () - accept (Visitor &v) - -Int32 - Int32 (int n) - getNumber ( ) - accept (Visitor &v); - -Load - Load (const char *i) - getIdent () - accept (Visitor& v) - -LoadMatrix - LoadMatrix (const char *i, int pos_1, int pos_2) - -LoadVector - LoadVector (const char *i, int pos) - -Matrix - Matrix (const char *n, MatrixElements *me) - -Node - isFunctionDecl() - Node () - vector const& children() - acceot (visitor &) - -OutPort - OutPort (const char *p, Node *e) - -Print - Print (Node *e) - -Program - Program (Stmts *stmts) - declara_auxiliary_c_funcs () - -Return - Return (Node *n) - -Scalar - Scalar (const char *n, Node *e) - getIdent () - accept (Visitor& v) - -Semantic - Verification () - -Stmts - Stmts (Node *s) - vector const& children() - append (Node *s) - prepend (Node *s) - -String - String (const char *s) - -Vector - Vector (const char *n, ArrayElements *aes) - -While - While (Node *e, Node *stms) - accept (Visitor& v) diff --git a/Ex1.txt b/Ex1.txt deleted file mode 100644 index dab5a70..0000000 --- a/Ex1.txt +++ /dev/null @@ -1,18 +0,0 @@ - -c1 = 1; -c2 = 0; -z = c1 + c2; - -print z; - -i = 1; -while (i <= c1){ - x = c1 + i; - i++; -} -b = func_name(2, 2, 2); -print b; - -int func_name(int a, int b, int c){ - return (a*b)+c; -} diff --git a/Documentation/LICENSE b/LICENSE similarity index 100% rename from Documentation/LICENSE rename to LICENSE diff --git a/Makefile b/Makefile.old similarity index 65% rename from Makefile rename to Makefile.old index 826f4da..ec56055 100644 --- a/Makefile +++ b/Makefile.old @@ -27,35 +27,47 @@ COMPILER_NAME=$(shell basename "${PWD}") SRC = src BIN = . -FLAGS=-O3 -march=native -flto -#DFLAGS=-ggdb -O0 +#FLAGS=-O3 -march=native -flto +DFLAGS=-ggdb -O0 -std=c++17 +SCANNERS=src/Language_gen.y src/LanguageUse_gen.y CPPS=$(patsubst src/%.cpp,src/out/%.o,$(wildcard ${SRC}/*.cpp)) -YACS=$(patsubst src/%.y,src/out/%_y.o,$(wildcard ${SRC}/*.y)) +YACS=$(patsubst src/%.y,src/out/%_y.o,$(SCANNERS)) LEXS=$(patsubst src/%.l,src/out/%_l.o,$(wildcard ${SRC}/*.l)) all: src/out $(COMPILER_NAME) %_l.cpp: %.l - lex -o $@ $< + flex -o $@ $< + +.PRECIOUS : %_l.cpp %_y.cpp %_y.hpp +.SECONDARY : $(SCANNERS) + +-include $(CPPS:%.o=%.d) + +main.cpp : %_l.cpp %_y.cpp %_y.hpp + +%_gen.y : src/LanguageHeader.y %.y + -chmod u+w $@ + cat $^ > $@ + chmod u-w $@ %_y.cpp: %.y - bison -Wall --report=state --defines=$(SRC)/bison.hpp -o $@ $< + bison -Wall --defines=$(patsubst %.cpp,%.hpp,$@) -o $@ $< $(SED) 's/\"syntax\ error\"/COLOR_RED\ \"syntax\ error\"\ COLOR_RESET/' -i $@ $(SED) 's/\"syntax\ error:/COLOR_RED\ \"syntax\ error:\"\ COLOR_RESET\"/' -i $@ $(SED) 's/\"syntax\ error,/COLOR_RED\ \"syntax\ error:\"\ COLOR_RESET\"/' -i $@ $(COMPILER_NAME): ${YACS} ${LEXS} ${CPPS} - ${CC} -std=c++11 ${FLAGS} ${DFLAGS} ${SRC}/out/*.o ${LLVMLIBS} -o $(BIN)/$@ + ${CC} ${FLAGS} ${DFLAGS} -std=c++17 ${SRC}/out/*.o ${LLVMLIBS} -o $(BIN)/$@ src/out/%.o: src/%.cpp - ${CC} -std=c++11 ${LLVMFLAGS} ${FLAGS} ${DFLAGS} -c $< -o $@ + ${CC} ${LLVMFLAGS} ${FLAGS} ${DFLAGS} -MMD -std=c++17 -c $< -o $@ src/out: mkdir ${SRC}/out clean: - rm -f ${SRC}/*_y.cpp ${SRC}/*_l.cpp ${SRC}/bison.hpp ${SRC}/out/*.o + rm -f ${SRC}/*_y.{hpp,cpp} ${SRC}/*_l.{hpp,cpp} ${SRC}/out/*.o #.SILENT: -.PRECIOUS: bison.hpp diff --git a/Teste_Matrix.txt b/Teste_Matrix.txt deleted file mode 100644 index c4f36a5..0000000 --- a/Teste_Matrix.txt +++ /dev/null @@ -1,10 +0,0 @@ -vector_name = {{0:3, 2:3, 1}:2}; - -i = 0; -j = 0; - -while (i < 7){ - b = vector_name[i][j]; - print b; - i = i+1; -} diff --git a/butbuil b/butbuil new file mode 100755 index 0000000..a8cef49 --- /dev/null +++ b/butbuil @@ -0,0 +1,6 @@ +CXX=clang++ +CC=clang +export CXX +export CC +cmake -DCMAKE_BUILD_TYPE="Debug" .. +#cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_BUILD_TYPE="Debug" .. diff --git a/compare/Ex1.c b/compare/Ex1.c deleted file mode 100644 index 581f8d1..0000000 --- a/compare/Ex1.c +++ /dev/null @@ -1,16 +0,0 @@ -#include - -int func_name (int a, int b, int c){ - return (a * b) + c; -} - -void main (){ - int c1 = 1, c2 = 0, int x; - int z = c1 + c2; - - printf ("%d", z); - - for (i = 1; i <= c1; i++){ - x = c1 + i; - } -} diff --git a/compare/Ex1.txt b/compare/Ex1.txt deleted file mode 100644 index 2f144e5..0000000 --- a/compare/Ex1.txt +++ /dev/null @@ -1,18 +0,0 @@ -int func_name(int a, int b, int c){ - return (a * b) + c; -} - -c1 = 1; -c2 = 0; -z = c1 + c2; - -print z; - -i = 1; -while (i <= c1){ - x = c1 + i; - i++; -} -b = func_name(2, 2, 2); -print b; - diff --git a/compare/Ex2.c b/compare/Ex2.c deleted file mode 100644 index 16d223a..0000000 --- a/compare/Ex2.c +++ /dev/null @@ -1,19 +0,0 @@ -#include - -void funct(int a){ - printf ("%d", a); -} - -void main(){ - int x = 5; - printf ("%d\n", x); - funct(x); - - printf ("%d\n", x); - int y; - funct(y); - - - -} - diff --git a/compare/Makefile b/compare/Makefile deleted file mode 100644 index cd37668..0000000 --- a/compare/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -ALL_LL=$(patsubst %.txt,out/%.ll,$(wildcard *.txt)) -ALLOBJS=$(patsubst %.ll,%.o,${ALL_LL}) -ALLASM=$(patsubst %.ll,%.s,${ALL_LL}) -ALLBIN=$(patsubst %.ll,%,${ALL_LL}) - -COMPILER_NAME=../robcmp - -all: ${ALL_LL} ${ALLASM} ${ALLOBJS} ${ALLBIN} - -clean: - rm -f ${ALLBIN} ${ALLASM} ${ALLOBJS} ${ALL_LL} - -out/%.ll : %.txt ${COMPILER_NAME} - ${COMPILER_NAME} $< > $@ - -%.o : %.ll - llc-9 $< -o $@ -filetype=obj - -%.s : %.ll - llc-9 $< -o $@ -filetype=asm - -core.o : debug.c - gcc debug.c -o core.o -c - -% : %.s core.o - gcc core.o $< -o $@ -lncurses - diff --git a/compare/Remember b/compare/Remember deleted file mode 100644 index c66600a..0000000 --- a/compare/Remember +++ /dev/null @@ -1 +0,0 @@ -gcc -O2 debug.o nome.c -o exec -lncurses diff --git a/compare/debug.c b/compare/debug.c deleted file mode 100644 index de38122..0000000 --- a/compare/debug.c +++ /dev/null @@ -1,179 +0,0 @@ - -#include -#include -#include -#include - -void onexit(void) __attribute__ ((destructor)); - -#define ARDUINO_PORTS 14 -int arduino_out_ports[ARDUINO_PORTS]; -int steppers_pos[3] = {0}; - -#define LCD_ROWS 6 -#define LCD_COLS 14 -#define LCD_CHARS (LCD_ROWS*LCD_COLS) -char display[LCD_CHARS]; -int display_pos = 0; -char last_msg[1000]; - -char *port_names[ARDUINO_PORTS] = { - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "14", -}; - -void refresh_screen() { - - mvprintw(1, 1, "Simulador de E/S para Robcmp"); - mvprintw(2, 1, "----------------------------"); - - mvprintw(6, 1, "Ultima msg: "); - attron(COLOR_PAIR(3)); - mvprintw(6, 14, "%s ", last_msg); - attroff(COLOR_PAIR(3)); - - int currow = 10; - mvprintw(currow++, 1, "[ Mensagens print ]"); - mvprintw(currow++, 1, "---------------"); - attron(COLOR_PAIR(2)); - for(int r=0; r ARDUINO_PORTS) { - attron(COLOR_PAIR(3)); - sprintf(last_msg, "Erro: porta %d nao existe.", - port); - attroff(COLOR_PAIR(3)); - } else { - arduino_out_ports[port] = value; - } - - refresh_screen(); -} - -void delay(int milis) { - attron(COLOR_PAIR(3)); - sprintf(last_msg, "Delay %d milis", milis); - attroff(COLOR_PAIR(3)); - refresh_screen(); - - usleep(milis*1000); -} - -void stepper_goto(int stepper, int pos) { - attron(COLOR_PAIR(3)); - sprintf(last_msg, "Motor %d move para posicao %d.", stepper, pos); - attroff(COLOR_PAIR(3)); - refresh_screen(); - usleep(1e6); -} - -void servo_goto(int pos) { - attron(COLOR_PAIR(3)); - if (pos >= 0 && pos <= 30) { - sprintf(last_msg, "Servo move para posicao %d.", pos); - } else { - sprintf(last_msg, "Servo nao pode se mover para posicao %d (0-30).", pos); - } - attroff(COLOR_PAIR(3)); - refresh_screen(); - usleep(1e6); -} - -void onexit(void) { - getchar(); - curs_set(1); - clear(); - endwin(); -} - -/*int main() { - - int r = 10; - float d = 100.903; - - print(1, &d); - print(0, &r); -} -*/ diff --git a/docs/download/robcmp-Darwin-x86_64-0.1.tar.gz b/docs/download/robcmp-Darwin-x86_64-0.1.tar.gz deleted file mode 100644 index 787cfb4..0000000 Binary files a/docs/download/robcmp-Darwin-x86_64-0.1.tar.gz and /dev/null differ diff --git a/docs/download/robcmp-Linux-x86_64-0.1.tar.gz b/docs/download/robcmp-Linux-x86_64-0.1.tar.gz deleted file mode 100644 index 50a904e..0000000 Binary files a/docs/download/robcmp-Linux-x86_64-0.1.tar.gz and /dev/null differ diff --git a/gcc_llvm/function_parameters.c b/gcc_llvm/function_parameters.c deleted file mode 100644 index 338579f..0000000 --- a/gcc_llvm/function_parameters.c +++ /dev/null @@ -1,8 +0,0 @@ -int func(int var){ - return var; -} - -int main(){ - int var = 2; - func(var); -} diff --git a/gcc_llvm/matrix.c b/gcc_llvm/matrix.c deleted file mode 100644 index 0391857..0000000 --- a/gcc_llvm/matrix.c +++ /dev/null @@ -1,9 +0,0 @@ - -int main () -{ - int a[3][2]; - - a[2][1] = 2; - -} - diff --git a/hack/avr/Makefile b/hack/avr/Makefile index a5ae5a6..195b50a 100644 --- a/hack/avr/Makefile +++ b/hack/avr/Makefile @@ -1,9 +1,9 @@ INCLUDES=-I/Users/thborges/.platformio/packages/toolchain-atmelavr/avr/include #AVRLIB=-L~/.platformio/packages/toolchain-atmelavr/lib/gcc/avr/7.3.0/avr5 -lgcc -CC=/usr/local/robllvm/bin/clang -LLC=/usr/local/robllvm/bin/llc +CC=clang +LLC=llc CCPLAT=-target avr -mmcu=atmega328p -DF_CPU=16000000 -ROBCMP=../../robcmp +ROBCMP=../../build/robcmp AVRDUDECFG=-C /Users/thborges/.platformio/packages/tool-avrdude/avrdude.conf AVRDUDEPORT=`ls /dev/cu.usb*` @@ -18,7 +18,7 @@ all: ${ROBCMP} ${ALL} ${CC} ${CCPLAT} -Oz -S -emit-llvm ${INCLUDES} $< -o $@ %.c.o: %.c - ${CC} ${CCPLAT} -Oz -c ${INCLUDES} $< -o $@ + ${CC} ${CCPLAT} -ggdb -O0 -c ${INCLUDES} $< -o $@ @@ -36,10 +36,13 @@ all: ${ROBCMP} ${ALL} %.elf : %.o @#${CC} -v ${CCPLAT} ${AVRLIB} $< -o $@ @#avr-gcc -v -mmcu=atmega328p $< -o $@ - avr-ld -o $@ --gc-sections -Tdata=0x800100 $< + #avr-ld -o $@ -Tdata=0x800100 $< + ld.lld -o $@ -Tdata=0x800100 $< + %.hex : %.elf - avr-objcopy -Oihex $< $@ + #avr-objcopy -Oihex $< $@ + llvm-objcopy -Oihex $< $@ %.up: %.hex avrdude ${AVRDUDECFG} -v -V -c arduino -p m328p -U flash:w:$<:i -P ${AVRDUDEPORT} diff --git a/hack/debug/Makefile b/hack/debug/Makefile new file mode 100644 index 0000000..a2f81c1 --- /dev/null +++ b/hack/debug/Makefile @@ -0,0 +1,39 @@ +AVRDUDECFG=-C /Users/thborges/.platformio/packages/tool-avrdude/avrdude.conf +AVRDUDEPORT=`ls /dev/cu.usb*` + +#OPT=-O0 -g +OPT=-Os + +all: avr5.o main.o main.lld.elf main.lld.size main.avr.elf main.avr.size + +avr5.o: avr5.s + avr-gcc -mmcu=atmega328p -O3 -c avr5.S + +main.ll: main.rob + robcmp -a avr328p ${OPT} $< > $@ + +main.o: main.rob + robcmp -a avr328p ${OPT} $< -o $@ + @#ld -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem main.o -o main + +main.c.o: main.c + avr-gcc ${OPT} -mmcu=atmega328p -c $< -o $@ + +main.avr.elf: main.c.o + avr-gcc -Wl,--gc-sections ${OPT} -mmcu=atmega328p $< -o $@ + +main.lld.elf: main.o avr5.o + @#clang-16 -v -fuse-ld=lld -e main -target avr -mmcu=atmega328p main.o -o main.elf + ld.lld --gc-sections -o $@ -L../../share/avr/ -Tavr328p.ld -Tdata=0x800100 -e main ${LOPT} main.o avr5.o + +%.hex : %.elf + avr-objcopy -Oihex $< $@ + +%.up: %.hex + avrdude ${AVRDUDECFG} -v -V -c arduino -p m328p -U flash:w:$<:i -P ${AVRDUDEPORT} + +%.size: %.elf + avr-size $< + +clean: + rm -f *.o *.elf *.ll *.hex diff --git a/hack/debug/avr5.S b/hack/debug/avr5.S new file mode 100644 index 0000000..d0013a1 --- /dev/null +++ b/hack/debug/avr5.S @@ -0,0 +1,112 @@ +/* + * Code excerpt from libgcc + * vim: syntax=nasm + */ + +#define A0 26 +#define B0 18 +#define C0 22 + +#define A1 A0+1 + +#define B1 B0+1 +#define B2 B0+2 +#define B3 B0+3 + +#define C1 C0+1 +#define C2 C0+2 +#define C3 C0+3 + +#define __zero_reg__ r1 +#define __tmp_reg__ r0 + + +.macro DEFUN name +.global \name +.func \name +\name: +.endm + + +.macro ENDF name +.size \name, .-\name +.endfunc +.endm + + +.macro wmov r_dest, r_src + movw \r_dest, \r_src +.endm + + +;;; R25:R22 = (unsigned long) R27:R26 * (unsigned long) R19:R18 +;;; C3:C0 = (unsigned long) A1:A0 * (unsigned long) B1:B0 +;;; Clobbers: __tmp_reg__ +DEFUN __umulhisi3 + mul A0, B0 + movw C0, r0 + mul A1, B1 + movw C2, r0 + mul A0, B1 +;;#ifdef __AVR_HAVE_JMP_CALL__ + ;; This function is used by many other routines, often multiple times. + ;; Therefore, if the flash size is not too limited, avoid the RCALL + ;; and inverst 6 Bytes to speed things up. + add C1, r0 + adc C2, r1 + clr __zero_reg__ + adc C3, __zero_reg__ +;;#else +;; rcall 1f +;;#endif + mul A1, B0 +1: add C1, r0 + adc C2, r1 + clr __zero_reg__ + adc C3, __zero_reg__ + ret +ENDF __umulhisi3 + + +;;; R25:R22 = (unsigned long) R27:R26 * R21:R18 +;;; (C3:C0) = (unsigned long) A1:A0 * B3:B0 +;;; Clobbers: __tmp_reg__ +DEFUN __muluhisi3 + call __umulhisi3 + mul A0, B3 + add C3, r0 + mul A1, B2 + add C3, r0 + mul A0, B2 + add C2, r0 + adc C3, r1 + clr __zero_reg__ + ret +ENDF __muluhisi3 + +/******************************************************* + Multiplication 32 x 32 with MUL +*******************************************************/ + +;;; R25:R22 = R25:R22 * R21:R18 +;;; (C3:C0) = C3:C0 * B3:B0 +;;; Clobbers: R26, R27, __tmp_reg__ +DEFUN __mulsi3 + movw A0, C0 + push C2 + push C3 + call __muluhisi3 + pop A1 + pop A0 + ;; A1:A0 now contains the high word of A + mul A0, B0 + add C2, r0 + adc C3, r1 + mul A0, B1 + add C3, r0 + mul A1, B0 + add C3, r0 + clr __zero_reg__ + ret +ENDF __mulsi3 + diff --git a/hack/debug/main.c b/hack/debug/main.c new file mode 100644 index 0000000..8283733 --- /dev/null +++ b/hack/debug/main.c @@ -0,0 +1,52 @@ + +typedef struct { + char pin8 : 1; + char pin9 : 1; + char pin10 : 1; + char pin11 : 1; + char pin12 : 1; + char pin13 : 1; + char others : 2; +} ddrb_t; + + +typedef struct { + char pin8 : 1; + char pin9 : 1; + char pin10 : 1; + char pin11 : 1; + char pin12 : 1; + char pin13 : 1; + char others : 2; +} portb_t; + + +void wait(long qtd) { + volatile long q = qtd; + while(q > 0) { + q--; + } +} + +int main() { + volatile ddrb_t *ddrb = (ddrb_t*)0x24; + volatile portb_t *portb = (portb_t*)0x25; + + char a = ddrb->pin13; + + ddrb->pin13 = 1; //output + char i = 10; + for(;;) { + // blink + portb->pin13 = 0; + wait(i*100000); + portb->pin13 = 1; + wait(i*100000); + + i--; + if (i == 0) { + i = 10; + } + } +} + diff --git a/hack/debug/main.rob b/hack/debug/main.rob new file mode 100644 index 0000000..5944faa --- /dev/null +++ b/hack/debug/main.rob @@ -0,0 +1,91 @@ + +void main(); +void __init(); +void __bad_irq(); + +void __vectors() { + /* atmega328p has 26 interruptions */ + asm "jmp __init"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; +} + +void __bad_irq() { + __vectors(); +} + +register int8 SREG at 0x3f; +register int16 STACK at 0x3d; + +void __init() { + SREG = 0; + STACK = 0x0AFF; + main(); + loop { asm "nop"; } +} + +register int8 ddrb at 0x24 { + bool pin8; + bool pin9; + bool pin10; + bool pin11; + bool pin12; + bool pin13; +} + +register int8 portb at 0x25 { + bool pin8; + bool pin9; + bool pin10; + bool pin11; + bool pin12; + bool pin13; +} + +void wait(int32 qtd) { + volatile q = qtd; + while(q > 0) { + q--; + } +} + +void main() { + ddrb.pin13 = true; //output + i = 10; + loop { + // blink + portb.pin13 = false; + wait(i*100000); + portb.pin13 = true; + wait(i*100000); + + i--; + if (i == 0) { + i = 10; + } + } +} + diff --git a/hack/stm32/Makefile b/hack/stm32/Makefile index 5e5e397..d37acf4 100644 --- a/hack/stm32/Makefile +++ b/hack/stm32/Makefile @@ -1,10 +1,11 @@ -#GCC=~/.platformio/packages/toolchain-gccarmnoneeabi/bin/arm-none-eabi-gcc -CC=/usr/local/robllvm/bin/clang -LLC=/usr/local/robllvm/bin/llc -OBJCOPY=/usr/local/robllvm/bin/llvm-objcopy +CC=~/.platformio/packages/toolchain-gccarmnoneeabi/bin/arm-none-eabi-gcc +#CC=/usr/local/opt/llvm/bin/clang +LLC=/usr/local/opt/llvm/bin/llc +OBJCOPY=/usr/local/opt/llvm/bin/llvm-objcopy INCLUDES= -CCPLAT=-target arm-none-eabi -mcpu=cortex-m3 -mthumb -ROBCMP=../../robcmp +#CCPLAT=-target arm-none-eabi -mcpu=cortex-m3 -mthumb +CCPLAT=-mcpu=cortex-m3 -mthumb +ROBCMP=../../build/robcmp USBPORT=`ls /dev/cu.usb*` @@ -15,10 +16,11 @@ ALL=${ALL_C} ${ALL_ROB} all: ${ROBCMP} ${ALL} %.c.ll: %.c - ${CC} ${CCPLAT} -Oz -S -emit-llvm ${INCLUDES} $< -o $@ + #${CC} ${CCPLAT} -Oz -S -emit-llvm ${INCLUDES} $< -o $@ + ${CC} ${CCPLAT} -Os -S -emit-llvm ${INCLUDES} $< -o $@ %.c.o: %.c - ${CC} ${CCPLAT} -Oz -c ${INCLUDES} $< -o $@ + ${CC} -v ${CCPLAT} -Os -c ${INCLUDES} $< -o $@ @@ -34,8 +36,8 @@ all: ${ROBCMP} ${ALL} ${LLC} $< -o $@ -filetype=asm %.elf : %.o - ${CC} -v ${CCPLAT} -nostdlib -Wl,-entry=main -Wl,-Tmemory.lld.ld $< -o $@ - @#${GCC} -mthumb -mcpu=cortex-m3 -nostdlib -Wl,-Tmemory.gcc.ld $< -o $@ + #${CC} ${CCPLAT} -nostdlib -Wl,-entry=main -Wl,-Tmemory.lld.ld $< -o $@ + ${CC} -mthumb -mcpu=cortex-m3 -nostdlib -Wl,-Tmemory.gcc.ld $< -o $@ %.bin : %.elf diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..797992b --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,23 @@ + +GEN=avr5.o avr51.o cortex-m3-arm-missing.o cortex-m0plus-arm-missing.o + +all: ${GEN} + +avr5.o: avr5.S + @#here we are interested in the fastest possible code, intead of size + @#avr-gcc -mmcu=avr5 -O3 -c $< + clang --target=avr -mmcu=avr5 -O3 -c $< + +avr51.o: avr51.S + @#here we are interested in the fastest possible code, intead of size + @#avr-gcc -mmcu=avr5 -O3 -c $< + clang --target=avr -mmcu=avr51 -O3 -c $< + +cortex-m3-arm-missing.o: arm-missing.c + clang --target=arm-none-eabi -mcpu=cortex-m3 -mthumb -O3 -c $< -o $@ + +cortex-m0plus-arm-missing.o: arm-missing.c + clang --target=arm-none-eabi -mcpu=cortex-m0plus -mthumb -O3 -c $< -o $@ + +clean: + rm -f ${GEN} diff --git a/lib/arch/Makefile b/lib/arch/Makefile new file mode 100644 index 0000000..0f3c346 --- /dev/null +++ b/lib/arch/Makefile @@ -0,0 +1,22 @@ +ATDF=$(shell find . -type f -name '*.atdf') +GEN_SVDS=$(patsubst %.atdf,%.svd,$(ATDF)) + +SVD := $(shell find . -type f -name '*.svd') +DIRS := $(sort $(dir $(SVD))) +ALL_ROBS := $(foreach d,$(DIRS),$(d)regs.rob) + +all: pre $(ALL_ROBS) + +pre: $(GEN_SVDS) + +.SECONDARY: +%.svd : %.atdf + atdf2svd $< > $@ + +define SVD_template +$(1)regs.rob: $(wildcard $(1)*.svd) svd2rob.py + python3 svd2rob.py $$< > $$@ +endef + +$(foreach d,$(DIRS),$(eval $(call SVD_template,$(d)))) + diff --git a/lib/arch/README b/lib/arch/README new file mode 100644 index 0000000..42660e7 --- /dev/null +++ b/lib/arch/README @@ -0,0 +1,6 @@ +AFDT files for AVRs +- http://packs.download.atmel.com +- To convert from .afdt to .svd, use atdf2svd from Rust language, available through cargo install + +SVDs files for STM32 can be downloaded at: +- https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html#cad-resources under System View Description diff --git a/lib/arch/avr/avr5mcu.rob b/lib/arch/avr/avr5mcu.rob new file mode 100644 index 0000000..4684cd4 --- /dev/null +++ b/lib/arch/avr/avr5mcu.rob @@ -0,0 +1,342 @@ + +use intfs.mcu; +use intfs.ports; +use intfs.databus; +use assert; +use avr5regs; + +void __delay_us(); + +int_usart_rx = interrupt_i8(); + +void check_irq_handler(uint8 h) { + assert(h != void, "IRQ enabled without setting the handler."); +} + +/*void irq_usart_rx() signal, section __irqs { + check_irq_handler(typeid(int_usart_rx)); + byte = UDR0; + int_usart_rx.handler(byte); +}*/ + +type avr5mcu implements mcu { + + uint32 clock() inline { + return 16E6; + } + + void set_interruptions(bool enabled) inline { + if enabled { + asm "sei"; + } else { + asm "cli"; + } + } + + /* implement this idea later! + template digport { + void mode(m port_mode) { port_config = mode; } + void set(bool v) { port = v; } + bool get() { return port; } + } + b0 = digport + */ + + b0 implements digitalport { + void mode(port_mode m) inline { ddrb.b0 = m; } + void set(bool v) inline { portb.b0 = v; } + bool get() inline { return portb.b0; } + } + + b1 implements digitalport { + void mode(port_mode m) inline { ddrb.b1 = m; } + void set(bool v) inline { portb.b1 = v; } + bool get() inline { return portb.b1; } + } + + b2 implements digitalport { + void mode(port_mode m) inline { ddrb.b2 = m; } + void set(bool v) inline { portb.b2 = v; } + bool get() inline { return portb.b2; } + } + + b3 implements digitalport { + void mode(port_mode m) inline { ddrb.b3 = m; } + void set(bool v) inline { portb.b3 = v; } + bool get() inline { return portb.b3; } + } + + b4 implements digitalport { + void mode(port_mode m) inline { ddrb.b4 = m; } + void set(bool v) inline { portb.b4 = v; } + bool get() inline { return portb.b4; } + } + + b5 implements digitalport { + void mode(port_mode m) inline { ddrb.b5 = m; } + void set(bool v) inline { portb.b5 = v; } + bool get() inline { return portb.b5; } + } + + void enable_led() { + b5.mode(port_mode.output); + } + + void set_led(bool s) { + b5.set(s); + } + + void busy_wait_loop1(uint16 count) noopt { + /* trusting that ABI will put the count parameter in r25:r24 + sbiw takes 2 cycles + brne takes 2 cycles when branching, 1 when not + ret +1 cycle */ + asm "1: + sbiw r24, 1 + brne 1b"; // a ret is appended here + } + + void busy_wait_loop5(uint16 count) noopt { + /* trusting that ABI will put the count parameter in r25:r24 + cycles total: 3 + count*5-1 + 3 + +2 (ldi r25:r24 prior to cal) + count*5 - 1 + 3 + +1 (ser) + +count*5-1 (loop) + +2 (rjmp) + +1 (ret) */ + asm "ser r18 + busy_wait_loop5_loop: + subi r18,1 + sbci r24,0 + sbci r25,0 + brne busy_wait_loop5_loop + rjmp busy_wait_loop5_end + busy_wait_loop5_end: "; // a ret is appended here + } + + void wait_us(uint16 us) { + count = uint16(clock() / 4e6) * us - 1; + busy_wait_loop1(count); + } + + // secure range 1 -- 5460 + void wait_ms(uint16 ms) { + count = uint16(clock() / 1280e3) * ms - 1; + busy_wait_loop5(count); + } + + spi implements databus { + /* setup hardware SPI at: + b2 = SS + b3 = MOSI + b4 = MISO + b5 = SCK */ + void setup(uint32 speed) { + b3.mode(port_mode.output); + b4.mode(port_mode.input); + b5.mode(port_mode.output); + + // set SS pin high before enabling master mode + // (mandatory for master mode) + b2.mode(port_mode.output); + b2.set(true); + SPCR.MSTR = true; // master + + //TODO: ignoring speed for now. Set to fsck/4 = 4Mhz + SPSR.SPI2x = false; + SPCR.SPR0 = false; + SPCR.SPR1 = false; + + SPCR.CPOL = false; + SPCR.CPHA = false; + } + + void async_read_to(interrupt_i8 i) {} + + void enable() { + SPCR.SPE = true; + } + + void disable() { + SPCR.SPE = false; + } + + void write(uint8 b) { + SPDR = b; + while !SPSR.SPIF; + } + + void write_array(int8[] data) { + i = 0u; + while i < data.size { + SPDR = uint8(data[i]); + while !SPSR.SPIF; + i++; + } + } + + uint8 read() { + //TODO: Verify correctness + while !SPSR.SPIF; + return SPDR; + } + + bool has_data() { + //TODO: Verify correctness + return SPSR.SPIF; + } + + bool start_transaction(uint16 address) { return true; } + void end_transaction() { return; } + + databus_protocol get_protocol() { + return databus_protocol.SPI; + } + } + + uart0 implements databus { + + void setup(uint32 baud) { + // use 2x + UCSR0A.U2X0 = false; + + multipl = 16u; + if UCSR0A.U2X0 { + multipl = 8u; + } + + div = uint32(baud) * multipl; + velocity = (clock() / div) - 1; + + // set baudrate + UBRR0 = uint16(velocity); + + // 8 bit + UCSR0B.UCSZ02 = false; + UCSR0C.UCSZ0 = 0x3; + + // no parity + UCSR0C.UPM0 = 0x0; + + // 1 stop bit + UCSR0C.USBS0 = false; + } + + void async_read_to(interrupt_i8 i) { + //int_usart_rx = i; + UCSR0B.RXCIE0 = true; + } + + void enable() { + // enable tx and rx + UCSR0B.RXEN0 = true; + UCSR0B.TXEN0 = true; + } + + void disable() { + // disable tx and rx + UCSR0B.RXEN0 = false; + UCSR0B.TXEN0 = false; + // disable RX interruption + UCSR0B.RXCIE0 = false; + } + + void write(uint8 b) inline { + while !UCSR0A.UDRE0; + UDR0 = b; + } + + void write_array(int8[] data) { + i = 0u; + while i < data.size { + write(uint8(data[i])); + i++; + } + } + + uint8 read() inline { + while !UCSR0A.RXC0; + return UDR0; + } + + bool has_data() inline { + return UCSR0A.RXC0; + } + + bool start_transaction(uint16 address) inline { return true; } + void end_transaction() { } + + databus_protocol get_protocol() inline { + return databus_protocol.UART; + } + } + + i2c implements databus { + + enum STATUS {START_OK = 0x1, MT_SLA_ACK_OK = 0x3} + + void setup(uint32 speed) { + TWSR.TWS = 0; + TWSR.TWPS = 0; + TWBR = uint8(((clock() / speed) - 16) / 2); + } + + void async_read_to(interrupt_i8 i) {} + + void enable() { return; } + + void disable() { return; } + + bool start_transaction(uint16 addr) { + // write START condition + TWCR = ETWCR.TWSTA | ETWCR.TWEN | ETWCR.TWINT; + while (TWCR & ETWCR.TWINT) == 0; + + if TWSR.TWS != STATUS.START_OK { + return false; + } + + // write SLA addr + TWDR = uint8(addr); + TWCR = ETWCR.TWEN | ETWCR.TWINT; + while (TWCR & ETWCR.TWINT) == 0; + + if TWSR.TWS != STATUS.MT_SLA_ACK_OK { + return false; + } + + return true; + } + + void end_transaction() { + // send STOP condition + TWCR = ETWCR.TWSTO | ETWCR.TWEN | ETWCR.TWINT; + } + + void write(uint8 b) { + TWDR = b; + TWCR = ETWCR.TWINT | ETWCR.TWEN; + while (TWCR & ETWCR.TWINT) == 0; + } + + void write_array(int8[] data) { + i = 0u; + while (i < data.size) { + TWDR = uint8(data[i]); + TWCR = ETWCR.TWEN | ETWCR.TWINT; + while (TWCR & ETWCR.TWINT) == 0; + // check if TWSR.TWS != 0x5 // 0x28 >> 3 + // data transmited and ack received + i++; + } + } + + uint8 read() { return 0; } + + bool has_data() { return false; } + + databus_protocol get_protocol() { + return databus_protocol.I2C; + } + } +} diff --git a/lib/arch/avr/avr5regs.rob b/lib/arch/avr/avr5regs.rob new file mode 100644 index 0000000..a2546dd --- /dev/null +++ b/lib/arch/avr/avr5regs.rob @@ -0,0 +1,163 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* + * Global Registers + */ + +type SREG_t { + C = false; // Carry Flag + Z = false; // Zero Flag + N = false; // Negative Flag + V = false; // Two’s Complement Overflow Flag + S = false; // Sign Bit + H = false; // Half Carry Flag + T = false; // Bit Copy Storage + I = false; // Global Interrupt Enable +} + +register SREG_t SREG at 0x5f; + + +/* + * IO PORTS + */ + +type PORTB_t { + b0 = false; + b1 = false; + b2 = false; + b3 = false; + b4 = false; + b5 = false; + ignore = uint2(0); +} + +register PORTB_t portb at 0x25; +register PORTB_t ddrb at 0x24; + + +/* + * UART + */ + + type UCSRA_t { + MPCM0 = false; + U2X0 = false; + UPE0 = false; + DOR0 = false; + FE0 = false; + UDRE0 = false; + TXC0 = false; + RXC0 = false; +} + +type UCSRB_t { + TXB80 = false; + RXB80 = false; + UCSZ02 = false; + TXEN0 = false; + RXEN0 = false; + UDRIE0 = false; + TXCIE0 = false; + RXCIE0 = false; +} + +type UCSRC_t { + UCPOL0 = false; + UCSZ0 = uint2(0); + USBS0 = false; + UPM0 = uint2(0); + UMSEL0 = uint2(0); +} + +// USART0 control status register A +register UCSRA_t UCSR0A at 0xc0; + +// USART0 control status register B +register UCSRB_t UCSR0B at 0xc1; + +// USART0 control status register C +register UCSRC_t UCSR0C at 0xc2; + +// USART0 baud rate register, 12 bits +register uint16 UBRR0 at 0xc4; + +// USART0 byte to send/received +register uint8 UDR0 at 0xc6; + + +/* + * SPI + */ + +type SPCR_t { + SPR0 = false; // SPI clock rate 0 + SPR1 = false; // SPI clock rate 1 + CPHA = false; // Clock phase + CPOL = false; // Clock polarity + MSTR = false; // Master + DORD = false; // Data order + SPE = false; // SPI enable + SPIE = false; // SPI interruption enable +} + +// SPI Control Register +register SPCR_t SPCR at 0x4c; + +type SPSR_t { + SPI2x = false; // Double SPI speed + _reserved = uint5(0); + WCOL = false; // Write COLision flag + SPIF = false; // SPI interrupt flag +} + +// SPI Status Register +register SPSR_t SPSR at 0x4d; + +// SPI Data Register +register uint8 SPDR at 0x4e; + + +/* + * I2C (TWI) + * In atmega328p, PC5 = SCL, and PC4 = SDA. + */ + +// TWI Bit Rate Register +register uint8 TWBR at 0xB8; + +// TWI Control Register +// all fields of TWCR must be set at once, so we are not using a register type for it +enum ETWCR {TWIE = 1, TWEN = 4, TWWC = 8, TWSTO = 16, TWSTA = 32, TWEA = 64, TWINT = 128} +register uint8 TWCR at 0xBC; + +type TWSR_t { + TWPS = uint2(0); + _reserved = false; + TWS = uint5(0); +} + +// TWI Status Register +register TWSR_t TWSR at 0xB9; + +// TWI Data Register +register uint8 TWDR at 0xBB; + +type TWAR_t { + TWGCE = false; + TWA = uint7(0); +} + +// TWI Slave Address Register +register TWAR_t TWAR at 0xBA; + +type TWAMR_t { + _reserved = false; + TWAM = uint7(0); +} + +//TWI Slave Address Mask Register +register TWAMR_t TWAMR at 0xBD; diff --git a/lib/arch/rp/rp2040/boot2.o b/lib/arch/rp/rp2040/boot2.o new file mode 100755 index 0000000..a167ee0 Binary files /dev/null and b/lib/arch/rp/rp2040/boot2.o differ diff --git a/lib/arch/rp/rp2040/init.rob b/lib/arch/rp/rp2040/init.rob new file mode 100644 index 0000000..68865a8 --- /dev/null +++ b/lib/arch/rp/rp2040/init.rob @@ -0,0 +1,124 @@ +/* + * Robcmp bare-metal routines for rp2040 + */ + +use regs; + +int16 main(); + +void __system_config() { + // set vtor table offset from __start symbol of linker + /*asm "LDR R0, =__isr_start"; + asm "LDR R1, =0xE000ED08"; + asm "STR R0, [R1]";*/ + + // disable Watchdog + //WATCHDOG_CTRL.ENABLE = false; + //WATCHDOG_CTRL.TIME = 0; + + // Configure and Enable XOSC (External Crystal Oscillator) + XOSC_CTRL.ENABLE = XOSC_CTRL_ENABLE.ENABLE; + while !XOSC_STATUS.STABLE; // wait it becomes stable + + // Reset pll_sys + RESET.PLL_SYS = false; + while !RESET_DONE.PLL_SYS; + + // Configure PLL_SYS to generate 200MHz from 12MHz XOSC + PLL_SYS_FBDIV_INT.FBDIV_INT = 200; + PLL_SYS_PWR.PD = false; + PLL_SYS_PWR.VCOPD = false; + while !PLL_SYS_PLL_SYS_CS.LOCK; + + // set and turn on the post dividers + PLL_SYS_PRIM.POSTDIV1 = 6; + PLL_SYS_PRIM.POSTDIV2 = 2; + PLL_SYS_PWR.POSTDIVPD = false; + + // Setup clock generators + // Setup clk_ref + CLK_REF_CTRL.SRC = CLK_REF_CTRL_SRC.xosc_clksrc; + while (CLK_REF_SELECTED.CLK_REF_SELECTED & 0b100) != 0b100; + + // Setup clk_sys + CLK_SYS_CTRL.SRC = CLK_SYS_CTRL_SRC.clksrc_clk_sys_aux; + while (CLK_SYS_SELECTED.CLK_SYS_SELECTED & 0b10) != 0b10; + + // disable ROSC + ROSC_CTRL.ENABLE = ROSC_CTRL_ENABLE.DISABLE; + + // Enable 64-bit Timer + WATCHDOG_CTRL.TIME = 12; // 12 or 6? + RESET.TIMER = false; + while !RESET_DONE.TIMER; + + // reset GPIOs + RESET.IO_BANK0 = false; + RESET.PADS_BANK0 = false; + while !RESET_DONE.IO_BANK0; + while !RESET_DONE.PADS_BANK0; +} + +void __error_handler() { + asm "bkpt #0"; // breakpoint +} + +void __enter_vtable_in_r0() naked { + //read the VTOR offset and send core to vtable previously set in r0 + //PPB_BASE is at _u(0xe0000000) and the M0PLUS_VTOR_OFFSET is 0x0000ed08 + //thus, ldr r1, =(PPB_BASE + M0PLUS_VTOR_OFFSET) + asm "ldr r1, =0xe000ed08 + str r0, [r1] + ldmia r0!, {r1, r2} + msr msp, r1 + bx r2"; +} + +void __do_copy_data_and_bss() noinline { +// TODO: Improve __do_copy_data, this is a copy of stm32f1 +asm + "movs r1, #0 + b __do_copy_data_start + __do_copy_data_loop: + ldr r3, =__data_init + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + __do_copy_data_start: + ldr r0, =__data_start + ldr r3, =__data_end + adds r2, r0, r1 + cmp r2, r3 + bcc __do_copy_data_loop + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, #0 + b __do_clear_bss_start + __do_clear_bss_loop: + stm r1!, {r0} + __do_clear_bss_start: + cmp r1, r2 + bcc __do_clear_bss_loop"; +} + +void __isr_reset() naked { + // check if (and put) core 1 to sleep in the bootrom + // xx = 0xd0000000 = (SIO_BASE) 0xd0000000 + SIO_CPUID_OFFSET 0x00000000 + // value from [xx] is 0 when read from processor core 0, and 1 when read from processor core 1 + asm "ldr r0, =0xd0000000 + ldr r0, [r0] + cmp r0, #0 + beq 1f + hold_non_core0_in_bootrom: + ldr r0, #0 //BOOTROM_VTABLE_OFFSET + b __enter_vtable_in_r0 + 1: "; + + __do_copy_data_and_bss(); + + __system_config(); + + ret = main(); + + __error_handler(); +} diff --git a/lib/arch/rp/rp2040/mcu.rob b/lib/arch/rp/rp2040/mcu.rob new file mode 100644 index 0000000..f5dbdc0 --- /dev/null +++ b/lib/arch/rp/rp2040/mcu.rob @@ -0,0 +1,157 @@ + +use intfs.mcu; +use intfs.ports; +use intfs.databus; + +use regs; + +type rp2040mcu implements mcu { + + uint32 clock() inline { + // 200Mhz set by init + return 200E6; + } + + void set_interruptions(bool enabled) { + return; + } + + io24 implements digitalport { + void mode(port_mode m) { + GPIO24_CTRL.FUNCSEL = 5; + GPIO24.SLEWFAST = true; + GPIO24.SCHMITT = true; + GPIO24.OD = false; + if m == port_mode.input { + GPIO_OE.IO24 = false; + GPIO24.IE = true; + GPIO24.DRIVE = 0; + } else { + GPIO_OE.IO24 = true; + GPIO24.IE = false; + GPIO24.DRIVE = 3; + } + } + void set(bool v) { + x = uint32(1) << 24; + if (v) { GPIO_OUT_SET_raw = x; } + else { GPIO_OUT_CLR_raw = x; } + } + bool get() { return GPIO_IN.IO24; } + } + + io25 implements digitalport { + void mode(port_mode m) { + GPIO25_CTRL.FUNCSEL = 5; + GPIO25.SLEWFAST = true; + GPIO25.SCHMITT = true; + GPIO25.OD = false; + if m == port_mode.input { + GPIO_OE.IO25 = false; + GPIO25.IE = true; + GPIO25.DRIVE = 0; + } else { + GPIO_OE.IO25 = true; + GPIO25.IE = false; + GPIO25.DRIVE = 3; + } + } + void set(bool v) { + x = uint32(1) << 25; + if (v) { GPIO_OUT_SET_raw = x; } + else { GPIO_OUT_CLR_raw = x; } + } + bool get() { return GPIO_IN.IO25; } + } + + uint64 micros() { + timeLR = TIMELR_raw; + timeHR = TIMEHR_raw; + return (uint64(timeHR) << 32) | timeLR; + } + + uint64 millis() { + return micros() / 1000; + } + + void wait_us(uint16 us) { + old = micros(); + while micros() - old < us; + } + + void wait_ms(uint16 ms) { + old = millis(); + while millis() - old < ms; + } + + uart0 implements databus { + + void setup(uint32 baud) { + // set uart0 in IO0 (tx) and IO1 (rx) + GPIO0_CTRL.FUNCSEL = GPIO0_CTRL_FUNCSEL.uart0_tx; + GPIO1_CTRL.FUNCSEL = GPIO1_CTRL_FUNCSEL.uart0_rx; + + // set baudrate integer and fraction + // for clock = 133E6 > 125E6, clk_peri automatically switches to 48E6 + common_denominator = baud * 16; + baud_rate_integer = 48E6 / common_denominator; + baud_rate_frac = ((48E6 % common_denominator) * 64) / common_denominator; + UART0_UARTIBRD.BAUD_DIVINT = uint16(baud_rate_integer); + UART0_UARTFBRD.BAUD_DIVFRAC = uint6(baud_rate_frac); + + // 8 bit + UART0_UARTLCR_H.WLEN = 0b11; // 8 bit + UART0_UARTLCR_H.FEN = true; // enable FIFO buffers + UART0_UARTLCR_H.STP2 = false; // 1 stop bit + UART0_UARTLCR_H.PEN = false; // no parity + UART0_UARTLCR_H.BRK = false; // don't send break + + // enable TX and RX + UART0_UARTCR.TXE = true; + UART0_UARTCR.RXE = true; + } + + void async_read_to(interrupt_i8 i) { + //int_usart_rx = i; + //UCSR0B.RXCIE0 = true; + } + + void enable() { + UART0_UARTCR.UARTEN = true; + } + + void disable() { + UART0_UARTCR.UARTEN = false; + } + + void write(uint8 b) inline { + while UART0_UARTFR.TXFF; // wait if transmit fifo is full + UART0_UARTDR.DATA = b; + } + + void write_array(int8[] data) { + i = 0u; + while i < data.size { + write(uint8(data[i])); + i++; + } + } + + uint8 read() inline { + while UART0_UARTFR.RXFE; // wait if receive fifo is empty + return UART0_UARTDR.DATA; + } + + bool has_data() inline { + return !UART0_UARTFR.RXFE; + } + + bool start_transaction(uint16 address) inline { return true; } + void end_transaction() { } + + databus_protocol get_protocol() inline { + return databus_protocol.UART; + } + } + +} diff --git a/lib/arch/rp/rp2040/regs.rob b/lib/arch/rp/rp2040/regs.rob new file mode 100644 index 0000000..262a72e --- /dev/null +++ b/lib/arch/rp/rp2040/regs.rob @@ -0,0 +1,18269 @@ + +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + * + * This file was machine generated from rp/rp2040/rp2040.svd. Don't edit. + */ + +/* + vendor: Raspberry Pi + name: RP2040 + series: RP + version: 0.1 + description: + Dual-core Arm Cortex-M0+ processor, flexible clock running up to 133 MHz + 264KB on-chip SRAM + 2 x UART, 2 x SPI controllers, 2 x I2C controllers, 16 x PWM channels + 1 x USB 1.1 controller and PHY, with host and device support + 8 x Programmable I/O (PIO) state machines for custom peripheral support + Supported input power 1.8-5.5V DC + Operating temperature -20C to +85C + Drag-and-drop programming using mass storage over USB + Low-power sleep and dormant modes + Accurate on-chip clock + Temperature sensor + Accelerated integer and floating-point libraries on-chip + + width: 32 + size: 32 +*/ + +/* Types and registers for RESETS */ + + type RESET_t { + ADC = false; // + BUSCTRL = false; // + DMA = false; // + I2C0 = false; // + I2C1 = false; // + IO_BANK0 = false; // + IO_QSPI = false; // + JTAG = false; // + PADS_BANK0 = false; // + PADS_QSPI = false; // + PIO0 = false; // + PIO1 = false; // + PLL_SYS = false; // + PLL_USB = false; // + PWM = false; // + RTC = false; // + SPI0 = false; // + SPI1 = false; // + SYSCFG = false; // + SYSINFO = false; // + TBMAN = false; // + TIMER = false; // + UART0 = false; // + UART1 = false; // + USBCTRL = false; // + _res1 = uint7(0); // Reserved, 7 bits + } + + // Reset control. If a bit is set it means the peripheral is in reset. 0 means the peripheral's reset is deasserted. + register RESET_t RESET at 0x4000c000; + register uint32 RESET_raw at 0x4000c000; + + type RESETS_WDSEL_t { + ADC = false; // + BUSCTRL = false; // + DMA = false; // + I2C0 = false; // + I2C1 = false; // + IO_BANK0 = false; // + IO_QSPI = false; // + JTAG = false; // + PADS_BANK0 = false; // + PADS_QSPI = false; // + PIO0 = false; // + PIO1 = false; // + PLL_SYS = false; // + PLL_USB = false; // + PWM = false; // + RTC = false; // + SPI0 = false; // + SPI1 = false; // + SYSCFG = false; // + SYSINFO = false; // + TBMAN = false; // + TIMER = false; // + UART0 = false; // + UART1 = false; // + USBCTRL = false; // + _res1 = uint7(0); // Reserved, 7 bits + } + + // Watchdog select. If a bit is set then the watchdog will reset this peripheral when the watchdog fires. + register RESETS_WDSEL_t RESETS_WDSEL at 0x4000c004; + register uint32 RESETS_WDSEL_raw at 0x4000c004; + + type RESET_DONE_t { + ADC = false; // + BUSCTRL = false; // + DMA = false; // + I2C0 = false; // + I2C1 = false; // + IO_BANK0 = false; // + IO_QSPI = false; // + JTAG = false; // + PADS_BANK0 = false; // + PADS_QSPI = false; // + PIO0 = false; // + PIO1 = false; // + PLL_SYS = false; // + PLL_USB = false; // + PWM = false; // + RTC = false; // + SPI0 = false; // + SPI1 = false; // + SYSCFG = false; // + SYSINFO = false; // + TBMAN = false; // + TIMER = false; // + UART0 = false; // + UART1 = false; // + USBCTRL = false; // + _res1 = uint7(0); // Reserved, 7 bits + } + + // Reset done. If a bit is set then a reset done signal has been returned by the peripheral. This indicates that the peripheral's registers are ready to be accessed. + register RESET_DONE_t RESET_DONE at 0x4000c008; + register uint32 RESET_DONE_raw at 0x4000c008; + + +/* Types and registers for PSM */ + + type FRCE_ON_t { + ROSC = false; // + XOSC = false; // + CLOCKS = false; // + RESETS = false; // + BUSFABRIC = false; // + ROM = false; // + SRAM0 = false; // + SRAM1 = false; // + SRAM2 = false; // + SRAM3 = false; // + SRAM4 = false; // + SRAM5 = false; // + XIP = false; // + VREG_AND_CHIP_RESET = false; // + SIO = false; // + PROC0 = false; // + PROC1 = false; // + _res1 = uint15(0); // Reserved, 15 bits + } + + // Force block out of reset (i.e. power it on) + register FRCE_ON_t FRCE_ON at 0x40010000; + register uint32 FRCE_ON_raw at 0x40010000; + + type FRCE_OFF_t { + ROSC = false; // + XOSC = false; // + CLOCKS = false; // + RESETS = false; // + BUSFABRIC = false; // + ROM = false; // + SRAM0 = false; // + SRAM1 = false; // + SRAM2 = false; // + SRAM3 = false; // + SRAM4 = false; // + SRAM5 = false; // + XIP = false; // + VREG_AND_CHIP_RESET = false; // + SIO = false; // + PROC0 = false; // + PROC1 = false; // + _res1 = uint15(0); // Reserved, 15 bits + } + + // Force into reset (i.e. power it off) + register FRCE_OFF_t FRCE_OFF at 0x40010004; + register uint32 FRCE_OFF_raw at 0x40010004; + + type PSM_WDSEL_t { + ROSC = false; // + XOSC = false; // + CLOCKS = false; // + RESETS = false; // + BUSFABRIC = false; // + ROM = false; // + SRAM0 = false; // + SRAM1 = false; // + SRAM2 = false; // + SRAM3 = false; // + SRAM4 = false; // + SRAM5 = false; // + XIP = false; // + VREG_AND_CHIP_RESET = false; // + SIO = false; // + PROC0 = false; // + PROC1 = false; // + _res1 = uint15(0); // Reserved, 15 bits + } + + // Set to 1 if this peripheral should be reset when the watchdog fires. + register PSM_WDSEL_t PSM_WDSEL at 0x40010008; + register uint32 PSM_WDSEL_raw at 0x40010008; + + type DONE_t { + ROSC = false; // + XOSC = false; // + CLOCKS = false; // + RESETS = false; // + BUSFABRIC = false; // + ROM = false; // + SRAM0 = false; // + SRAM1 = false; // + SRAM2 = false; // + SRAM3 = false; // + SRAM4 = false; // + SRAM5 = false; // + XIP = false; // + VREG_AND_CHIP_RESET = false; // + SIO = false; // + PROC0 = false; // + PROC1 = false; // + _res1 = uint15(0); // Reserved, 15 bits + } + + // Indicates the peripheral's registers are ready to access. + register DONE_t DONE at 0x4001000c; + register uint32 DONE_raw at 0x4001000c; + + +/* Types and registers for CLOCKS */ + + enum CLK_GPOUT0_CTRL_AUXSRC { + clksrc_pll_sys = 0, // + clksrc_gpin0 = 1, // + clksrc_gpin1 = 2, // + clksrc_pll_usb = 3, // + rosc_clksrc = 4, // + xosc_clksrc = 5, // + clk_sys = 6, // + clk_usb = 7, // + clk_adc = 8, // + clk_rtc = 9, // + clk_ref = 10 // + } + + type CLK_GPOUT0_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint4(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = false; // Reserved, 1 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + DC50 = false; // Enables duty cycle correction for odd divisors + _res3 = uint3(0); // Reserved, 3 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_GPOUT0_CTRL_t CLK_GPOUT0_CTRL at 0x40008000; + register uint32 CLK_GPOUT0_CTRL_raw at 0x40008000; + + type CLK_GPOUT0_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_GPOUT0_DIV_t CLK_GPOUT0_DIV at 0x40008004; + register uint32 CLK_GPOUT0_DIV_raw at 0x40008004; + + type CLK_GPOUT0_SELECTED_t { + CLK_GPOUT0_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_GPOUT0_SELECTED_t CLK_GPOUT0_SELECTED at 0x40008008; + register uint32 CLK_GPOUT0_SELECTED_raw at 0x40008008; + + enum CLK_GPOUT1_CTRL_AUXSRC { + clksrc_pll_sys = 0, // + clksrc_gpin0 = 1, // + clksrc_gpin1 = 2, // + clksrc_pll_usb = 3, // + rosc_clksrc = 4, // + xosc_clksrc = 5, // + clk_sys = 6, // + clk_usb = 7, // + clk_adc = 8, // + clk_rtc = 9, // + clk_ref = 10 // + } + + type CLK_GPOUT1_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint4(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = false; // Reserved, 1 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + DC50 = false; // Enables duty cycle correction for odd divisors + _res3 = uint3(0); // Reserved, 3 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_GPOUT1_CTRL_t CLK_GPOUT1_CTRL at 0x4000800c; + register uint32 CLK_GPOUT1_CTRL_raw at 0x4000800c; + + type CLK_GPOUT1_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_GPOUT1_DIV_t CLK_GPOUT1_DIV at 0x40008010; + register uint32 CLK_GPOUT1_DIV_raw at 0x40008010; + + type CLK_GPOUT1_SELECTED_t { + CLK_GPOUT1_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_GPOUT1_SELECTED_t CLK_GPOUT1_SELECTED at 0x40008014; + register uint32 CLK_GPOUT1_SELECTED_raw at 0x40008014; + + enum CLK_GPOUT2_CTRL_AUXSRC { + clksrc_pll_sys = 0, // + clksrc_gpin0 = 1, // + clksrc_gpin1 = 2, // + clksrc_pll_usb = 3, // + rosc_clksrc_ph = 4, // + xosc_clksrc = 5, // + clk_sys = 6, // + clk_usb = 7, // + clk_adc = 8, // + clk_rtc = 9, // + clk_ref = 10 // + } + + type CLK_GPOUT2_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint4(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = false; // Reserved, 1 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + DC50 = false; // Enables duty cycle correction for odd divisors + _res3 = uint3(0); // Reserved, 3 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_GPOUT2_CTRL_t CLK_GPOUT2_CTRL at 0x40008018; + register uint32 CLK_GPOUT2_CTRL_raw at 0x40008018; + + type CLK_GPOUT2_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_GPOUT2_DIV_t CLK_GPOUT2_DIV at 0x4000801c; + register uint32 CLK_GPOUT2_DIV_raw at 0x4000801c; + + type CLK_GPOUT2_SELECTED_t { + CLK_GPOUT2_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_GPOUT2_SELECTED_t CLK_GPOUT2_SELECTED at 0x40008020; + register uint32 CLK_GPOUT2_SELECTED_raw at 0x40008020; + + enum CLK_GPOUT3_CTRL_AUXSRC { + clksrc_pll_sys = 0, // + clksrc_gpin0 = 1, // + clksrc_gpin1 = 2, // + clksrc_pll_usb = 3, // + rosc_clksrc_ph = 4, // + xosc_clksrc = 5, // + clk_sys = 6, // + clk_usb = 7, // + clk_adc = 8, // + clk_rtc = 9, // + clk_ref = 10 // + } + + type CLK_GPOUT3_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint4(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = false; // Reserved, 1 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + DC50 = false; // Enables duty cycle correction for odd divisors + _res3 = uint3(0); // Reserved, 3 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_GPOUT3_CTRL_t CLK_GPOUT3_CTRL at 0x40008024; + register uint32 CLK_GPOUT3_CTRL_raw at 0x40008024; + + type CLK_GPOUT3_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_GPOUT3_DIV_t CLK_GPOUT3_DIV at 0x40008028; + register uint32 CLK_GPOUT3_DIV_raw at 0x40008028; + + type CLK_GPOUT3_SELECTED_t { + CLK_GPOUT3_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_GPOUT3_SELECTED_t CLK_GPOUT3_SELECTED at 0x4000802c; + register uint32 CLK_GPOUT3_SELECTED_raw at 0x4000802c; + + enum CLK_REF_CTRL_AUXSRC { + clksrc_pll_usb = 0, // + clksrc_gpin0 = 1, // + clksrc_gpin1 = 2 // + } + + enum CLK_REF_CTRL_SRC { + rosc_clksrc_ph = 0, // + clksrc_clk_ref_aux = 1, // + xosc_clksrc = 2 // + } + + type CLK_REF_CTRL_t { + SRC = uint2(0); // Selects the clock source glitchlessly, can be changed on-the-fly + _res1 = uint3(0); // Reserved, 3 bits + AUXSRC = uint2(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint25(0); // Reserved, 25 bits + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_REF_CTRL_t CLK_REF_CTRL at 0x40008030; + register uint32 CLK_REF_CTRL_raw at 0x40008030; + + type CLK_REF_DIV_t { + _res1 = uint8(0); // Reserved, 8 bits + INT = uint2(0); // Integer component of the divisor, 0 -> divide by 2^16 + _res2 = uint22(0); // Reserved, 22 bits + } + + // Clock divisor, can be changed on-the-fly + register CLK_REF_DIV_t CLK_REF_DIV at 0x40008034; + register uint32 CLK_REF_DIV_raw at 0x40008034; + + type CLK_REF_SELECTED_t { + CLK_REF_SELECTED = uint32(0); // The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_REF_SELECTED_t CLK_REF_SELECTED at 0x40008038; + register uint32 CLK_REF_SELECTED_raw at 0x40008038; + + enum CLK_SYS_CTRL_AUXSRC { + clksrc_pll_sys = 0, // + clksrc_pll_usb = 1, // + rosc_clksrc = 2, // + xosc_clksrc = 3, // + clksrc_gpin0 = 4, // + clksrc_gpin1 = 5 // + } + + enum CLK_SYS_CTRL_SRC { + clk_ref = 0, // + clksrc_clk_sys_aux = 1 // + } + + type CLK_SYS_CTRL_t { + SRC = false; // Selects the clock source glitchlessly, can be changed on-the-fly + _res1 = uint4(0); // Reserved, 4 bits + AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint24(0); // Reserved, 24 bits + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_SYS_CTRL_t CLK_SYS_CTRL at 0x4000803c; + register uint32 CLK_SYS_CTRL_raw at 0x4000803c; + + type CLK_SYS_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_SYS_DIV_t CLK_SYS_DIV at 0x40008040; + register uint32 CLK_SYS_DIV_raw at 0x40008040; + + type CLK_SYS_SELECTED_t { + CLK_SYS_SELECTED = uint32(0); // The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_SYS_SELECTED_t CLK_SYS_SELECTED at 0x40008044; + register uint32 CLK_SYS_SELECTED_raw at 0x40008044; + + enum CLK_PERI_CTRL_AUXSRC { + clk_sys = 0, // + clksrc_pll_sys = 1, // + clksrc_pll_usb = 2, // + rosc_clksrc_ph = 3, // + xosc_clksrc = 4, // + clksrc_gpin0 = 5, // + clksrc_gpin1 = 6 // + } + + type CLK_PERI_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint2(0); // Reserved, 2 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + _res3 = uint20(0); // Reserved, 20 bits + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_PERI_CTRL_t CLK_PERI_CTRL at 0x40008048; + register uint32 CLK_PERI_CTRL_raw at 0x40008048; + + type CLK_PERI_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_PERI_DIV_t CLK_PERI_DIV at 0x4000804c; + register uint32 CLK_PERI_DIV_raw at 0x4000804c; + + type CLK_PERI_SELECTED_t { + CLK_PERI_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_PERI_SELECTED_t CLK_PERI_SELECTED at 0x40008050; + register uint32 CLK_PERI_SELECTED_raw at 0x40008050; + + enum CLK_USB_CTRL_AUXSRC { + clksrc_pll_usb = 0, // + clksrc_pll_sys = 1, // + rosc_clksrc_ph = 2, // + xosc_clksrc = 3, // + clksrc_gpin0 = 4, // + clksrc_gpin1 = 5 // + } + + type CLK_USB_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint2(0); // Reserved, 2 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + _res3 = uint4(0); // Reserved, 4 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_USB_CTRL_t CLK_USB_CTRL at 0x40008054; + register uint32 CLK_USB_CTRL_raw at 0x40008054; + + type CLK_USB_DIV_t { + _res1 = uint8(0); // Reserved, 8 bits + INT = uint2(0); // Integer component of the divisor, 0 -> divide by 2^16 + _res2 = uint22(0); // Reserved, 22 bits + } + + // Clock divisor, can be changed on-the-fly + register CLK_USB_DIV_t CLK_USB_DIV at 0x40008058; + register uint32 CLK_USB_DIV_raw at 0x40008058; + + type CLK_USB_SELECTED_t { + CLK_USB_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_USB_SELECTED_t CLK_USB_SELECTED at 0x4000805c; + register uint32 CLK_USB_SELECTED_raw at 0x4000805c; + + enum CLK_ADC_CTRL_AUXSRC { + clksrc_pll_usb = 0, // + clksrc_pll_sys = 1, // + rosc_clksrc_ph = 2, // + xosc_clksrc = 3, // + clksrc_gpin0 = 4, // + clksrc_gpin1 = 5 // + } + + type CLK_ADC_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint2(0); // Reserved, 2 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + _res3 = uint4(0); // Reserved, 4 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_ADC_CTRL_t CLK_ADC_CTRL at 0x40008060; + register uint32 CLK_ADC_CTRL_raw at 0x40008060; + + type CLK_ADC_DIV_t { + _res1 = uint8(0); // Reserved, 8 bits + INT = uint2(0); // Integer component of the divisor, 0 -> divide by 2^16 + _res2 = uint22(0); // Reserved, 22 bits + } + + // Clock divisor, can be changed on-the-fly + register CLK_ADC_DIV_t CLK_ADC_DIV at 0x40008064; + register uint32 CLK_ADC_DIV_raw at 0x40008064; + + type CLK_ADC_SELECTED_t { + CLK_ADC_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_ADC_SELECTED_t CLK_ADC_SELECTED at 0x40008068; + register uint32 CLK_ADC_SELECTED_raw at 0x40008068; + + enum CLK_RTC_CTRL_AUXSRC { + clksrc_pll_usb = 0, // + clksrc_pll_sys = 1, // + rosc_clksrc_ph = 2, // + xosc_clksrc = 3, // + clksrc_gpin0 = 4, // + clksrc_gpin1 = 5 // + } + + type CLK_RTC_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint2(0); // Reserved, 2 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + _res3 = uint4(0); // Reserved, 4 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_RTC_CTRL_t CLK_RTC_CTRL at 0x4000806c; + register uint32 CLK_RTC_CTRL_raw at 0x4000806c; + + type CLK_RTC_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_RTC_DIV_t CLK_RTC_DIV at 0x40008070; + register uint32 CLK_RTC_DIV_raw at 0x40008070; + + type CLK_RTC_SELECTED_t { + CLK_RTC_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_RTC_SELECTED_t CLK_RTC_SELECTED at 0x40008074; + register uint32 CLK_RTC_SELECTED_raw at 0x40008074; + + type CLK_SYS_RESUS_CTRL_t { + TIMEOUT = uint8(0); // This is expressed as a number of clk_ref cycles and must be >= 2x clk_ref_freq/min_clk_tst_freq + ENABLE = false; // Enable resus + _res1 = uint3(0); // Reserved, 3 bits + FRCE = false; // Force a resus, for test purposes only + _res2 = uint3(0); // Reserved, 3 bits + CLEAR = false; // For clearing the resus after the fault that triggered it has been corrected + _res3 = uint15(0); // Reserved, 15 bits + } + + // + register CLK_SYS_RESUS_CTRL_t CLK_SYS_RESUS_CTRL at 0x40008078; + register uint32 CLK_SYS_RESUS_CTRL_raw at 0x40008078; + + type CLK_SYS_RESUS_STATUS_t { + RESUSSED = false; // Clock has been resuscitated, correct the error then send ctrl_clear=1 + _res1 = uint31(0); // Reserved, 31 bits + } + + // + register CLK_SYS_RESUS_STATUS_t CLK_SYS_RESUS_STATUS at 0x4000807c; + register uint32 CLK_SYS_RESUS_STATUS_raw at 0x4000807c; + + type FC0_REF_KHZ_t { + FC0_REF_KHZ = uint20(0); // + _res1 = uint12(0); // Reserved, 12 bits + } + + // Reference clock frequency in kHz + register FC0_REF_KHZ_t FC0_REF_KHZ at 0x40008080; + register uint32 FC0_REF_KHZ_raw at 0x40008080; + + type FC0_MIN_KHZ_t { + FC0_MIN_KHZ = uint25(0); // + _res1 = uint7(0); // Reserved, 7 bits + } + + // Minimum pass frequency in kHz. This is optional. Set to 0 if you are not using the pass/fail flags + register FC0_MIN_KHZ_t FC0_MIN_KHZ at 0x40008084; + register uint32 FC0_MIN_KHZ_raw at 0x40008084; + + type FC0_MAX_KHZ_t { + FC0_MAX_KHZ = uint25(0); // + _res1 = uint7(0); // Reserved, 7 bits + } + + // Maximum pass frequency in kHz. This is optional. Set to 0x1ffffff if you are not using the pass/fail flags + register FC0_MAX_KHZ_t FC0_MAX_KHZ at 0x40008088; + register uint32 FC0_MAX_KHZ_raw at 0x40008088; + + type FC0_DELAY_t { + FC0_DELAY = uint3(0); // + _res1 = uint29(0); // Reserved, 29 bits + } + + // Delays the start of frequency counting to allow the mux to settle Delay is measured in multiples of the reference clock period + register FC0_DELAY_t FC0_DELAY at 0x4000808c; + register uint32 FC0_DELAY_raw at 0x4000808c; + + type FC0_INTERVAL_t { + FC0_INTERVAL = uint4(0); // + _res1 = uint28(0); // Reserved, 28 bits + } + + // The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval The default gives a test interval of 250us + register FC0_INTERVAL_t FC0_INTERVAL at 0x40008090; + register uint32 FC0_INTERVAL_raw at 0x40008090; + + enum FC0_SRC_FC0_SRC { + NULL = 0, // + pll_sys_clksrc_primary = 1, // + pll_usb_clksrc_primary = 2, // + rosc_clksrc = 3, // + rosc_clksrc_ph = 4, // + xosc_clksrc = 5, // + clksrc_gpin0 = 6, // + clksrc_gpin1 = 7, // + clk_ref = 8, // + clk_sys = 9, // + clk_peri = 10, // + clk_usb = 11, // + clk_adc = 12, // + clk_rtc = 13 // + } + + type FC0_SRC_t { + FC0_SRC = uint8(0); // + _res1 = uint24(0); // Reserved, 24 bits + } + + // Clock sent to frequency counter, set to 0 when not required Writing to this register initiates the frequency count + register FC0_SRC_t FC0_SRC at 0x40008094; + register uint32 FC0_SRC_raw at 0x40008094; + + type FC0_STATUS_t { + PASS = false; // Test passed + _res1 = uint3(0); // Reserved, 3 bits + DONE = false; // Test complete + _res2 = uint3(0); // Reserved, 3 bits + RUNNING = false; // Test running + _res3 = uint3(0); // Reserved, 3 bits + WAITING = false; // Waiting for test clock to start + _res4 = uint3(0); // Reserved, 3 bits + FAIL = false; // Test failed + _res5 = uint3(0); // Reserved, 3 bits + SLOW = false; // Test clock slower than expected, only valid when status_done=1 + _res6 = uint3(0); // Reserved, 3 bits + FAST = false; // Test clock faster than expected, only valid when status_done=1 + _res7 = uint3(0); // Reserved, 3 bits + DIED = false; // Test clock stopped during test + _res8 = uint3(0); // Reserved, 3 bits + } + + // Frequency counter status + register FC0_STATUS_t FC0_STATUS at 0x40008098; + register uint32 FC0_STATUS_raw at 0x40008098; + + type FC0_RESULT_t { + FRAC = uint5(0); // + KHZ = uint25(0); // + _res1 = uint2(0); // Reserved, 2 bits + } + + // Result of frequency measurement, only valid when status_done=1 + register FC0_RESULT_t FC0_RESULT at 0x4000809c; + register uint32 FC0_RESULT_raw at 0x4000809c; + + type WAKE_EN0_t { + CLK_SYS_CLOCKS = false; // + CLK_ADC_ADC = false; // + CLK_SYS_ADC = false; // + CLK_SYS_BUSCTRL = false; // + CLK_SYS_BUSFABRIC = false; // + CLK_SYS_DMA = false; // + CLK_SYS_I2C0 = false; // + CLK_SYS_I2C1 = false; // + CLK_SYS_IO = false; // + CLK_SYS_JTAG = false; // + CLK_SYS_VREG_AND_CHIP_RESET = false; // + CLK_SYS_PADS = false; // + CLK_SYS_PIO0 = false; // + CLK_SYS_PIO1 = false; // + CLK_SYS_PLL_SYS = false; // + CLK_SYS_PLL_USB = false; // + CLK_SYS_PSM = false; // + CLK_SYS_PWM = false; // + CLK_SYS_RESETS = false; // + CLK_SYS_ROM = false; // + CLK_SYS_ROSC = false; // + CLK_RTC_RTC = false; // + CLK_SYS_RTC = false; // + CLK_SYS_SIO = false; // + CLK_PERI_SPI0 = false; // + CLK_SYS_SPI0 = false; // + CLK_PERI_SPI1 = false; // + CLK_SYS_SPI1 = false; // + CLK_SYS_SRAM0 = false; // + CLK_SYS_SRAM1 = false; // + CLK_SYS_SRAM2 = false; // + CLK_SYS_SRAM3 = false; // + } + + // enable clock in wake mode + register WAKE_EN0_t WAKE_EN0 at 0x400080a0; + register uint32 WAKE_EN0_raw at 0x400080a0; + + type WAKE_EN1_t { + CLK_SYS_SRAM4 = false; // + CLK_SYS_SRAM5 = false; // + CLK_SYS_SYSCFG = false; // + CLK_SYS_SYSINFO = false; // + CLK_SYS_TBMAN = false; // + CLK_SYS_TIMER = false; // + CLK_PERI_UART0 = false; // + CLK_SYS_UART0 = false; // + CLK_PERI_UART1 = false; // + CLK_SYS_UART1 = false; // + CLK_SYS_USBCTRL = false; // + CLK_USB_USBCTRL = false; // + CLK_SYS_WATCHDOG = false; // + CLK_SYS_XIP = false; // + CLK_SYS_XOSC = false; // + _res1 = uint17(0); // Reserved, 17 bits + } + + // enable clock in wake mode + register WAKE_EN1_t WAKE_EN1 at 0x400080a4; + register uint32 WAKE_EN1_raw at 0x400080a4; + + type SLEEP_EN0_t { + CLK_SYS_CLOCKS = false; // + CLK_ADC_ADC = false; // + CLK_SYS_ADC = false; // + CLK_SYS_BUSCTRL = false; // + CLK_SYS_BUSFABRIC = false; // + CLK_SYS_DMA = false; // + CLK_SYS_I2C0 = false; // + CLK_SYS_I2C1 = false; // + CLK_SYS_IO = false; // + CLK_SYS_JTAG = false; // + CLK_SYS_VREG_AND_CHIP_RESET = false; // + CLK_SYS_PADS = false; // + CLK_SYS_PIO0 = false; // + CLK_SYS_PIO1 = false; // + CLK_SYS_PLL_SYS = false; // + CLK_SYS_PLL_USB = false; // + CLK_SYS_PSM = false; // + CLK_SYS_PWM = false; // + CLK_SYS_RESETS = false; // + CLK_SYS_ROM = false; // + CLK_SYS_ROSC = false; // + CLK_RTC_RTC = false; // + CLK_SYS_RTC = false; // + CLK_SYS_SIO = false; // + CLK_PERI_SPI0 = false; // + CLK_SYS_SPI0 = false; // + CLK_PERI_SPI1 = false; // + CLK_SYS_SPI1 = false; // + CLK_SYS_SRAM0 = false; // + CLK_SYS_SRAM1 = false; // + CLK_SYS_SRAM2 = false; // + CLK_SYS_SRAM3 = false; // + } + + // enable clock in sleep mode + register SLEEP_EN0_t SLEEP_EN0 at 0x400080a8; + register uint32 SLEEP_EN0_raw at 0x400080a8; + + type SLEEP_EN1_t { + CLK_SYS_SRAM4 = false; // + CLK_SYS_SRAM5 = false; // + CLK_SYS_SYSCFG = false; // + CLK_SYS_SYSINFO = false; // + CLK_SYS_TBMAN = false; // + CLK_SYS_TIMER = false; // + CLK_PERI_UART0 = false; // + CLK_SYS_UART0 = false; // + CLK_PERI_UART1 = false; // + CLK_SYS_UART1 = false; // + CLK_SYS_USBCTRL = false; // + CLK_USB_USBCTRL = false; // + CLK_SYS_WATCHDOG = false; // + CLK_SYS_XIP = false; // + CLK_SYS_XOSC = false; // + _res1 = uint17(0); // Reserved, 17 bits + } + + // enable clock in sleep mode + register SLEEP_EN1_t SLEEP_EN1 at 0x400080ac; + register uint32 SLEEP_EN1_raw at 0x400080ac; + + type ENABLED0_t { + CLK_SYS_CLOCKS = false; // + CLK_ADC_ADC = false; // + CLK_SYS_ADC = false; // + CLK_SYS_BUSCTRL = false; // + CLK_SYS_BUSFABRIC = false; // + CLK_SYS_DMA = false; // + CLK_SYS_I2C0 = false; // + CLK_SYS_I2C1 = false; // + CLK_SYS_IO = false; // + CLK_SYS_JTAG = false; // + CLK_SYS_VREG_AND_CHIP_RESET = false; // + CLK_SYS_PADS = false; // + CLK_SYS_PIO0 = false; // + CLK_SYS_PIO1 = false; // + CLK_SYS_PLL_SYS = false; // + CLK_SYS_PLL_USB = false; // + CLK_SYS_PSM = false; // + CLK_SYS_PWM = false; // + CLK_SYS_RESETS = false; // + CLK_SYS_ROM = false; // + CLK_SYS_ROSC = false; // + CLK_RTC_RTC = false; // + CLK_SYS_RTC = false; // + CLK_SYS_SIO = false; // + CLK_PERI_SPI0 = false; // + CLK_SYS_SPI0 = false; // + CLK_PERI_SPI1 = false; // + CLK_SYS_SPI1 = false; // + CLK_SYS_SRAM0 = false; // + CLK_SYS_SRAM1 = false; // + CLK_SYS_SRAM2 = false; // + CLK_SYS_SRAM3 = false; // + } + + // indicates the state of the clock enable + register ENABLED0_t ENABLED0 at 0x400080b0; + register uint32 ENABLED0_raw at 0x400080b0; + + type ENABLED1_t { + CLK_SYS_SRAM4 = false; // + CLK_SYS_SRAM5 = false; // + CLK_SYS_SYSCFG = false; // + CLK_SYS_SYSINFO = false; // + CLK_SYS_TBMAN = false; // + CLK_SYS_TIMER = false; // + CLK_PERI_UART0 = false; // + CLK_SYS_UART0 = false; // + CLK_PERI_UART1 = false; // + CLK_SYS_UART1 = false; // + CLK_SYS_USBCTRL = false; // + CLK_USB_USBCTRL = false; // + CLK_SYS_WATCHDOG = false; // + CLK_SYS_XIP = false; // + CLK_SYS_XOSC = false; // + _res1 = uint17(0); // Reserved, 17 bits + } + + // indicates the state of the clock enable + register ENABLED1_t ENABLED1 at 0x400080b4; + register uint32 ENABLED1_raw at 0x400080b4; + + type CLOCKS_INTR_t { + CLK_SYS_RESUS = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Raw Interrupts + register CLOCKS_INTR_t CLOCKS_INTR at 0x400080b8; + register uint32 CLOCKS_INTR_raw at 0x400080b8; + + type CLOCKS_INTE_t { + CLK_SYS_RESUS = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Interrupt Enable + register CLOCKS_INTE_t CLOCKS_INTE at 0x400080bc; + register uint32 CLOCKS_INTE_raw at 0x400080bc; + + type CLOCKS_INTF_t { + CLK_SYS_RESUS = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Interrupt Force + register CLOCKS_INTF_t CLOCKS_INTF at 0x400080c0; + register uint32 CLOCKS_INTF_raw at 0x400080c0; + + type CLOCKS_INTS_t { + CLK_SYS_RESUS = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Interrupt status after masking & forcing + register CLOCKS_INTS_t CLOCKS_INTS at 0x400080c4; + register uint32 CLOCKS_INTS_raw at 0x400080c4; + + +/* Types and registers for PADS_BANK0 */ + + enum PADS_BANK0_VOLTAGE_SELECT_VOLTAGE_SELECT { + _3v3 = 0, // Set voltage to 3.3V (DVDD >= 2V5) + _1v8 = 1 // Set voltage to 1.8V (DVDD <= 1V8) + } + + type PADS_BANK0_VOLTAGE_SELECT_t { + VOLTAGE_SELECT = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Voltage select. Per bank control + register PADS_BANK0_VOLTAGE_SELECT_t PADS_BANK0_VOLTAGE_SELECT at 0x4001c000; + register uint32 PADS_BANK0_VOLTAGE_SELECT_raw at 0x4001c000; + + enum GPIO0_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO0_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO0_t GPIO0 at 0x4001c004; + register uint32 GPIO0_raw at 0x4001c004; + + enum GPIO1_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO1_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO1_t GPIO1 at 0x4001c008; + register uint32 GPIO1_raw at 0x4001c008; + + enum GPIO2_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO2_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO2_t GPIO2 at 0x4001c00c; + register uint32 GPIO2_raw at 0x4001c00c; + + enum GPIO3_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO3_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO3_t GPIO3 at 0x4001c010; + register uint32 GPIO3_raw at 0x4001c010; + + enum GPIO4_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO4_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO4_t GPIO4 at 0x4001c014; + register uint32 GPIO4_raw at 0x4001c014; + + enum GPIO5_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO5_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO5_t GPIO5 at 0x4001c018; + register uint32 GPIO5_raw at 0x4001c018; + + enum GPIO6_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO6_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO6_t GPIO6 at 0x4001c01c; + register uint32 GPIO6_raw at 0x4001c01c; + + enum GPIO7_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO7_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO7_t GPIO7 at 0x4001c020; + register uint32 GPIO7_raw at 0x4001c020; + + enum GPIO8_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO8_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO8_t GPIO8 at 0x4001c024; + register uint32 GPIO8_raw at 0x4001c024; + + enum GPIO9_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO9_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO9_t GPIO9 at 0x4001c028; + register uint32 GPIO9_raw at 0x4001c028; + + enum GPIO10_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO10_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO10_t GPIO10 at 0x4001c02c; + register uint32 GPIO10_raw at 0x4001c02c; + + enum GPIO11_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO11_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO11_t GPIO11 at 0x4001c030; + register uint32 GPIO11_raw at 0x4001c030; + + enum GPIO12_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO12_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO12_t GPIO12 at 0x4001c034; + register uint32 GPIO12_raw at 0x4001c034; + + enum GPIO13_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO13_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO13_t GPIO13 at 0x4001c038; + register uint32 GPIO13_raw at 0x4001c038; + + enum GPIO14_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO14_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO14_t GPIO14 at 0x4001c03c; + register uint32 GPIO14_raw at 0x4001c03c; + + enum GPIO15_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO15_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO15_t GPIO15 at 0x4001c040; + register uint32 GPIO15_raw at 0x4001c040; + + enum GPIO16_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO16_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO16_t GPIO16 at 0x4001c044; + register uint32 GPIO16_raw at 0x4001c044; + + enum GPIO17_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO17_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO17_t GPIO17 at 0x4001c048; + register uint32 GPIO17_raw at 0x4001c048; + + enum GPIO18_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO18_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO18_t GPIO18 at 0x4001c04c; + register uint32 GPIO18_raw at 0x4001c04c; + + enum GPIO19_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO19_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO19_t GPIO19 at 0x4001c050; + register uint32 GPIO19_raw at 0x4001c050; + + enum GPIO20_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO20_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO20_t GPIO20 at 0x4001c054; + register uint32 GPIO20_raw at 0x4001c054; + + enum GPIO21_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO21_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO21_t GPIO21 at 0x4001c058; + register uint32 GPIO21_raw at 0x4001c058; + + enum GPIO22_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO22_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO22_t GPIO22 at 0x4001c05c; + register uint32 GPIO22_raw at 0x4001c05c; + + enum GPIO23_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO23_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO23_t GPIO23 at 0x4001c060; + register uint32 GPIO23_raw at 0x4001c060; + + enum GPIO24_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO24_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO24_t GPIO24 at 0x4001c064; + register uint32 GPIO24_raw at 0x4001c064; + + enum GPIO25_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO25_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO25_t GPIO25 at 0x4001c068; + register uint32 GPIO25_raw at 0x4001c068; + + enum GPIO26_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO26_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO26_t GPIO26 at 0x4001c06c; + register uint32 GPIO26_raw at 0x4001c06c; + + enum GPIO27_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO27_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO27_t GPIO27 at 0x4001c070; + register uint32 GPIO27_raw at 0x4001c070; + + enum GPIO28_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO28_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO28_t GPIO28 at 0x4001c074; + register uint32 GPIO28_raw at 0x4001c074; + + enum GPIO29_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO29_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO29_t GPIO29 at 0x4001c078; + register uint32 GPIO29_raw at 0x4001c078; + + enum SWCLK_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type SWCLK_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register SWCLK_t SWCLK at 0x4001c07c; + register uint32 SWCLK_raw at 0x4001c07c; + + enum SWD_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type SWD_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register SWD_t SWD at 0x4001c080; + register uint32 SWD_raw at 0x4001c080; + + +/* Types and registers for PADS_QSPI */ + + enum PADS_QSPI_VOLTAGE_SELECT_VOLTAGE_SELECT { + _3v3 = 0, // Set voltage to 3.3V (DVDD >= 2V5) + _1v8 = 1 // Set voltage to 1.8V (DVDD <= 1V8) + } + + type PADS_QSPI_VOLTAGE_SELECT_t { + VOLTAGE_SELECT = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Voltage select. Per bank control + register PADS_QSPI_VOLTAGE_SELECT_t PADS_QSPI_VOLTAGE_SELECT at 0x40020000; + register uint32 PADS_QSPI_VOLTAGE_SELECT_raw at 0x40020000; + + enum GPIO_QSPI_SCLK_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO_QSPI_SCLK_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO_QSPI_SCLK_t GPIO_QSPI_SCLK at 0x40020004; + register uint32 GPIO_QSPI_SCLK_raw at 0x40020004; + + enum GPIO_QSPI_SD0_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO_QSPI_SD0_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO_QSPI_SD0_t GPIO_QSPI_SD0 at 0x40020008; + register uint32 GPIO_QSPI_SD0_raw at 0x40020008; + + enum GPIO_QSPI_SD1_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO_QSPI_SD1_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO_QSPI_SD1_t GPIO_QSPI_SD1 at 0x4002000c; + register uint32 GPIO_QSPI_SD1_raw at 0x4002000c; + + enum GPIO_QSPI_SD2_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO_QSPI_SD2_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO_QSPI_SD2_t GPIO_QSPI_SD2 at 0x40020010; + register uint32 GPIO_QSPI_SD2_raw at 0x40020010; + + enum GPIO_QSPI_SD3_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO_QSPI_SD3_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO_QSPI_SD3_t GPIO_QSPI_SD3 at 0x40020014; + register uint32 GPIO_QSPI_SD3_raw at 0x40020014; + + enum GPIO_QSPI_SS_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } + + type GPIO_QSPI_SS_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits + } + + // Pad control register + register GPIO_QSPI_SS_t GPIO_QSPI_SS at 0x40020018; + register uint32 GPIO_QSPI_SS_raw at 0x40020018; + + +/* Types and registers for IO_QSPI */ + + type GPIO_QSPI_SCLK_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO_QSPI_SCLK_STATUS_t GPIO_QSPI_SCLK_STATUS at 0x40018000; + register uint32 GPIO_QSPI_SCLK_STATUS_raw at 0x40018000; + + enum GPIO_QSPI_SCLK_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SCLK_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SCLK_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SCLK_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SCLK_CTRL_FUNCSEL { + xip_sclk = 0, // + sio_30 = 5, // + null = 31 // + } + + type GPIO_QSPI_SCLK_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SCLK_CTRL_t GPIO_QSPI_SCLK_CTRL at 0x40018004; + register uint32 GPIO_QSPI_SCLK_CTRL_raw at 0x40018004; + + type GPIO_QSPI_SS_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO_QSPI_SS_STATUS_t GPIO_QSPI_SS_STATUS at 0x40018008; + register uint32 GPIO_QSPI_SS_STATUS_raw at 0x40018008; + + enum GPIO_QSPI_SS_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SS_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SS_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SS_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SS_CTRL_FUNCSEL { + xip_ss_n = 0, // + sio_31 = 5, // + null = 31 // + } + + type GPIO_QSPI_SS_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SS_CTRL_t GPIO_QSPI_SS_CTRL at 0x4001800c; + register uint32 GPIO_QSPI_SS_CTRL_raw at 0x4001800c; + + type GPIO_QSPI_SD0_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO_QSPI_SD0_STATUS_t GPIO_QSPI_SD0_STATUS at 0x40018010; + register uint32 GPIO_QSPI_SD0_STATUS_raw at 0x40018010; + + enum GPIO_QSPI_SD0_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SD0_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SD0_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SD0_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SD0_CTRL_FUNCSEL { + xip_sd0 = 0, // + sio_32 = 5, // + null = 31 // + } + + type GPIO_QSPI_SD0_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SD0_CTRL_t GPIO_QSPI_SD0_CTRL at 0x40018014; + register uint32 GPIO_QSPI_SD0_CTRL_raw at 0x40018014; + + type GPIO_QSPI_SD1_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO_QSPI_SD1_STATUS_t GPIO_QSPI_SD1_STATUS at 0x40018018; + register uint32 GPIO_QSPI_SD1_STATUS_raw at 0x40018018; + + enum GPIO_QSPI_SD1_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SD1_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SD1_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SD1_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SD1_CTRL_FUNCSEL { + xip_sd1 = 0, // + sio_33 = 5, // + null = 31 // + } + + type GPIO_QSPI_SD1_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SD1_CTRL_t GPIO_QSPI_SD1_CTRL at 0x4001801c; + register uint32 GPIO_QSPI_SD1_CTRL_raw at 0x4001801c; + + type GPIO_QSPI_SD2_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO_QSPI_SD2_STATUS_t GPIO_QSPI_SD2_STATUS at 0x40018020; + register uint32 GPIO_QSPI_SD2_STATUS_raw at 0x40018020; + + enum GPIO_QSPI_SD2_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SD2_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SD2_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SD2_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SD2_CTRL_FUNCSEL { + xip_sd2 = 0, // + sio_34 = 5, // + null = 31 // + } + + type GPIO_QSPI_SD2_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SD2_CTRL_t GPIO_QSPI_SD2_CTRL at 0x40018024; + register uint32 GPIO_QSPI_SD2_CTRL_raw at 0x40018024; + + type GPIO_QSPI_SD3_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO_QSPI_SD3_STATUS_t GPIO_QSPI_SD3_STATUS at 0x40018028; + register uint32 GPIO_QSPI_SD3_STATUS_raw at 0x40018028; + + enum GPIO_QSPI_SD3_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SD3_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SD3_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SD3_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SD3_CTRL_FUNCSEL { + xip_sd3 = 0, // + sio_35 = 5, // + null = 31 // + } + + type GPIO_QSPI_SD3_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SD3_CTRL_t GPIO_QSPI_SD3_CTRL at 0x4001802c; + register uint32 GPIO_QSPI_SD3_CTRL_raw at 0x4001802c; + + type IO_QSPI_INTR_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Raw Interrupts + register IO_QSPI_INTR_t IO_QSPI_INTR at 0x40018030; + register uint32 IO_QSPI_INTR_raw at 0x40018030; + + type PROC0_INTE_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Enable for proc0 + register PROC0_INTE_t PROC0_INTE at 0x40018034; + register uint32 PROC0_INTE_raw at 0x40018034; + + type PROC0_INTF_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Force for proc0 + register PROC0_INTF_t PROC0_INTF at 0x40018038; + register uint32 PROC0_INTF_raw at 0x40018038; + + type PROC0_INTS_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt status after masking & forcing for proc0 + register PROC0_INTS_t PROC0_INTS at 0x4001803c; + register uint32 PROC0_INTS_raw at 0x4001803c; + + type PROC1_INTE_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Enable for proc1 + register PROC1_INTE_t PROC1_INTE at 0x40018040; + register uint32 PROC1_INTE_raw at 0x40018040; + + type PROC1_INTF_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Force for proc1 + register PROC1_INTF_t PROC1_INTF at 0x40018044; + register uint32 PROC1_INTF_raw at 0x40018044; + + type PROC1_INTS_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt status after masking & forcing for proc1 + register PROC1_INTS_t PROC1_INTS at 0x40018048; + register uint32 PROC1_INTS_raw at 0x40018048; + + type DORMANT_WAKE_INTE_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Enable for dormant_wake + register DORMANT_WAKE_INTE_t DORMANT_WAKE_INTE at 0x4001804c; + register uint32 DORMANT_WAKE_INTE_raw at 0x4001804c; + + type DORMANT_WAKE_INTF_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Force for dormant_wake + register DORMANT_WAKE_INTF_t DORMANT_WAKE_INTF at 0x40018050; + register uint32 DORMANT_WAKE_INTF_raw at 0x40018050; + + type DORMANT_WAKE_INTS_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt status after masking & forcing for dormant_wake + register DORMANT_WAKE_INTS_t DORMANT_WAKE_INTS at 0x40018054; + register uint32 DORMANT_WAKE_INTS_raw at 0x40018054; + + +/* Types and registers for IO_BANK0 */ + + type GPIO0_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO0_STATUS_t GPIO0_STATUS at 0x40014000; + register uint32 GPIO0_STATUS_raw at 0x40014000; + + enum GPIO0_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO0_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO0_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO0_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO0_CTRL_FUNCSEL { + jtag_tck = 0, // + spi0_rx = 1, // + uart0_tx = 2, // + i2c0_sda = 3, // + pwm_a_0 = 4, // + sio_0 = 5, // + pio0_0 = 6, // + pio1_0 = 7, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } + + type GPIO0_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO0_CTRL_t GPIO0_CTRL at 0x40014004; + register uint32 GPIO0_CTRL_raw at 0x40014004; + + type GPIO1_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO1_STATUS_t GPIO1_STATUS at 0x40014008; + register uint32 GPIO1_STATUS_raw at 0x40014008; + + enum GPIO1_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO1_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO1_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO1_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO1_CTRL_FUNCSEL { + jtag_tms = 0, // + spi0_ss_n = 1, // + uart0_rx = 2, // + i2c0_scl = 3, // + pwm_b_0 = 4, // + sio_1 = 5, // + pio0_1 = 6, // + pio1_1 = 7, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } + + type GPIO1_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO1_CTRL_t GPIO1_CTRL at 0x4001400c; + register uint32 GPIO1_CTRL_raw at 0x4001400c; + + type GPIO2_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO2_STATUS_t GPIO2_STATUS at 0x40014010; + register uint32 GPIO2_STATUS_raw at 0x40014010; + + enum GPIO2_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO2_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO2_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO2_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO2_CTRL_FUNCSEL { + jtag_tdi = 0, // + spi0_sclk = 1, // + uart0_cts = 2, // + i2c1_sda = 3, // + pwm_a_1 = 4, // + sio_2 = 5, // + pio0_2 = 6, // + pio1_2 = 7, // + usb_muxing_vbus_en = 9, // + null = 31 // + } + + type GPIO2_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO2_CTRL_t GPIO2_CTRL at 0x40014014; + register uint32 GPIO2_CTRL_raw at 0x40014014; + + type GPIO3_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO3_STATUS_t GPIO3_STATUS at 0x40014018; + register uint32 GPIO3_STATUS_raw at 0x40014018; + + enum GPIO3_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO3_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO3_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO3_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO3_CTRL_FUNCSEL { + jtag_tdo = 0, // + spi0_tx = 1, // + uart0_rts = 2, // + i2c1_scl = 3, // + pwm_b_1 = 4, // + sio_3 = 5, // + pio0_3 = 6, // + pio1_3 = 7, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } + + type GPIO3_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO3_CTRL_t GPIO3_CTRL at 0x4001401c; + register uint32 GPIO3_CTRL_raw at 0x4001401c; + + type GPIO4_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO4_STATUS_t GPIO4_STATUS at 0x40014020; + register uint32 GPIO4_STATUS_raw at 0x40014020; + + enum GPIO4_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO4_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO4_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO4_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO4_CTRL_FUNCSEL { + spi0_rx = 1, // + uart1_tx = 2, // + i2c0_sda = 3, // + pwm_a_2 = 4, // + sio_4 = 5, // + pio0_4 = 6, // + pio1_4 = 7, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } + + type GPIO4_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO4_CTRL_t GPIO4_CTRL at 0x40014024; + register uint32 GPIO4_CTRL_raw at 0x40014024; + + type GPIO5_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO5_STATUS_t GPIO5_STATUS at 0x40014028; + register uint32 GPIO5_STATUS_raw at 0x40014028; + + enum GPIO5_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO5_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO5_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO5_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO5_CTRL_FUNCSEL { + spi0_ss_n = 1, // + uart1_rx = 2, // + i2c0_scl = 3, // + pwm_b_2 = 4, // + sio_5 = 5, // + pio0_5 = 6, // + pio1_5 = 7, // + usb_muxing_vbus_en = 9, // + null = 31 // + } + + type GPIO5_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO5_CTRL_t GPIO5_CTRL at 0x4001402c; + register uint32 GPIO5_CTRL_raw at 0x4001402c; + + type GPIO6_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO6_STATUS_t GPIO6_STATUS at 0x40014030; + register uint32 GPIO6_STATUS_raw at 0x40014030; + + enum GPIO6_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO6_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO6_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO6_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO6_CTRL_FUNCSEL { + spi0_sclk = 1, // + uart1_cts = 2, // + i2c1_sda = 3, // + pwm_a_3 = 4, // + sio_6 = 5, // + pio0_6 = 6, // + pio1_6 = 7, // + usb_muxing_extphy_softcon = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } + + type GPIO6_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO6_CTRL_t GPIO6_CTRL at 0x40014034; + register uint32 GPIO6_CTRL_raw at 0x40014034; + + type GPIO7_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO7_STATUS_t GPIO7_STATUS at 0x40014038; + register uint32 GPIO7_STATUS_raw at 0x40014038; + + enum GPIO7_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO7_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO7_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO7_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO7_CTRL_FUNCSEL { + spi0_tx = 1, // + uart1_rts = 2, // + i2c1_scl = 3, // + pwm_b_3 = 4, // + sio_7 = 5, // + pio0_7 = 6, // + pio1_7 = 7, // + usb_muxing_extphy_oe_n = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } + + type GPIO7_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO7_CTRL_t GPIO7_CTRL at 0x4001403c; + register uint32 GPIO7_CTRL_raw at 0x4001403c; + + type GPIO8_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO8_STATUS_t GPIO8_STATUS at 0x40014040; + register uint32 GPIO8_STATUS_raw at 0x40014040; + + enum GPIO8_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO8_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO8_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO8_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO8_CTRL_FUNCSEL { + spi1_rx = 1, // + uart1_tx = 2, // + i2c0_sda = 3, // + pwm_a_4 = 4, // + sio_8 = 5, // + pio0_8 = 6, // + pio1_8 = 7, // + usb_muxing_extphy_rcv = 8, // + usb_muxing_vbus_en = 9, // + null = 31 // + } + + type GPIO8_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO8_CTRL_t GPIO8_CTRL at 0x40014044; + register uint32 GPIO8_CTRL_raw at 0x40014044; + + type GPIO9_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO9_STATUS_t GPIO9_STATUS at 0x40014048; + register uint32 GPIO9_STATUS_raw at 0x40014048; + + enum GPIO9_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO9_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO9_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO9_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO9_CTRL_FUNCSEL { + spi1_ss_n = 1, // + uart1_rx = 2, // + i2c0_scl = 3, // + pwm_b_4 = 4, // + sio_9 = 5, // + pio0_9 = 6, // + pio1_9 = 7, // + usb_muxing_extphy_vp = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } + + type GPIO9_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO9_CTRL_t GPIO9_CTRL at 0x4001404c; + register uint32 GPIO9_CTRL_raw at 0x4001404c; + + type GPIO10_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO10_STATUS_t GPIO10_STATUS at 0x40014050; + register uint32 GPIO10_STATUS_raw at 0x40014050; + + enum GPIO10_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO10_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO10_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO10_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO10_CTRL_FUNCSEL { + spi1_sclk = 1, // + uart1_cts = 2, // + i2c1_sda = 3, // + pwm_a_5 = 4, // + sio_10 = 5, // + pio0_10 = 6, // + pio1_10 = 7, // + usb_muxing_extphy_vm = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } + + type GPIO10_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO10_CTRL_t GPIO10_CTRL at 0x40014054; + register uint32 GPIO10_CTRL_raw at 0x40014054; + + type GPIO11_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO11_STATUS_t GPIO11_STATUS at 0x40014058; + register uint32 GPIO11_STATUS_raw at 0x40014058; + + enum GPIO11_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO11_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO11_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO11_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO11_CTRL_FUNCSEL { + spi1_tx = 1, // + uart1_rts = 2, // + i2c1_scl = 3, // + pwm_b_5 = 4, // + sio_11 = 5, // + pio0_11 = 6, // + pio1_11 = 7, // + usb_muxing_extphy_suspnd = 8, // + usb_muxing_vbus_en = 9, // + null = 31 // + } + + type GPIO11_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO11_CTRL_t GPIO11_CTRL at 0x4001405c; + register uint32 GPIO11_CTRL_raw at 0x4001405c; + + type GPIO12_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO12_STATUS_t GPIO12_STATUS at 0x40014060; + register uint32 GPIO12_STATUS_raw at 0x40014060; + + enum GPIO12_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO12_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO12_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO12_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO12_CTRL_FUNCSEL { + spi1_rx = 1, // + uart0_tx = 2, // + i2c0_sda = 3, // + pwm_a_6 = 4, // + sio_12 = 5, // + pio0_12 = 6, // + pio1_12 = 7, // + usb_muxing_extphy_speed = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } + + type GPIO12_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO12_CTRL_t GPIO12_CTRL at 0x40014064; + register uint32 GPIO12_CTRL_raw at 0x40014064; + + type GPIO13_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO13_STATUS_t GPIO13_STATUS at 0x40014068; + register uint32 GPIO13_STATUS_raw at 0x40014068; + + enum GPIO13_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO13_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO13_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO13_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO13_CTRL_FUNCSEL { + spi1_ss_n = 1, // + uart0_rx = 2, // + i2c0_scl = 3, // + pwm_b_6 = 4, // + sio_13 = 5, // + pio0_13 = 6, // + pio1_13 = 7, // + usb_muxing_extphy_vpo = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } + + type GPIO13_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO13_CTRL_t GPIO13_CTRL at 0x4001406c; + register uint32 GPIO13_CTRL_raw at 0x4001406c; + + type GPIO14_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO14_STATUS_t GPIO14_STATUS at 0x40014070; + register uint32 GPIO14_STATUS_raw at 0x40014070; + + enum GPIO14_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO14_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO14_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO14_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO14_CTRL_FUNCSEL { + spi1_sclk = 1, // + uart0_cts = 2, // + i2c1_sda = 3, // + pwm_a_7 = 4, // + sio_14 = 5, // + pio0_14 = 6, // + pio1_14 = 7, // + usb_muxing_extphy_vmo = 8, // + usb_muxing_vbus_en = 9, // + null = 31 // + } + + type GPIO14_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO14_CTRL_t GPIO14_CTRL at 0x40014074; + register uint32 GPIO14_CTRL_raw at 0x40014074; + + type GPIO15_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO15_STATUS_t GPIO15_STATUS at 0x40014078; + register uint32 GPIO15_STATUS_raw at 0x40014078; + + enum GPIO15_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO15_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO15_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO15_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO15_CTRL_FUNCSEL { + spi1_tx = 1, // + uart0_rts = 2, // + i2c1_scl = 3, // + pwm_b_7 = 4, // + sio_15 = 5, // + pio0_15 = 6, // + pio1_15 = 7, // + usb_muxing_digital_dp = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } + + type GPIO15_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO15_CTRL_t GPIO15_CTRL at 0x4001407c; + register uint32 GPIO15_CTRL_raw at 0x4001407c; + + type GPIO16_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO16_STATUS_t GPIO16_STATUS at 0x40014080; + register uint32 GPIO16_STATUS_raw at 0x40014080; + + enum GPIO16_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO16_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO16_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO16_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO16_CTRL_FUNCSEL { + spi0_rx = 1, // + uart0_tx = 2, // + i2c0_sda = 3, // + pwm_a_0 = 4, // + sio_16 = 5, // + pio0_16 = 6, // + pio1_16 = 7, // + usb_muxing_digital_dm = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } + + type GPIO16_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO16_CTRL_t GPIO16_CTRL at 0x40014084; + register uint32 GPIO16_CTRL_raw at 0x40014084; + + type GPIO17_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO17_STATUS_t GPIO17_STATUS at 0x40014088; + register uint32 GPIO17_STATUS_raw at 0x40014088; + + enum GPIO17_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO17_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO17_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO17_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO17_CTRL_FUNCSEL { + spi0_ss_n = 1, // + uart0_rx = 2, // + i2c0_scl = 3, // + pwm_b_0 = 4, // + sio_17 = 5, // + pio0_17 = 6, // + pio1_17 = 7, // + usb_muxing_vbus_en = 9, // + null = 31 // + } + + type GPIO17_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO17_CTRL_t GPIO17_CTRL at 0x4001408c; + register uint32 GPIO17_CTRL_raw at 0x4001408c; + + type GPIO18_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO18_STATUS_t GPIO18_STATUS at 0x40014090; + register uint32 GPIO18_STATUS_raw at 0x40014090; + + enum GPIO18_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO18_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO18_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO18_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO18_CTRL_FUNCSEL { + spi0_sclk = 1, // + uart0_cts = 2, // + i2c1_sda = 3, // + pwm_a_1 = 4, // + sio_18 = 5, // + pio0_18 = 6, // + pio1_18 = 7, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } + + type GPIO18_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO18_CTRL_t GPIO18_CTRL at 0x40014094; + register uint32 GPIO18_CTRL_raw at 0x40014094; + + type GPIO19_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO19_STATUS_t GPIO19_STATUS at 0x40014098; + register uint32 GPIO19_STATUS_raw at 0x40014098; + + enum GPIO19_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO19_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO19_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO19_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO19_CTRL_FUNCSEL { + spi0_tx = 1, // + uart0_rts = 2, // + i2c1_scl = 3, // + pwm_b_1 = 4, // + sio_19 = 5, // + pio0_19 = 6, // + pio1_19 = 7, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } + + type GPIO19_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO19_CTRL_t GPIO19_CTRL at 0x4001409c; + register uint32 GPIO19_CTRL_raw at 0x4001409c; + + type GPIO20_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO20_STATUS_t GPIO20_STATUS at 0x400140a0; + register uint32 GPIO20_STATUS_raw at 0x400140a0; + + enum GPIO20_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO20_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO20_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO20_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO20_CTRL_FUNCSEL { + spi0_rx = 1, // + uart1_tx = 2, // + i2c0_sda = 3, // + pwm_a_2 = 4, // + sio_20 = 5, // + pio0_20 = 6, // + pio1_20 = 7, // + clocks_gpin_0 = 8, // + usb_muxing_vbus_en = 9, // + null = 31 // + } + + type GPIO20_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO20_CTRL_t GPIO20_CTRL at 0x400140a4; + register uint32 GPIO20_CTRL_raw at 0x400140a4; + + type GPIO21_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO21_STATUS_t GPIO21_STATUS at 0x400140a8; + register uint32 GPIO21_STATUS_raw at 0x400140a8; + + enum GPIO21_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO21_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO21_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO21_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO21_CTRL_FUNCSEL { + spi0_ss_n = 1, // + uart1_rx = 2, // + i2c0_scl = 3, // + pwm_b_2 = 4, // + sio_21 = 5, // + pio0_21 = 6, // + pio1_21 = 7, // + clocks_gpout_0 = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } + + type GPIO21_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO21_CTRL_t GPIO21_CTRL at 0x400140ac; + register uint32 GPIO21_CTRL_raw at 0x400140ac; + + type GPIO22_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO22_STATUS_t GPIO22_STATUS at 0x400140b0; + register uint32 GPIO22_STATUS_raw at 0x400140b0; + + enum GPIO22_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO22_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO22_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO22_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO22_CTRL_FUNCSEL { + spi0_sclk = 1, // + uart1_cts = 2, // + i2c1_sda = 3, // + pwm_a_3 = 4, // + sio_22 = 5, // + pio0_22 = 6, // + pio1_22 = 7, // + clocks_gpin_1 = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } + + type GPIO22_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO22_CTRL_t GPIO22_CTRL at 0x400140b4; + register uint32 GPIO22_CTRL_raw at 0x400140b4; + + type GPIO23_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO23_STATUS_t GPIO23_STATUS at 0x400140b8; + register uint32 GPIO23_STATUS_raw at 0x400140b8; + + enum GPIO23_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO23_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO23_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO23_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO23_CTRL_FUNCSEL { + spi0_tx = 1, // + uart1_rts = 2, // + i2c1_scl = 3, // + pwm_b_3 = 4, // + sio_23 = 5, // + pio0_23 = 6, // + pio1_23 = 7, // + clocks_gpout_1 = 8, // + usb_muxing_vbus_en = 9, // + null = 31 // + } + + type GPIO23_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO23_CTRL_t GPIO23_CTRL at 0x400140bc; + register uint32 GPIO23_CTRL_raw at 0x400140bc; + + type GPIO24_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO24_STATUS_t GPIO24_STATUS at 0x400140c0; + register uint32 GPIO24_STATUS_raw at 0x400140c0; + + enum GPIO24_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO24_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO24_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO24_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO24_CTRL_FUNCSEL { + spi1_rx = 1, // + uart1_tx = 2, // + i2c0_sda = 3, // + pwm_a_4 = 4, // + sio_24 = 5, // + pio0_24 = 6, // + pio1_24 = 7, // + clocks_gpout_2 = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } + + type GPIO24_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO24_CTRL_t GPIO24_CTRL at 0x400140c4; + register uint32 GPIO24_CTRL_raw at 0x400140c4; + + type GPIO25_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO25_STATUS_t GPIO25_STATUS at 0x400140c8; + register uint32 GPIO25_STATUS_raw at 0x400140c8; + + enum GPIO25_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO25_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO25_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO25_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO25_CTRL_FUNCSEL { + spi1_ss_n = 1, // + uart1_rx = 2, // + i2c0_scl = 3, // + pwm_b_4 = 4, // + sio_25 = 5, // + pio0_25 = 6, // + pio1_25 = 7, // + clocks_gpout_3 = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } + + type GPIO25_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO25_CTRL_t GPIO25_CTRL at 0x400140cc; + register uint32 GPIO25_CTRL_raw at 0x400140cc; + + type GPIO26_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO26_STATUS_t GPIO26_STATUS at 0x400140d0; + register uint32 GPIO26_STATUS_raw at 0x400140d0; + + enum GPIO26_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO26_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO26_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO26_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO26_CTRL_FUNCSEL { + spi1_sclk = 1, // + uart1_cts = 2, // + i2c1_sda = 3, // + pwm_a_5 = 4, // + sio_26 = 5, // + pio0_26 = 6, // + pio1_26 = 7, // + usb_muxing_vbus_en = 9, // + null = 31 // + } + + type GPIO26_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO26_CTRL_t GPIO26_CTRL at 0x400140d4; + register uint32 GPIO26_CTRL_raw at 0x400140d4; + + type GPIO27_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO27_STATUS_t GPIO27_STATUS at 0x400140d8; + register uint32 GPIO27_STATUS_raw at 0x400140d8; + + enum GPIO27_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO27_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO27_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO27_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO27_CTRL_FUNCSEL { + spi1_tx = 1, // + uart1_rts = 2, // + i2c1_scl = 3, // + pwm_b_5 = 4, // + sio_27 = 5, // + pio0_27 = 6, // + pio1_27 = 7, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } + + type GPIO27_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO27_CTRL_t GPIO27_CTRL at 0x400140dc; + register uint32 GPIO27_CTRL_raw at 0x400140dc; + + type GPIO28_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO28_STATUS_t GPIO28_STATUS at 0x400140e0; + register uint32 GPIO28_STATUS_raw at 0x400140e0; + + enum GPIO28_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO28_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO28_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO28_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO28_CTRL_FUNCSEL { + spi1_rx = 1, // + uart0_tx = 2, // + i2c0_sda = 3, // + pwm_a_6 = 4, // + sio_28 = 5, // + pio0_28 = 6, // + pio1_28 = 7, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } + + type GPIO28_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO28_CTRL_t GPIO28_CTRL at 0x400140e4; + register uint32 GPIO28_CTRL_raw at 0x400140e4; + + type GPIO29_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits + } + + // GPIO status + register GPIO29_STATUS_t GPIO29_STATUS at 0x400140e8; + register uint32 GPIO29_STATUS_raw at 0x400140e8; + + enum GPIO29_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO29_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO29_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO29_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO29_CTRL_FUNCSEL { + spi1_ss_n = 1, // + uart0_rx = 2, // + i2c0_scl = 3, // + pwm_b_6 = 4, // + sio_29 = 5, // + pio0_29 = 6, // + pio1_29 = 7, // + usb_muxing_vbus_en = 9, // + null = 31 // + } + + type GPIO29_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits + IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits + } + + // GPIO control including function select and overrides. + register GPIO29_CTRL_t GPIO29_CTRL at 0x400140ec; + register uint32 GPIO29_CTRL_raw at 0x400140ec; + + type INTR0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Raw Interrupts + register INTR0_t INTR0 at 0x400140f0; + register uint32 INTR0_raw at 0x400140f0; + + type IO_BANK0_INTR1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Raw Interrupts + register IO_BANK0_INTR1_t IO_BANK0_INTR1 at 0x400140f4; + register uint32 IO_BANK0_INTR1_raw at 0x400140f4; + + type INTR2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Raw Interrupts + register INTR2_t INTR2 at 0x400140f8; + register uint32 INTR2_raw at 0x400140f8; + + type INTR3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Raw Interrupts + register INTR3_t INTR3 at 0x400140fc; + register uint32 INTR3_raw at 0x400140fc; + + type PROC0_INTE0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc0 + register PROC0_INTE0_t PROC0_INTE0 at 0x40014100; + register uint32 PROC0_INTE0_raw at 0x40014100; + + type PROC0_INTE1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc0 + register PROC0_INTE1_t PROC0_INTE1 at 0x40014104; + register uint32 PROC0_INTE1_raw at 0x40014104; + + type PROC0_INTE2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc0 + register PROC0_INTE2_t PROC0_INTE2 at 0x40014108; + register uint32 PROC0_INTE2_raw at 0x40014108; + + type PROC0_INTE3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Enable for proc0 + register PROC0_INTE3_t PROC0_INTE3 at 0x4001410c; + register uint32 PROC0_INTE3_raw at 0x4001410c; + + type PROC0_INTF0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Force for proc0 + register PROC0_INTF0_t PROC0_INTF0 at 0x40014110; + register uint32 PROC0_INTF0_raw at 0x40014110; + + type PROC0_INTF1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Force for proc0 + register PROC0_INTF1_t PROC0_INTF1 at 0x40014114; + register uint32 PROC0_INTF1_raw at 0x40014114; + + type PROC0_INTF2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Force for proc0 + register PROC0_INTF2_t PROC0_INTF2 at 0x40014118; + register uint32 PROC0_INTF2_raw at 0x40014118; + + type PROC0_INTF3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Force for proc0 + register PROC0_INTF3_t PROC0_INTF3 at 0x4001411c; + register uint32 PROC0_INTF3_raw at 0x4001411c; + + type PROC0_INTS0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc0 + register PROC0_INTS0_t PROC0_INTS0 at 0x40014120; + register uint32 PROC0_INTS0_raw at 0x40014120; + + type PROC0_INTS1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc0 + register PROC0_INTS1_t PROC0_INTS1 at 0x40014124; + register uint32 PROC0_INTS1_raw at 0x40014124; + + type PROC0_INTS2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc0 + register PROC0_INTS2_t PROC0_INTS2 at 0x40014128; + register uint32 PROC0_INTS2_raw at 0x40014128; + + type PROC0_INTS3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt status after masking & forcing for proc0 + register PROC0_INTS3_t PROC0_INTS3 at 0x4001412c; + register uint32 PROC0_INTS3_raw at 0x4001412c; + + type PROC1_INTE0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc1 + register PROC1_INTE0_t PROC1_INTE0 at 0x40014130; + register uint32 PROC1_INTE0_raw at 0x40014130; + + type PROC1_INTE1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc1 + register PROC1_INTE1_t PROC1_INTE1 at 0x40014134; + register uint32 PROC1_INTE1_raw at 0x40014134; + + type PROC1_INTE2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc1 + register PROC1_INTE2_t PROC1_INTE2 at 0x40014138; + register uint32 PROC1_INTE2_raw at 0x40014138; + + type PROC1_INTE3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Enable for proc1 + register PROC1_INTE3_t PROC1_INTE3 at 0x4001413c; + register uint32 PROC1_INTE3_raw at 0x4001413c; + + type PROC1_INTF0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Force for proc1 + register PROC1_INTF0_t PROC1_INTF0 at 0x40014140; + register uint32 PROC1_INTF0_raw at 0x40014140; + + type PROC1_INTF1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Force for proc1 + register PROC1_INTF1_t PROC1_INTF1 at 0x40014144; + register uint32 PROC1_INTF1_raw at 0x40014144; + + type PROC1_INTF2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Force for proc1 + register PROC1_INTF2_t PROC1_INTF2 at 0x40014148; + register uint32 PROC1_INTF2_raw at 0x40014148; + + type PROC1_INTF3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Force for proc1 + register PROC1_INTF3_t PROC1_INTF3 at 0x4001414c; + register uint32 PROC1_INTF3_raw at 0x4001414c; + + type PROC1_INTS0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc1 + register PROC1_INTS0_t PROC1_INTS0 at 0x40014150; + register uint32 PROC1_INTS0_raw at 0x40014150; + + type PROC1_INTS1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc1 + register PROC1_INTS1_t PROC1_INTS1 at 0x40014154; + register uint32 PROC1_INTS1_raw at 0x40014154; + + type PROC1_INTS2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc1 + register PROC1_INTS2_t PROC1_INTS2 at 0x40014158; + register uint32 PROC1_INTS2_raw at 0x40014158; + + type PROC1_INTS3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt status after masking & forcing for proc1 + register PROC1_INTS3_t PROC1_INTS3 at 0x4001415c; + register uint32 PROC1_INTS3_raw at 0x4001415c; + + type DORMANT_WAKE_INTE0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Enable for dormant_wake + register DORMANT_WAKE_INTE0_t DORMANT_WAKE_INTE0 at 0x40014160; + register uint32 DORMANT_WAKE_INTE0_raw at 0x40014160; + + type DORMANT_WAKE_INTE1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Enable for dormant_wake + register DORMANT_WAKE_INTE1_t DORMANT_WAKE_INTE1 at 0x40014164; + register uint32 DORMANT_WAKE_INTE1_raw at 0x40014164; + + type DORMANT_WAKE_INTE2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Enable for dormant_wake + register DORMANT_WAKE_INTE2_t DORMANT_WAKE_INTE2 at 0x40014168; + register uint32 DORMANT_WAKE_INTE2_raw at 0x40014168; + + type DORMANT_WAKE_INTE3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Enable for dormant_wake + register DORMANT_WAKE_INTE3_t DORMANT_WAKE_INTE3 at 0x4001416c; + register uint32 DORMANT_WAKE_INTE3_raw at 0x4001416c; + + type DORMANT_WAKE_INTF0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Force for dormant_wake + register DORMANT_WAKE_INTF0_t DORMANT_WAKE_INTF0 at 0x40014170; + register uint32 DORMANT_WAKE_INTF0_raw at 0x40014170; + + type DORMANT_WAKE_INTF1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Force for dormant_wake + register DORMANT_WAKE_INTF1_t DORMANT_WAKE_INTF1 at 0x40014174; + register uint32 DORMANT_WAKE_INTF1_raw at 0x40014174; + + type DORMANT_WAKE_INTF2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Force for dormant_wake + register DORMANT_WAKE_INTF2_t DORMANT_WAKE_INTF2 at 0x40014178; + register uint32 DORMANT_WAKE_INTF2_raw at 0x40014178; + + type DORMANT_WAKE_INTF3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt Force for dormant_wake + register DORMANT_WAKE_INTF3_t DORMANT_WAKE_INTF3 at 0x4001417c; + register uint32 DORMANT_WAKE_INTF3_raw at 0x4001417c; + + type DORMANT_WAKE_INTS0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for dormant_wake + register DORMANT_WAKE_INTS0_t DORMANT_WAKE_INTS0 at 0x40014180; + register uint32 DORMANT_WAKE_INTS0_raw at 0x40014180; + + type DORMANT_WAKE_INTS1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for dormant_wake + register DORMANT_WAKE_INTS1_t DORMANT_WAKE_INTS1 at 0x40014184; + register uint32 DORMANT_WAKE_INTS1_raw at 0x40014184; + + type DORMANT_WAKE_INTS2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for dormant_wake + register DORMANT_WAKE_INTS2_t DORMANT_WAKE_INTS2 at 0x40014188; + register uint32 DORMANT_WAKE_INTS2_raw at 0x40014188; + + type DORMANT_WAKE_INTS3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Interrupt status after masking & forcing for dormant_wake + register DORMANT_WAKE_INTS3_t DORMANT_WAKE_INTS3 at 0x4001418c; + register uint32 DORMANT_WAKE_INTS3_raw at 0x4001418c; + + +/* Types and registers for SYSINFO */ + + type CHIP_ID_t { + MANUFACTURER = uint12(0); // + PART = uint16(0); // + REVISION = uint4(0); // + } + + // JEDEC JEP-106 compliant chip identifier. + register CHIP_ID_t CHIP_ID at 0x40000000; + register uint32 CHIP_ID_raw at 0x40000000; + + type SYSINFO_PLATFORM_t { + FPGA = false; // + ASIC = false; // + _res1 = uint30(0); // Reserved, 30 bits + } + + // Platform register. Allows software to know what environment it is running in. + register SYSINFO_PLATFORM_t SYSINFO_PLATFORM at 0x40000004; + register uint32 SYSINFO_PLATFORM_raw at 0x40000004; + + type GITREF_RP2040_t { + GITREF_RP2040 = uint32(0); // + } + + // Git hash of the chip source. Used to identify chip version. + register GITREF_RP2040_t GITREF_RP2040 at 0x40000010; + register uint32 GITREF_RP2040_raw at 0x40000010; + + +/* Types and registers for PPB */ + + type SYST_CSR_t { + ENABLE = false; // Enable SysTick counter: 0 = Counter disabled. 1 = Counter enabled. + TICKINT = false; // Enables SysTick exception request: 0 = Counting down to zero does not assert the SysTick exception request. 1 = Counting down to zero to asserts the SysTick exception request. + CLKSOURCE = false; // SysTick clock source. Always reads as one if SYST_CALIB reports NOREF. Selects the SysTick timer clock source: 0 = External reference clock. 1 = Processor clock. + _res1 = uint13(0); // Reserved, 13 bits + COUNTFLAG = false; // Returns 1 if timer counted to 0 since last time this was read. Clears on read by application or debugger. + _res2 = uint15(0); // Reserved, 15 bits + } + + // Use the SysTick Control and Status Register to enable the SysTick features. + register SYST_CSR_t SYST_CSR at 0xe000e010; + register uint32 SYST_CSR_raw at 0xe000e010; + + type SYST_RVR_t { + RELOAD = uint24(0); // Value to load into the SysTick Current Value Register when the counter reaches 0. + _res1 = uint8(0); // Reserved, 8 bits + } + + // Use the SysTick Reload Value Register to specify the start value to load into the current value register when the counter reaches 0. It can be any value between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect because the SysTick interrupt and COUNTFLAG are activated when counting from 1 to 0. The reset value of this register is UNKNOWN. To generate a multi-shot timer with a period of N processor clock cycles, use a RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 clock pulses, set RELOAD to 99. + register SYST_RVR_t SYST_RVR at 0xe000e014; + register uint32 SYST_RVR_raw at 0xe000e014; + + type SYST_CVR_t { + CURRENT = uint24(0); // Reads return the current value of the SysTick counter. This register is write-clear. Writing to it with any value clears the register to 0. Clearing this register also clears the COUNTFLAG bit of the SysTick Control and Status Register. + _res1 = uint8(0); // Reserved, 8 bits + } + + // Use the SysTick Current Value Register to find the current value in the register. The reset value of this register is UNKNOWN. + register SYST_CVR_t SYST_CVR at 0xe000e018; + register uint32 SYST_CVR_raw at 0xe000e018; + + type SYST_CALIB_t { + TENMS = uint24(0); // An optional Reload value to be used for 10ms (100Hz) timing, subject to system clock skew errors. If the value reads as 0, the calibration value is not known. + _res1 = uint6(0); // Reserved, 6 bits + SKEW = false; // If reads as 1, the calibration value for 10ms is inexact (due to clock frequency). + NOREF = false; // If reads as 1, the Reference clock is not provided - the CLKSOURCE bit of the SysTick Control and Status register will be forced to 1 and cannot be cleared to 0. + } + + // Use the SysTick Calibration Value Register to enable software to scale to any required speed using divide and multiply. + register SYST_CALIB_t SYST_CALIB at 0xe000e01c; + register uint32 SYST_CALIB_raw at 0xe000e01c; + + type NVIC_ISER_t { + SETENA = uint32(0); // Interrupt set-enable bits. Write: 0 = No effect. 1 = Enable interrupt. Read: 0 = Interrupt disabled. 1 = Interrupt enabled. + } + + // Use the Interrupt Set-Enable Register to enable interrupts and determine which interrupts are currently enabled. If a pending interrupt is enabled, the NVIC activates the interrupt based on its priority. If an interrupt is not enabled, asserting its interrupt signal changes the interrupt state to pending, but the NVIC never activates the interrupt, regardless of its priority. + register NVIC_ISER_t NVIC_ISER at 0xe000e100; + register uint32 NVIC_ISER_raw at 0xe000e100; + + type NVIC_ICER_t { + CLRENA = uint32(0); // Interrupt clear-enable bits. Write: 0 = No effect. 1 = Disable interrupt. Read: 0 = Interrupt disabled. 1 = Interrupt enabled. + } + + // Use the Interrupt Clear-Enable Registers to disable interrupts and determine which interrupts are currently enabled. + register NVIC_ICER_t NVIC_ICER at 0xe000e180; + register uint32 NVIC_ICER_raw at 0xe000e180; + + type NVIC_ISPR_t { + SETPEND = uint32(0); // Interrupt set-pending bits. Write: 0 = No effect. 1 = Changes interrupt state to pending. Read: 0 = Interrupt is not pending. 1 = Interrupt is pending. Note: Writing 1 to the NVIC_ISPR bit corresponding to: An interrupt that is pending has no effect. A disabled interrupt sets the state of that interrupt to pending. + } + + // The NVIC_ISPR forces interrupts into the pending state, and shows which interrupts are pending. + register NVIC_ISPR_t NVIC_ISPR at 0xe000e200; + register uint32 NVIC_ISPR_raw at 0xe000e200; + + type NVIC_ICPR_t { + CLRPEND = uint32(0); // Interrupt clear-pending bits. Write: 0 = No effect. 1 = Removes pending state and interrupt. Read: 0 = Interrupt is not pending. 1 = Interrupt is pending. + } + + // Use the Interrupt Clear-Pending Register to clear pending interrupts and determine which interrupts are currently pending. + register NVIC_ICPR_t NVIC_ICPR at 0xe000e280; + register uint32 NVIC_ICPR_raw at 0xe000e280; + + type NVIC_IPR0_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_0 = uint2(0); // Priority of interrupt 0 + _res2 = uint6(0); // Reserved, 6 bits + IP_1 = uint2(0); // Priority of interrupt 1 + _res3 = uint6(0); // Reserved, 6 bits + IP_2 = uint2(0); // Priority of interrupt 2 + _res4 = uint6(0); // Reserved, 6 bits + IP_3 = uint2(0); // Priority of interrupt 3 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. Note: Writing 1 to an NVIC_ICPR bit does not affect the active state of the corresponding interrupt. These registers are only word-accessible + register NVIC_IPR0_t NVIC_IPR0 at 0xe000e400; + register uint32 NVIC_IPR0_raw at 0xe000e400; + + type NVIC_IPR1_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_4 = uint2(0); // Priority of interrupt 4 + _res2 = uint6(0); // Reserved, 6 bits + IP_5 = uint2(0); // Priority of interrupt 5 + _res3 = uint6(0); // Reserved, 6 bits + IP_6 = uint2(0); // Priority of interrupt 6 + _res4 = uint6(0); // Reserved, 6 bits + IP_7 = uint2(0); // Priority of interrupt 7 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR1_t NVIC_IPR1 at 0xe000e404; + register uint32 NVIC_IPR1_raw at 0xe000e404; + + type NVIC_IPR2_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_8 = uint2(0); // Priority of interrupt 8 + _res2 = uint6(0); // Reserved, 6 bits + IP_9 = uint2(0); // Priority of interrupt 9 + _res3 = uint6(0); // Reserved, 6 bits + IP_10 = uint2(0); // Priority of interrupt 10 + _res4 = uint6(0); // Reserved, 6 bits + IP_11 = uint2(0); // Priority of interrupt 11 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR2_t NVIC_IPR2 at 0xe000e408; + register uint32 NVIC_IPR2_raw at 0xe000e408; + + type NVIC_IPR3_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_12 = uint2(0); // Priority of interrupt 12 + _res2 = uint6(0); // Reserved, 6 bits + IP_13 = uint2(0); // Priority of interrupt 13 + _res3 = uint6(0); // Reserved, 6 bits + IP_14 = uint2(0); // Priority of interrupt 14 + _res4 = uint6(0); // Reserved, 6 bits + IP_15 = uint2(0); // Priority of interrupt 15 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR3_t NVIC_IPR3 at 0xe000e40c; + register uint32 NVIC_IPR3_raw at 0xe000e40c; + + type NVIC_IPR4_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_16 = uint2(0); // Priority of interrupt 16 + _res2 = uint6(0); // Reserved, 6 bits + IP_17 = uint2(0); // Priority of interrupt 17 + _res3 = uint6(0); // Reserved, 6 bits + IP_18 = uint2(0); // Priority of interrupt 18 + _res4 = uint6(0); // Reserved, 6 bits + IP_19 = uint2(0); // Priority of interrupt 19 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR4_t NVIC_IPR4 at 0xe000e410; + register uint32 NVIC_IPR4_raw at 0xe000e410; + + type NVIC_IPR5_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_20 = uint2(0); // Priority of interrupt 20 + _res2 = uint6(0); // Reserved, 6 bits + IP_21 = uint2(0); // Priority of interrupt 21 + _res3 = uint6(0); // Reserved, 6 bits + IP_22 = uint2(0); // Priority of interrupt 22 + _res4 = uint6(0); // Reserved, 6 bits + IP_23 = uint2(0); // Priority of interrupt 23 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR5_t NVIC_IPR5 at 0xe000e414; + register uint32 NVIC_IPR5_raw at 0xe000e414; + + type NVIC_IPR6_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_24 = uint2(0); // Priority of interrupt 24 + _res2 = uint6(0); // Reserved, 6 bits + IP_25 = uint2(0); // Priority of interrupt 25 + _res3 = uint6(0); // Reserved, 6 bits + IP_26 = uint2(0); // Priority of interrupt 26 + _res4 = uint6(0); // Reserved, 6 bits + IP_27 = uint2(0); // Priority of interrupt 27 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR6_t NVIC_IPR6 at 0xe000e418; + register uint32 NVIC_IPR6_raw at 0xe000e418; + + type NVIC_IPR7_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_28 = uint2(0); // Priority of interrupt 28 + _res2 = uint6(0); // Reserved, 6 bits + IP_29 = uint2(0); // Priority of interrupt 29 + _res3 = uint6(0); // Reserved, 6 bits + IP_30 = uint2(0); // Priority of interrupt 30 + _res4 = uint6(0); // Reserved, 6 bits + IP_31 = uint2(0); // Priority of interrupt 31 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR7_t NVIC_IPR7 at 0xe000e41c; + register uint32 NVIC_IPR7_raw at 0xe000e41c; + + type PPB_CPUID_t { + REVISION = uint4(0); // Minor revision number m in the rnpm revision status: 0x1 = Patch 1. + PARTNO = uint12(0); // Number of processor within family: 0xC60 = Cortex-M0+ + ARCHITECTURE = uint4(0); // Constant that defines the architecture of the processor: 0xC = ARMv6-M architecture. + VARIANT = uint4(0); // Major revision number n in the rnpm revision status: 0x0 = Revision 0. + IMPLEMENTER = uint8(0); // Implementor code: 0x41 = ARM + } + + // Read the CPU ID Base Register to determine: the ID number of the processor core, the version number of the processor core, the implementation details of the processor core. + register PPB_CPUID_t PPB_CPUID at 0xe000ed00; + register uint32 PPB_CPUID_raw at 0xe000ed00; + + type ICSR_t { + VECTACTIVE = uint9(0); // Active exception number field. Reset clears the VECTACTIVE field. + _res1 = uint3(0); // Reserved, 3 bits + VECTPENDING = uint9(0); // Indicates the exception number for the highest priority pending exception: 0 = no pending exceptions. Non zero = The pending state includes the effect of memory-mapped enable and mask registers. It does not include the PRIMASK special-purpose register qualifier. + _res2 = false; // Reserved, 1 bits + ISRPENDING = false; // External interrupt pending flag + ISRPREEMPT = false; // The system can only access this bit when the core is halted. It indicates that a pending interrupt is to be taken in the next running cycle. If C_MASKINTS is clear in the Debug Halting Control and Status Register, the interrupt is serviced. + _res3 = false; // Reserved, 1 bits + PENDSTCLR = false; // SysTick exception clear-pending bit. Write: 0 = No effect. 1 = Removes the pending state from the SysTick exception. This bit is WO. On a register read its value is Unknown. + PENDSTSET = false; // SysTick exception set-pending bit. Write: 0 = No effect. 1 = Changes SysTick exception state to pending. Read: 0 = SysTick exception is not pending. 1 = SysTick exception is pending. + PENDSVCLR = false; // PendSV clear-pending bit. Write: 0 = No effect. 1 = Removes the pending state from the PendSV exception. + PENDSVSET = false; // PendSV set-pending bit. Write: 0 = No effect. 1 = Changes PendSV exception state to pending. Read: 0 = PendSV exception is not pending. 1 = PendSV exception is pending. Writing 1 to this bit is the only way to set the PendSV exception state to pending. + _res4 = uint2(0); // Reserved, 2 bits + NMIPENDSET = false; // Setting this bit will activate an NMI. Since NMI is the highest priority exception, it will activate as soon as it is registered. NMI set-pending bit. Write: 0 = No effect. 1 = Changes NMI exception state to pending. Read: 0 = NMI exception is not pending. 1 = NMI exception is pending. Because NMI is the highest-priority exception, normally the processor enters the NMI exception handler as soon as it detects a write of 1 to this bit. Entering the handler then clears this bit to 0. This means a read of this bit by the NMI exception handler returns 1 only if the NMI signal is reasserted while the processor is executing that handler. + } + + // Use the Interrupt Control State Register to set a pending Non-Maskable Interrupt (NMI), set or clear a pending PendSV, set or clear a pending SysTick, check for pending exceptions, check the vector number of the highest priority pended exception, check the vector number of the active exception. + register ICSR_t ICSR at 0xe000ed04; + register uint32 ICSR_raw at 0xe000ed04; + + type VTOR_t { + _res1 = uint8(0); // Reserved, 8 bits + TBLOFF = uint24(0); // Bits [31:8] of the indicate the vector table offset address. + } + + // The VTOR holds the vector table offset address. + register VTOR_t VTOR at 0xe000ed08; + register uint32 VTOR_raw at 0xe000ed08; + + type AIRCR_t { + _res1 = false; // Reserved, 1 bits + VECTCLRACTIVE = false; // Clears all active state information for fixed and configurable exceptions. This bit: is self-clearing, can only be set by the DAP when the core is halted. When set: clears all active exception status of the processor, forces a return to Thread mode, forces an IPSR of 0. A debugger must re-initialize the stack. + SYSRESETREQ = false; // Writing 1 to this bit causes the SYSRESETREQ signal to the outer system to be asserted to request a reset. The intention is to force a large system reset of all major components except for debug. The C_HALT bit in the DHCSR is cleared as a result of the system reset requested. The debugger does not lose contact with the device. + _res2 = uint12(0); // Reserved, 12 bits + ENDIANESS = false; // Data endianness implemented: 0 = Little-endian. + VECTKEY = uint16(0); // Register key: Reads as Unknown On writes, write 0x05FA to VECTKEY, otherwise the write is ignored. + } + + // Use the Application Interrupt and Reset Control Register to: determine data endianness, clear all active state information from debug halt mode, request a system reset. + register AIRCR_t AIRCR at 0xe000ed0c; + register uint32 AIRCR_raw at 0xe000ed0c; + + type SCR_t { + _res1 = false; // Reserved, 1 bits + SLEEPONEXIT = false; // Indicates sleep-on-exit when returning from Handler mode to Thread mode: 0 = Do not sleep when returning to Thread mode. 1 = Enter sleep, or deep sleep, on return from an ISR to Thread mode. Setting this bit to 1 enables an interrupt driven application to avoid returning to an empty main application. + SLEEPDEEP = false; // Controls whether the processor uses sleep or deep sleep as its low power mode: 0 = Sleep. 1 = Deep sleep. + _res2 = false; // Reserved, 1 bits + SEVONPEND = false; // Send Event on Pending bit: 0 = Only enabled interrupts or events can wakeup the processor, disabled interrupts are excluded. 1 = Enabled events and all interrupts, including disabled interrupts, can wakeup the processor. When an event or interrupt becomes pending, the event signal wakes up the processor from WFE. If the processor is not waiting for an event, the event is registered and affects the next WFE. The processor also wakes up on execution of an SEV instruction or an external event. + _res3 = uint27(0); // Reserved, 27 bits + } + + // System Control Register. Use the System Control Register for power-management functions: signal to the system when the processor can enter a low power state, control how the processor enters and exits low power states. + register SCR_t SCR at 0xe000ed10; + register uint32 SCR_raw at 0xe000ed10; + + type CCR_t { + _res1 = uint3(0); // Reserved, 3 bits + UNALIGN_TRP = false; // Always reads as one, indicates that all unaligned accesses generate a HardFault. + _res2 = uint5(0); // Reserved, 5 bits + STKALIGN = false; // Always reads as one, indicates 8-byte stack alignment on exception entry. On exception entry, the processor uses bit[9] of the stacked PSR to indicate the stack alignment. On return from the exception it uses this stacked bit to restore the correct stack alignment. + _res3 = uint22(0); // Reserved, 22 bits + } + + // The Configuration and Control Register permanently enables stack alignment and causes unaligned accesses to result in a Hard Fault. + register CCR_t CCR at 0xe000ed14; + register uint32 CCR_raw at 0xe000ed14; + + type SHPR2_t { + _res1 = uint30(0); // Reserved, 30 bits + PRI_11 = uint2(0); // Priority of system handler 11, SVCall + } + + // System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 2 to set the priority of SVCall. + register SHPR2_t SHPR2 at 0xe000ed1c; + register uint32 SHPR2_raw at 0xe000ed1c; + + type SHPR3_t { + _res1 = uint22(0); // Reserved, 22 bits + PRI_14 = uint2(0); // Priority of system handler 14, PendSV + _res2 = uint6(0); // Reserved, 6 bits + PRI_15 = uint2(0); // Priority of system handler 15, SysTick + } + + // System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 3 to set the priority of PendSV and SysTick. + register SHPR3_t SHPR3 at 0xe000ed20; + register uint32 SHPR3_raw at 0xe000ed20; + + type SHCSR_t { + _res1 = uint15(0); // Reserved, 15 bits + SVCALLPENDED = false; // Reads as 1 if SVCall is Pending. Write 1 to set pending SVCall, write 0 to clear pending SVCall. + _res2 = uint16(0); // Reserved, 16 bits + } + + // Use the System Handler Control and State Register to determine or clear the pending status of SVCall. + register SHCSR_t SHCSR at 0xe000ed24; + register uint32 SHCSR_raw at 0xe000ed24; + + type MPU_TYPE_t { + SEPARATE = false; // Indicates support for separate instruction and data address maps. Reads as 0 as ARMv6-M only supports a unified MPU. + _res1 = uint7(0); // Reserved, 7 bits + DREGION = uint8(0); // Number of regions supported by the MPU. + IREGION = uint8(0); // Instruction region. Reads as zero as ARMv6-M only supports a unified MPU. + _res2 = uint8(0); // Reserved, 8 bits + } + + // Read the MPU Type Register to determine if the processor implements an MPU, and how many regions the MPU supports. + register MPU_TYPE_t MPU_TYPE at 0xe000ed90; + register uint32 MPU_TYPE_raw at 0xe000ed90; + + type MPU_CTRL_t { + ENABLE = false; // Enables the MPU. If the MPU is disabled, privileged and unprivileged accesses use the default memory map. 0 = MPU disabled. 1 = MPU enabled. + HFNMIENA = false; // Controls the use of the MPU for HardFaults and NMIs. Setting this bit when ENABLE is clear results in UNPREDICTABLE behaviour. When the MPU is enabled: 0 = MPU is disabled during HardFault and NMI handlers, regardless of the value of the ENABLE bit. 1 = the MPU is enabled during HardFault and NMI handlers. + PRIVDEFENA = false; // Controls whether the default memory map is enabled as a background region for privileged accesses. This bit is ignored when ENABLE is clear. 0 = If the MPU is enabled, disables use of the default memory map. Any memory access to a location not covered by any enabled region causes a fault. 1 = If the MPU is enabled, enables use of the default memory map as a background region for privileged software accesses. When enabled, the background region acts as if it is region number -1. Any region that is defined and enabled has priority over this default map. + _res1 = uint29(0); // Reserved, 29 bits + } + + // Use the MPU Control Register to enable and disable the MPU, and to control whether the default memory map is enabled as a background region for privileged accesses, and whether the MPU is enabled for HardFaults and NMIs. + register MPU_CTRL_t MPU_CTRL at 0xe000ed94; + register uint32 MPU_CTRL_raw at 0xe000ed94; + + type MPU_RNR_t { + REGION = uint4(0); // Indicates the MPU region referenced by the MPU_RBAR and MPU_RASR registers. The MPU supports 8 memory regions, so the permitted values of this field are 0-7. + _res1 = uint28(0); // Reserved, 28 bits + } + + // Use the MPU Region Number Register to select the region currently accessed by MPU_RBAR and MPU_RASR. + register MPU_RNR_t MPU_RNR at 0xe000ed98; + register uint32 MPU_RNR_raw at 0xe000ed98; + + type MPU_RBAR_t { + REGION = uint4(0); // On writes, specifies the number of the region whose base address to update provided VALID is set written as 1. On reads, returns bits [3:0] of MPU_RNR. + VALID = false; // On writes, indicates whether the write must update the base address of the region identified by the REGION field, updating the MPU_RNR to indicate this new region. Write: 0 = MPU_RNR not changed, and the processor: Updates the base address for the region specified in the MPU_RNR. Ignores the value of the REGION field. 1 = The processor: Updates the value of the MPU_RNR to the value of the REGION field. Updates the base address for the region specified in the REGION field. Always reads as zero. + _res1 = uint3(0); // Reserved, 3 bits + ADDR = uint24(0); // Base address of the region. + } + + // Read the MPU Region Base Address Register to determine the base address of the region identified by MPU_RNR. Write to update the base address of said region or that of a specified region, with whose number MPU_RNR will also be updated. + register MPU_RBAR_t MPU_RBAR at 0xe000ed9c; + register uint32 MPU_RBAR_raw at 0xe000ed9c; + + type MPU_RASR_t { + ENABLE = false; // Enables the region. + SIZE = uint5(0); // Indicates the region size. Region size in bytes = 2^(SIZE+1). The minimum permitted value is 7 (b00111) = 256Bytes + _res1 = uint2(0); // Reserved, 2 bits + SRD = uint8(0); // Subregion Disable. For regions of 256 bytes or larger, each bit of this field controls whether one of the eight equal subregions is enabled. + ATTRS = uint16(0); // The MPU Region Attribute field. Use to define the region attribute control. 28 = XN: Instruction access disable bit: 0 = Instruction fetches enabled. 1 = Instruction fetches disabled. 26:24 = AP: Access permission field 18 = S: Shareable bit 17 = C: Cacheable bit 16 = B: Bufferable bit + } + + // Use the MPU Region Attribute and Size Register to define the size, access behaviour and memory type of the region identified by MPU_RNR, and enable that region. + register MPU_RASR_t MPU_RASR at 0xe000eda0; + register uint32 MPU_RASR_raw at 0xe000eda0; + + +/* Types and registers for SSI + DW_apb_ssi has the following features: * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. * APB3 and APB4 protocol support. * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits. * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices. * Programmable Dual/Quad/Octal SPI support in Master Mode. * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation. * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes. * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes. * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests. * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently. * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus. * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains. * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates. * Programmable features: - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire. - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation. - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer. * Configured features: - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits. - 1 slave select output. - Hardware slave-select – Dedicated hardware slave-select line. - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller. - Interrupt polarity – active high interrupt lines. - Serial clock polarity – low serial-clock polarity directly after reset. - Serial clock phase – capture on first edge of serial-clock directly after reset. + */ + + enum CTRLR0_SPI_FRF { + STD = 0, // Standard 1-bit SPI frame format; 1 bit per SCK, full-duplex + DUAL = 1, // Dual-SPI frame format; two bits per SCK, half-duplex + QUAD = 2 // Quad-SPI frame format; four bits per SCK, half-duplex + } + + enum CTRLR0_TMOD { + TX_AND_RX = 0, // Both transmit and receive + TX_ONLY = 1, // Transmit only (not for FRF == 0, standard SPI mode) + RX_ONLY = 2, // Receive only (not for FRF == 0, standard SPI mode) + EEPROM_READ = 3 // EEPROM read mode (TX then RX; RX starts after control data TX'd) + } + + type CTRLR0_t { + DFS = uint4(0); // Data frame size + FRF = uint2(0); // Frame format + SCPH = false; // Serial clock phase + SCPOL = false; // Serial clock polarity + TMOD = uint2(0); // Transfer mode + SLV_OE = false; // Slave output enable + SRL = false; // Shift register loop (test mode) + CFS = uint4(0); // Control frame size Value of n -> n+1 clocks per frame. + DFS_32 = uint5(0); // Data frame size in 32b transfer mode Value of n -> n+1 clocks per frame. + SPI_FRF = uint2(0); // SPI frame format + _res1 = false; // Reserved, 1 bits + SSTE = false; // Slave select toggle enable + _res2 = uint7(0); // Reserved, 7 bits + } + + // Control register 0 + register CTRLR0_t CTRLR0 at 0x18000000; + register uint32 CTRLR0_raw at 0x18000000; + + type CTRLR1_t { + NDF = uint16(0); // Number of data frames + _res1 = uint16(0); // Reserved, 16 bits + } + + // Master Control register 1 + register CTRLR1_t CTRLR1 at 0x18000004; + register uint32 CTRLR1_raw at 0x18000004; + + type SSIENR_t { + SSI_EN = false; // SSI enable + _res1 = uint31(0); // Reserved, 31 bits + } + + // SSI Enable + register SSIENR_t SSIENR at 0x18000008; + register uint32 SSIENR_raw at 0x18000008; + + type MWCR_t { + MWMOD = false; // Microwire transfer mode + MDD = false; // Microwire control + MHS = false; // Microwire handshaking + _res1 = uint29(0); // Reserved, 29 bits + } + + // Microwire Control + register MWCR_t MWCR at 0x1800000c; + register uint32 MWCR_raw at 0x1800000c; + + type SER_t { + SER = false; // For each bit: 0 -> slave not selected 1 -> slave selected + _res1 = uint31(0); // Reserved, 31 bits + } + + // Slave enable + register SER_t SER at 0x18000010; + register uint32 SER_raw at 0x18000010; + + type BAUDR_t { + SCKDV = uint16(0); // SSI clock divider + _res1 = uint16(0); // Reserved, 16 bits + } + + // Baud rate + register BAUDR_t BAUDR at 0x18000014; + register uint32 BAUDR_raw at 0x18000014; + + type TXFTLR_t { + TFT = uint8(0); // Transmit FIFO threshold + _res1 = uint24(0); // Reserved, 24 bits + } + + // TX FIFO threshold level + register TXFTLR_t TXFTLR at 0x18000018; + register uint32 TXFTLR_raw at 0x18000018; + + type RXFTLR_t { + RFT = uint8(0); // Receive FIFO threshold + _res1 = uint24(0); // Reserved, 24 bits + } + + // RX FIFO threshold level + register RXFTLR_t RXFTLR at 0x1800001c; + register uint32 RXFTLR_raw at 0x1800001c; + + type TXFLR_t { + TFTFL = uint8(0); // Transmit FIFO level + _res1 = uint24(0); // Reserved, 24 bits + } + + // TX FIFO level + register TXFLR_t TXFLR at 0x18000020; + register uint32 TXFLR_raw at 0x18000020; + + type RXFLR_t { + RXTFL = uint8(0); // Receive FIFO level + _res1 = uint24(0); // Reserved, 24 bits + } + + // RX FIFO level + register RXFLR_t RXFLR at 0x18000024; + register uint32 RXFLR_raw at 0x18000024; + + type SR_t { + BUSY = false; // SSI busy flag + TFNF = false; // Transmit FIFO not full + TFE = false; // Transmit FIFO empty + RFNE = false; // Receive FIFO not empty + RFF = false; // Receive FIFO full + TXE = false; // Transmission error + DCOL = false; // Data collision error + _res1 = uint25(0); // Reserved, 25 bits + } + + // Status register + register SR_t SR at 0x18000028; + register uint32 SR_raw at 0x18000028; + + type IMR_t { + TXEIM = false; // Transmit FIFO empty interrupt mask + TXOIM = false; // Transmit FIFO overflow interrupt mask + RXUIM = false; // Receive FIFO underflow interrupt mask + RXOIM = false; // Receive FIFO overflow interrupt mask + RXFIM = false; // Receive FIFO full interrupt mask + MSTIM = false; // Multi-master contention interrupt mask + _res1 = uint26(0); // Reserved, 26 bits + } + + // Interrupt mask + register IMR_t IMR at 0x1800002c; + register uint32 IMR_raw at 0x1800002c; + + type ISR_t { + TXEIS = false; // Transmit FIFO empty interrupt status + TXOIS = false; // Transmit FIFO overflow interrupt status + RXUIS = false; // Receive FIFO underflow interrupt status + RXOIS = false; // Receive FIFO overflow interrupt status + RXFIS = false; // Receive FIFO full interrupt status + MSTIS = false; // Multi-master contention interrupt status + _res1 = uint26(0); // Reserved, 26 bits + } + + // Interrupt status + register ISR_t ISR at 0x18000030; + register uint32 ISR_raw at 0x18000030; + + type RISR_t { + TXEIR = false; // Transmit FIFO empty raw interrupt status + TXOIR = false; // Transmit FIFO overflow raw interrupt status + RXUIR = false; // Receive FIFO underflow raw interrupt status + RXOIR = false; // Receive FIFO overflow raw interrupt status + RXFIR = false; // Receive FIFO full raw interrupt status + MSTIR = false; // Multi-master contention raw interrupt status + _res1 = uint26(0); // Reserved, 26 bits + } + + // Raw interrupt status + register RISR_t RISR at 0x18000034; + register uint32 RISR_raw at 0x18000034; + + type TXOICR_t { + TXOICR = false; // Clear-on-read transmit FIFO overflow interrupt + _res1 = uint31(0); // Reserved, 31 bits + } + + // TX FIFO overflow interrupt clear + register TXOICR_t TXOICR at 0x18000038; + register uint32 TXOICR_raw at 0x18000038; + + type RXOICR_t { + RXOICR = false; // Clear-on-read receive FIFO overflow interrupt + _res1 = uint31(0); // Reserved, 31 bits + } + + // RX FIFO overflow interrupt clear + register RXOICR_t RXOICR at 0x1800003c; + register uint32 RXOICR_raw at 0x1800003c; + + type RXUICR_t { + RXUICR = false; // Clear-on-read receive FIFO underflow interrupt + _res1 = uint31(0); // Reserved, 31 bits + } + + // RX FIFO underflow interrupt clear + register RXUICR_t RXUICR at 0x18000040; + register uint32 RXUICR_raw at 0x18000040; + + type MSTICR_t { + MSTICR = false; // Clear-on-read multi-master contention interrupt + _res1 = uint31(0); // Reserved, 31 bits + } + + // Multi-master interrupt clear + register MSTICR_t MSTICR at 0x18000044; + register uint32 MSTICR_raw at 0x18000044; + + type ICR_t { + ICR = false; // Clear-on-read all active interrupts + _res1 = uint31(0); // Reserved, 31 bits + } + + // Interrupt clear + register ICR_t ICR at 0x18000048; + register uint32 ICR_raw at 0x18000048; + + type DMACR_t { + RDMAE = false; // Receive DMA enable + TDMAE = false; // Transmit DMA enable + _res1 = uint30(0); // Reserved, 30 bits + } + + // DMA control + register DMACR_t DMACR at 0x1800004c; + register uint32 DMACR_raw at 0x1800004c; + + type DMATDLR_t { + DMATDL = uint8(0); // Transmit data watermark level + _res1 = uint24(0); // Reserved, 24 bits + } + + // DMA TX data level + register DMATDLR_t DMATDLR at 0x18000050; + register uint32 DMATDLR_raw at 0x18000050; + + type DMARDLR_t { + DMARDL = uint8(0); // Receive data watermark level (DMARDLR+1) + _res1 = uint24(0); // Reserved, 24 bits + } + + // DMA RX data level + register DMARDLR_t DMARDLR at 0x18000054; + register uint32 DMARDLR_raw at 0x18000054; + + type IDR_t { + IDCODE = uint32(0); // Peripheral dentification code + } + + // Identification register + register IDR_t IDR at 0x18000058; + register uint32 IDR_raw at 0x18000058; + + type SSI_VERSION_ID_t { + SSI_COMP_VERSION = uint32(0); // SNPS component version (format X.YY) + } + + // Version ID + register SSI_VERSION_ID_t SSI_VERSION_ID at 0x1800005c; + register uint32 SSI_VERSION_ID_raw at 0x1800005c; + + type DR0_t { + DR = uint32(0); // First data register of 36 + } + + // Data Register 0 (of 36) + register DR0_t DR0 at 0x18000060; + register uint32 DR0_raw at 0x18000060; + + type RX_SAMPLE_DLY_t { + RSD = uint8(0); // RXD sample delay (in SCLK cycles) + _res1 = uint24(0); // Reserved, 24 bits + } + + // RX sample delay + register RX_SAMPLE_DLY_t RX_SAMPLE_DLY at 0x180000f0; + register uint32 RX_SAMPLE_DLY_raw at 0x180000f0; + + enum SPI_CTRLR0_INST_L { + NONE = 0, // No instruction + _4B = 1, // 4-bit instruction + _8B = 2, // 8-bit instruction + _16B = 3 // 16-bit instruction + } + + enum SPI_CTRLR0_TRANS_TYPE { + _1C1A = 0, // Command and address both in standard SPI frame format + _1C2A = 1, // Command in standard SPI format, address in format specified by FRF + _2C2A = 2 // Command and address both in format specified by FRF (e.g. Dual-SPI) + } + + type SPI_CTRLR0_t { + TRANS_TYPE = uint2(0); // Address and instruction transfer format + ADDR_L = uint4(0); // Address length (0b-60b in 4b increments) + _res1 = uint2(0); // Reserved, 2 bits + INST_L = uint2(0); // Instruction length (0/4/8/16b) + _res2 = false; // Reserved, 1 bits + WAIT_CYCLES = uint5(0); // Wait cycles between control frame transmit and data reception (in SCLK cycles) + SPI_DDR_EN = false; // SPI DDR transfer enable + INST_DDR_EN = false; // Instruction DDR transfer enable + SPI_RXDS_EN = false; // Read data strobe enable + _res3 = uint5(0); // Reserved, 5 bits + XIP_CMD = uint8(0); // SPI Command to send in XIP mode (INST_L = 8-bit) or to append to Address (INST_L = 0-bit) + } + + // SPI control + register SPI_CTRLR0_t SPI_CTRLR0 at 0x180000f4; + register uint32 SPI_CTRLR0_raw at 0x180000f4; + + type TXD_DRIVE_EDGE_t { + TDE = uint8(0); // TXD drive edge + _res1 = uint24(0); // Reserved, 24 bits + } + + // TX drive edge + register TXD_DRIVE_EDGE_t TXD_DRIVE_EDGE at 0x180000f8; + register uint32 TXD_DRIVE_EDGE_raw at 0x180000f8; + + +/* Types and registers for XIP_CTRL + QSPI flash execute-in-place block + */ + + type XIP_CTRL_CTRL_t { + EN = false; // When 1, enable the cache. When the cache is disabled, all XIP accesses will go straight to the flash, without querying the cache. When enabled, cacheable XIP accesses will query the cache, and the flash will not be accessed if the tag matches and the valid bit is set. If the cache is enabled, cache-as-SRAM accesses have no effect on the cache data RAM, and will produce a bus error response. + ERR_BADWRITE = false; // When 1, writes to any alias other than 0x0 (caching, allocating) will produce a bus fault. When 0, these writes are silently ignored. In either case, writes to the 0x0 alias will deallocate on tag match, as usual. + _res1 = false; // Reserved, 1 bits + POWER_DOWN = false; // When 1, the cache memories are powered down. They retain state, but can not be accessed. This reduces static power dissipation. Writing 1 to this bit forces CTRL_EN to 0, i.e. the cache cannot be enabled when powered down. Cache-as-SRAM accesses will produce a bus error response when the cache is powered down. + _res2 = uint28(0); // Reserved, 28 bits + } + + // Cache control + register XIP_CTRL_CTRL_t XIP_CTRL_CTRL at 0x14000000; + register uint32 XIP_CTRL_CTRL_raw at 0x14000000; + + type FLUSH_t { + FLUSH = false; // Write 1 to flush the cache. This clears the tag memory, but the data memory retains its contents. (This means cache-as-SRAM contents is not affected by flush or reset.) Reading will hold the bus (stall the processor) until the flush completes. Alternatively STAT can be polled until completion. + _res1 = uint31(0); // Reserved, 31 bits + } + + // Cache Flush control + register FLUSH_t FLUSH at 0x14000004; + register uint32 FLUSH_raw at 0x14000004; + + type STAT_t { + FLUSH_READY = false; // Reads as 0 while a cache flush is in progress, and 1 otherwise. The cache is flushed whenever the XIP block is reset, and also when requested via the FLUSH register. + FIFO_EMPTY = false; // When 1, indicates the XIP streaming FIFO is completely empty. + FIFO_FULL = false; // When 1, indicates the XIP streaming FIFO is completely full. The streaming FIFO is 2 entries deep, so the full and empty flag allow its level to be ascertained. + _res1 = uint29(0); // Reserved, 29 bits + } + + // Cache Status + register STAT_t STAT at 0x14000008; + register uint32 STAT_raw at 0x14000008; + + type CTR_HIT_t { + CTR_HIT = uint32(0); // A 32 bit saturating counter that increments upon each cache hit, i.e. when an XIP access is serviced directly from cached data. Write any value to clear. + } + + // Cache Hit counter + register CTR_HIT_t CTR_HIT at 0x1400000c; + register uint32 CTR_HIT_raw at 0x1400000c; + + type CTR_ACC_t { + CTR_ACC = uint32(0); // A 32 bit saturating counter that increments upon each XIP access, whether the cache is hit or not. This includes noncacheable accesses. Write any value to clear. + } + + // Cache Access counter + register CTR_ACC_t CTR_ACC at 0x14000010; + register uint32 CTR_ACC_raw at 0x14000010; + + type STREAM_ADDR_t { + _res1 = uint2(0); // Reserved, 2 bits + STREAM_ADDR = uint30(0); // The address of the next word to be streamed from flash to the streaming FIFO. Increments automatically after each flash access. Write the initial access address here before starting a streaming read. + } + + // FIFO stream address + register STREAM_ADDR_t STREAM_ADDR at 0x14000014; + register uint32 STREAM_ADDR_raw at 0x14000014; + + type STREAM_CTR_t { + STREAM_CTR = uint22(0); // Write a nonzero value to start a streaming read. This will then progress in the background, using flash idle cycles to transfer a linear data block from flash to the streaming FIFO. Decrements automatically (1 at a time) as the stream progresses, and halts on reaching 0. Write 0 to halt an in-progress stream, and discard any in-flight read, so that a new stream can immediately be started (after draining the FIFO and reinitialising STREAM_ADDR) + _res1 = uint10(0); // Reserved, 10 bits + } + + // FIFO stream control + register STREAM_CTR_t STREAM_CTR at 0x14000018; + register uint32 STREAM_CTR_raw at 0x14000018; + + type STREAM_FIFO_t { + STREAM_FIFO = uint32(0); // Streamed data is buffered here, for retrieval by the system DMA. This FIFO can also be accessed via the XIP_AUX slave, to avoid exposing the DMA to bus stalls caused by other XIP traffic. + } + + // FIFO stream data + register STREAM_FIFO_t STREAM_FIFO at 0x1400001c; + register uint32 STREAM_FIFO_raw at 0x1400001c; + + +/* Types and registers for SYSCFG + Register block for various chip control signals + */ + + type PROC0_NMI_MASK_t { + PROC0_NMI_MASK = uint32(0); // Set a bit high to enable NMI from that IRQ + } + + // Processor core 0 NMI source mask + register PROC0_NMI_MASK_t PROC0_NMI_MASK at 0x40004000; + register uint32 PROC0_NMI_MASK_raw at 0x40004000; + + type PROC1_NMI_MASK_t { + PROC1_NMI_MASK = uint32(0); // Set a bit high to enable NMI from that IRQ + } + + // Processor core 1 NMI source mask + register PROC1_NMI_MASK_t PROC1_NMI_MASK at 0x40004004; + register uint32 PROC1_NMI_MASK_raw at 0x40004004; + + type PROC_CONFIG_t { + PROC0_HALTED = false; // Indication that proc0 has halted + PROC1_HALTED = false; // Indication that proc1 has halted + _res1 = uint22(0); // Reserved, 22 bits + PROC0_DAP_INSTID = uint4(0); // Configure proc0 DAP instance ID. Recommend that this is NOT changed until you require debug access in multi-chip environment WARNING: do not set to 15 as this is reserved for RescueDP + PROC1_DAP_INSTID = uint4(0); // Configure proc1 DAP instance ID. Recommend that this is NOT changed until you require debug access in multi-chip environment WARNING: do not set to 15 as this is reserved for RescueDP + } + + // Configuration for processors + register PROC_CONFIG_t PROC_CONFIG at 0x40004008; + register uint32 PROC_CONFIG_raw at 0x40004008; + + type PROC_IN_SYNC_BYPASS_t { + PROC_IN_SYNC_BYPASS = uint30(0); // + _res1 = uint2(0); // Reserved, 2 bits + } + + // For each bit, if 1, bypass the input synchronizer between that GPIO and the GPIO input register in the SIO. The input synchronizers should generally be unbypassed, to avoid injecting metastabilities into processors. If you're feeling brave, you can bypass to save two cycles of input latency. This register applies to GPIO 0...29. + register PROC_IN_SYNC_BYPASS_t PROC_IN_SYNC_BYPASS at 0x4000400c; + register uint32 PROC_IN_SYNC_BYPASS_raw at 0x4000400c; + + type PROC_IN_SYNC_BYPASS_HI_t { + PROC_IN_SYNC_BYPASS_HI = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // For each bit, if 1, bypass the input synchronizer between that GPIO and the GPIO input register in the SIO. The input synchronizers should generally be unbypassed, to avoid injecting metastabilities into processors. If you're feeling brave, you can bypass to save two cycles of input latency. This register applies to GPIO 30...35 (the QSPI IOs). + register PROC_IN_SYNC_BYPASS_HI_t PROC_IN_SYNC_BYPASS_HI at 0x40004010; + register uint32 PROC_IN_SYNC_BYPASS_HI_raw at 0x40004010; + + type DBGFORCE_t { + PROC0_SWDO = false; // Observe the value of processor 0 SWDIO output. + PROC0_SWDI = false; // Directly drive processor 0 SWDIO input, if PROC0_ATTACH is set + PROC0_SWCLK = false; // Directly drive processor 0 SWCLK, if PROC0_ATTACH is set + PROC0_ATTACH = false; // Attach processor 0 debug port to syscfg controls, and disconnect it from external SWD pads. + PROC1_SWDO = false; // Observe the value of processor 1 SWDIO output. + PROC1_SWDI = false; // Directly drive processor 1 SWDIO input, if PROC1_ATTACH is set + PROC1_SWCLK = false; // Directly drive processor 1 SWCLK, if PROC1_ATTACH is set + PROC1_ATTACH = false; // Attach processor 1 debug port to syscfg controls, and disconnect it from external SWD pads. + _res1 = uint24(0); // Reserved, 24 bits + } + + // Directly control the SWD debug port of either processor + register DBGFORCE_t DBGFORCE at 0x40004014; + register uint32 DBGFORCE_raw at 0x40004014; + + type MEMPOWERDOWN_t { + SRAM0 = false; // + SRAM1 = false; // + SRAM2 = false; // + SRAM3 = false; // + SRAM4 = false; // + SRAM5 = false; // + USB = false; // + ROM = false; // + _res1 = uint24(0); // Reserved, 24 bits + } + + // Control power downs to memories. Set high to power down memories. Use with extreme caution + register MEMPOWERDOWN_t MEMPOWERDOWN at 0x40004018; + register uint32 MEMPOWERDOWN_raw at 0x40004018; + + +/* Types and registers for XOSC + Controls the crystal oscillator + */ + + enum XOSC_CTRL_ENABLE { + DISABLE = 3358, // + ENABLE = 4011 // + } + + enum XOSC_CTRL_FREQ_RANGE { + _1_15MHZ = 2720, // + RESERVED_1 = 2721, // + RESERVED_2 = 2722, // + RESERVED_3 = 2723 // + } + + type XOSC_CTRL_t { + FREQ_RANGE = uint12(0); // Frequency range. An invalid setting will retain the previous value. The actual value being used can be read from STATUS_FREQ_RANGE. This resets to 0xAA0 and cannot be changed. + ENABLE = uint12(0); // On power-up this field is initialised to DISABLE and the chip runs from the ROSC. If the chip has subsequently been programmed to run from the XOSC then DISABLE may lock-up the chip. If this is a concern then run the clk_ref from the ROSC and enable the clk_sys RESUS feature. The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + _res1 = uint8(0); // Reserved, 8 bits + } + + // Crystal Oscillator Control + register XOSC_CTRL_t XOSC_CTRL at 0x40024000; + register uint32 XOSC_CTRL_raw at 0x40024000; + + enum XOSC_STATUS_FREQ_RANGE { + _1_15MHZ = 0, // + RESERVED_1 = 1, // + RESERVED_2 = 2, // + RESERVED_3 = 3 // + } + + type XOSC_STATUS_t { + FREQ_RANGE = uint2(0); // The current frequency range setting, always reads 0 + _res1 = uint10(0); // Reserved, 10 bits + ENABLED = false; // Oscillator is enabled but not necessarily running and stable, resets to 0 + _res2 = uint11(0); // Reserved, 11 bits + BADWRITE = false; // An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or DORMANT + _res3 = uint6(0); // Reserved, 6 bits + STABLE = false; // Oscillator is running and stable + } + + // Crystal Oscillator Status + register XOSC_STATUS_t XOSC_STATUS at 0x40024004; + register uint32 XOSC_STATUS_raw at 0x40024004; + + enum XOSC_DORMANT_DORMANT { + dormant = 1668246881, // + WAKE = 2002873189 // + } + + type XOSC_DORMANT_t { + DORMANT = uint32(0); // This is used to save power by pausing the XOSC On power-up this field is initialised to WAKE An invalid write will also select WAKE Warning: stop the PLLs before selecting dormant mode Warning: setup the irq before selecting dormant mode + } + + // Crystal Oscillator pause control + register XOSC_DORMANT_t XOSC_DORMANT at 0x40024008; + register uint32 XOSC_DORMANT_raw at 0x40024008; + + type STARTUP_t { + DELAY = uint14(0); // in multiples of 256*xtal_period. The reset value of 0xc4 corresponds to approx 50 000 cycles. + _res1 = uint6(0); // Reserved, 6 bits + X4 = false; // Multiplies the startup_delay by 4. This is of little value to the user given that the delay can be programmed directly. + _res2 = uint11(0); // Reserved, 11 bits + } + + // Controls the startup delay + register STARTUP_t STARTUP at 0x4002400c; + register uint32 STARTUP_raw at 0x4002400c; + + type XOSC_COUNT_t { + COUNT = uint8(0); // + _res1 = uint24(0); // Reserved, 24 bits + } + + // A down counter running at the xosc frequency which counts to zero and stops. To start the counter write a non-zero value. Can be used for short software pauses when setting up time sensitive hardware. + register XOSC_COUNT_t XOSC_COUNT at 0x4002401c; + register uint32 XOSC_COUNT_raw at 0x4002401c; + + +/* Types and registers for PLL_SYS */ + + type PLL_SYS_CS_t { + REFDIV = uint6(0); // Divides the PLL input reference clock. Behaviour is undefined for div=0. PLL output will be unpredictable during refdiv changes, wait for lock=1 before using it. + _res1 = uint2(0); // Reserved, 2 bits + BYPASS = false; // Passes the reference clock to the output instead of the divided VCO. The VCO continues to run so the user can switch between the reference clock and the divided VCO but the output will glitch when doing so. + _res2 = uint22(0); // Reserved, 22 bits + LOCK = false; // PLL is locked + } + + // PLL_SYS Control and Status GENERAL CONSTRAINTS: Reference clock frequency min=5MHz, max=800MHz Feedback divider min=16, max=320 VCO frequency min=750MHz, max=1600MHz + register PLL_SYS_CS_t PLL_SYS_PLL_SYS_CS at 0x40028000; + register uint32 PLL_SYS_PLL_SYS_CS_raw at 0x40028000; + + type PWR_t { + PD = false; // PLL powerdown To save power set high when PLL output not required. + _res1 = false; // Reserved, 1 bits + DSMPD = false; // PLL DSM powerdown Nothing is achieved by setting this low. + POSTDIVPD = false; // PLL post divider powerdown To save power set high when PLL output not required or bypass=1. + _res2 = false; // Reserved, 1 bits + VCOPD = false; // PLL VCO powerdown To save power set high when PLL output not required or bypass=1. + _res3 = uint26(0); // Reserved, 26 bits + } + + // PLL_SYS Controls the PLL power modes. + register PWR_t PLL_SYS_PWR at 0x40028004; + register uint32 PLL_SYS_PWR_raw at 0x40028004; + + type FBDIV_INT_t { + FBDIV_INT = uint12(0); // see ctrl reg description for constraints + _res1 = uint20(0); // Reserved, 20 bits + } + + // PLL_SYS Feedback divisor (note: this PLL does not support fractional division) + register FBDIV_INT_t PLL_SYS_FBDIV_INT at 0x40028008; + register uint32 PLL_SYS_FBDIV_INT_raw at 0x40028008; + + type PRIM_t { + _res1 = uint12(0); // Reserved, 12 bits + POSTDIV2 = uint3(0); // divide by 1-7 + _res2 = false; // Reserved, 1 bits + POSTDIV1 = uint3(0); // divide by 1-7 + _res3 = uint13(0); // Reserved, 13 bits + } + + // PLL_SYS Controls the PLL post dividers for the primary output (note: this PLL does not have a secondary output) the primary output is driven from VCO divided by postdiv1*postdiv2 + register PRIM_t PLL_SYS_PRIM at 0x4002800c; + register uint32 PLL_SYS_PRIM_raw at 0x4002800c; + + +/* Types and registers for PLL_USB */ + + // PLL_USB Control and Status GENERAL CONSTRAINTS: Reference clock frequency min=5MHz, max=800MHz Feedback divider min=16, max=320 VCO frequency min=750MHz, max=1600MHz + register PLL_SYS_CS_t PLL_USB_CS at 0x4002c000; + register uint32 PLL_USB_CS_raw at 0x4002c000; + + // PLL_USB Controls the PLL power modes. + register PWR_t PLL_USB_PWR at 0x4002c004; + register uint32 PLL_USB_PWR_raw at 0x4002c004; + + // PLL_USB Feedback divisor (note: this PLL does not support fractional division) + register FBDIV_INT_t PLL_USB_FBDIV_INT at 0x4002c008; + register uint32 PLL_USB_FBDIV_INT_raw at 0x4002c008; + + // PLL_USB Controls the PLL post dividers for the primary output (note: this PLL does not have a secondary output) the primary output is driven from VCO divided by postdiv1*postdiv2 + register PRIM_t PLL_USB_PRIM at 0x4002c00c; + register uint32 PLL_USB_PRIM_raw at 0x4002c00c; + + +/* Types and registers for UART0 */ + + type UARTDR_t { + DATA = uint8(0); // Receive (read) data character. Transmit (write) data character. + FE = false; // Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is associated with the character at the top of the FIFO. + PE = false; // Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. In FIFO mode, this error is associated with the character at the top of the FIFO. + BE = false; // Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity and stop bits). In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state), and the next valid start bit is received. + OE = false; // Overrun error. This bit is set to 1 if data is received and the receive FIFO is already full. This is cleared to 0 once there is an empty space in the FIFO and a new character can be written to it. + _res1 = uint20(0); // Reserved, 20 bits + } + + // UART0 Data Register, UARTDR + register UARTDR_t UART0_UARTDR at 0x40034000; + register uint32 UART0_UARTDR_raw at 0x40034000; + + type UARTRSR_t { + FE = false; // Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + PE = false; // Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + BE = false; // Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity, and stop bits). This bit is cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state) and the next valid start bit is received. + OE = false; // Overrun error. This bit is set to 1 if data is received and the FIFO is already full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain valid because no more data is written when the FIFO is full, only the contents of the shift register are overwritten. The CPU must now read the data, to empty the FIFO. + _res1 = uint28(0); // Reserved, 28 bits + } + + // UART0 Receive Status Register/Error Clear Register, UARTRSR/UARTECR + register UARTRSR_t UART0_UARTRSR at 0x40034004; + register uint32 UART0_UARTRSR_raw at 0x40034004; + + type UARTFR_t { + CTS = false; // Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW. + DSR = false; // Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW. + DCD = false; // Data carrier detect. This bit is the complement of the UART data carrier detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. + BUSY = false; // UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit remains set until the complete byte, including all the stop bits, has been sent from the shift register. This bit is set as soon as the transmit FIFO becomes non-empty, regardless of whether the UART is enabled or not. + RXFE = false; // Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set when the receive FIFO is empty. + TXFF = false; // Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set when the transmit FIFO is full. + RXFF = false; // Receive FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is full. If the FIFO is enabled, the RXFF bit is set when the receive FIFO is full. + TXFE = false; // Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is set when the transmit holding register is empty. If the FIFO is enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if there is data in the transmit shift register. + RI = false; // Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW. + _res1 = uint23(0); // Reserved, 23 bits + } + + // UART0 Flag Register, UARTFR + register UARTFR_t UART0_UARTFR at 0x40034018; + register uint32 UART0_UARTFR_raw at 0x40034018; + + type UARTILPR_t { + ILPDVSR = uint8(0); // 8-bit low-power divisor value. These bits are cleared to 0 at reset. + _res1 = uint24(0); // Reserved, 24 bits + } + + // UART0 IrDA Low-Power Counter Register, UARTILPR + register UARTILPR_t UART0_UARTILPR at 0x40034020; + register uint32 UART0_UARTILPR_raw at 0x40034020; + + type UARTIBRD_t { + BAUD_DIVINT = uint16(0); // The integer baud rate divisor. These bits are cleared to 0 on reset. + _res1 = uint16(0); // Reserved, 16 bits + } + + // UART0 Integer Baud Rate Register, UARTIBRD + register UARTIBRD_t UART0_UARTIBRD at 0x40034024; + register uint32 UART0_UARTIBRD_raw at 0x40034024; + + type UARTFBRD_t { + BAUD_DIVFRAC = uint6(0); // The fractional baud rate divisor. These bits are cleared to 0 on reset. + _res1 = uint26(0); // Reserved, 26 bits + } + + // UART0 Fractional Baud Rate Register, UARTFBRD + register UARTFBRD_t UART0_UARTFBRD at 0x40034028; + register uint32 UART0_UARTFBRD_raw at 0x40034028; + + type UARTLCR_H_t { + BRK = false; // Send break. If this bit is set to 1, a low-level is continually output on the UARTTXD output, after completing transmission of the current character. For the proper execution of the break command, the software must set this bit for at least two complete frames. For normal use, this bit must be cleared to 0. + PEN = false; // Parity enable: 0 = parity is disabled and no parity bit added to the data frame 1 = parity checking and generation is enabled. + EPS = false; // Even parity select. Controls the type of parity the UART uses during transmission and reception: 0 = odd parity. The UART generates or checks for an odd number of 1s in the data and parity bits. 1 = even parity. The UART generates or checks for an even number of 1s in the data and parity bits. This bit has no effect when the PEN bit disables parity checking and generation. + STP2 = false; // Two stop bits select. If this bit is set to 1, two stop bits are transmitted at the end of the frame. The receive logic does not check for two stop bits being received. + FEN = false; // Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled (FIFO mode). + WLEN = uint2(0); // Word length. These bits indicate the number of data bits transmitted or received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. + SPS = false; // Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then the parity bit is transmitted and checked as a 0. This bit has no effect when the PEN bit disables parity checking and generation. + _res1 = uint24(0); // Reserved, 24 bits + } + + // UART0 Line Control Register, UARTLCR_H + register UARTLCR_H_t UART0_UARTLCR_H at 0x4003402c; + register uint32 UART0_UARTLCR_H_raw at 0x4003402c; + + type UARTCR_t { + UARTEN = false; // UART enable: 0 = UART is disabled. If the UART is disabled in the middle of transmission or reception, it completes the current character before stopping. 1 = the UART is enabled. Data transmission and reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. + SIREN = false; // SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD remains HIGH, in the marking state. Signal transitions on UARTRXD or modem status inputs have no effect. This bit has no effect if the UARTEN bit disables the UART. + SIRLP = false; // SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is cleared to 0, low-level bits are transmitted as an active high pulse with a width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are transmitted with a pulse width that is 3 times the period of the IrLPBaud16 input signal, regardless of the selected bit rate. Setting this bit uses less power, but might reduce transmission distances. + _res1 = uint4(0); // Reserved, 4 bits + LBE = false; // Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test register must be set to 1 to override the normal half-duplex SIR operation. This must be the requirement for accessing the test registers during normal operation, and SIRTEST must be cleared to 0 when loopback testing is finished. This feature reduces the amount of external coupling required during system test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path is fed through to the UARTRXD path. In either SIR mode or UART mode, when this bit is set, the modem outputs are also fed through to the modem inputs. This bit is cleared to 0 on reset, to disable loopback. + TXE = false; // Transmit enable. If this bit is set to 1, the transmit section of the UART is enabled. Data transmission occurs for either UART signals, or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of transmission, it completes the current character before stopping. + RXE = false; // Receive enable. If this bit is set to 1, the receive section of the UART is enabled. Data reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of reception, it completes the current character before stopping. + DTR = false; // Data transmit ready. This bit is the complement of the UART data transmit ready, nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then nUARTDTR is LOW. + RTS = false; // Request to send. This bit is the complement of the UART request to send, nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then nUARTRTS is LOW. + OUT1 = false; // This bit is the complement of the UART Out1 (nUARTOut1) modem status output. That is, when the bit is programmed to a 1 the output is 0. For DTE this can be used as Data Carrier Detect (DCD). + OUT2 = false; // This bit is the complement of the UART Out2 (nUARTOut2) modem status output. That is, when the bit is programmed to a 1, the output is 0. For DTE this can be used as Ring Indicator (RI). + RTSEN = false; // RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow control is enabled. Data is only requested when there is space in the receive FIFO for it to be received. + CTSEN = false; // CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow control is enabled. Data is only transmitted when the nUARTCTS signal is asserted. + _res2 = uint16(0); // Reserved, 16 bits + } + + // UART0 Control Register, UARTCR + register UARTCR_t UART0_UARTCR at 0x40034030; + register uint32 UART0_UARTCR_raw at 0x40034030; + + type UARTIFLS_t { + TXIFLSEL = uint3(0); // Transmit interrupt FIFO level select. The trigger points for the transmit interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 full b101-b111 = reserved. + RXIFLSEL = uint3(0); // Receive interrupt FIFO level select. The trigger points for the receive interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 full b101-b111 = reserved. + _res1 = uint26(0); // Reserved, 26 bits + } + + // UART0 Interrupt FIFO Level Select Register, UARTIFLS + register UARTIFLS_t UART0_UARTIFLS at 0x40034034; + register uint32 UART0_UARTIFLS_raw at 0x40034034; + + type UARTIMSC_t { + RIMIM = false; // nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write of 0 clears the mask. + CTSMIM = false; // nUARTCTS modem interrupt mask. A read returns the current mask for the UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is set. A write of 0 clears the mask. + DCDMIM = false; // nUARTDCD modem interrupt mask. A read returns the current mask for the UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is set. A write of 0 clears the mask. + DSRMIM = false; // nUARTDSR modem interrupt mask. A read returns the current mask for the UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is set. A write of 0 clears the mask. + RXIM = false; // Receive interrupt mask. A read returns the current mask for the UARTRXINTR interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write of 0 clears the mask. + TXIM = false; // Transmit interrupt mask. A read returns the current mask for the UARTTXINTR interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write of 0 clears the mask. + RTIM = false; // Receive timeout interrupt mask. A read returns the current mask for the UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is set. A write of 0 clears the mask. + FEIM = false; // Framing error interrupt mask. A read returns the current mask for the UARTFEINTR interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write of 0 clears the mask. + PEIM = false; // Parity error interrupt mask. A read returns the current mask for the UARTPEINTR interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write of 0 clears the mask. + BEIM = false; // Break error interrupt mask. A read returns the current mask for the UARTBEINTR interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write of 0 clears the mask. + OEIM = false; // Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write of 0 clears the mask. + _res1 = uint21(0); // Reserved, 21 bits + } + + // UART0 Interrupt Mask Set/Clear Register, UARTIMSC + register UARTIMSC_t UART0_UARTIMSC at 0x40034038; + register uint32 UART0_UARTIMSC_raw at 0x40034038; + + type UARTRIS_t { + RIRMIS = false; // nUARTRI modem interrupt status. Returns the raw interrupt state of the UARTRIINTR interrupt. + CTSRMIS = false; // nUARTCTS modem interrupt status. Returns the raw interrupt state of the UARTCTSINTR interrupt. + DCDRMIS = false; // nUARTDCD modem interrupt status. Returns the raw interrupt state of the UARTDCDINTR interrupt. + DSRRMIS = false; // nUARTDSR modem interrupt status. Returns the raw interrupt state of the UARTDSRINTR interrupt. + RXRIS = false; // Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR interrupt. + TXRIS = false; // Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR interrupt. + RTRIS = false; // Receive timeout interrupt status. Returns the raw interrupt state of the UARTRTINTR interrupt. a + FERIS = false; // Framing error interrupt status. Returns the raw interrupt state of the UARTFEINTR interrupt. + PERIS = false; // Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR interrupt. + BERIS = false; // Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR interrupt. + OERIS = false; // Overrun error interrupt status. Returns the raw interrupt state of the UARTOEINTR interrupt. + _res1 = uint21(0); // Reserved, 21 bits + } + + // UART0 Raw Interrupt Status Register, UARTRIS + register UARTRIS_t UART0_UARTRIS at 0x4003403c; + register uint32 UART0_UARTRIS_raw at 0x4003403c; + + type UARTMIS_t { + RIMMIS = false; // nUARTRI modem masked interrupt status. Returns the masked interrupt state of the UARTRIINTR interrupt. + CTSMMIS = false; // nUARTCTS modem masked interrupt status. Returns the masked interrupt state of the UARTCTSINTR interrupt. + DCDMMIS = false; // nUARTDCD modem masked interrupt status. Returns the masked interrupt state of the UARTDCDINTR interrupt. + DSRMMIS = false; // nUARTDSR modem masked interrupt status. Returns the masked interrupt state of the UARTDSRINTR interrupt. + RXMIS = false; // Receive masked interrupt status. Returns the masked interrupt state of the UARTRXINTR interrupt. + TXMIS = false; // Transmit masked interrupt status. Returns the masked interrupt state of the UARTTXINTR interrupt. + RTMIS = false; // Receive timeout masked interrupt status. Returns the masked interrupt state of the UARTRTINTR interrupt. + FEMIS = false; // Framing error masked interrupt status. Returns the masked interrupt state of the UARTFEINTR interrupt. + PEMIS = false; // Parity error masked interrupt status. Returns the masked interrupt state of the UARTPEINTR interrupt. + BEMIS = false; // Break error masked interrupt status. Returns the masked interrupt state of the UARTBEINTR interrupt. + OEMIS = false; // Overrun error masked interrupt status. Returns the masked interrupt state of the UARTOEINTR interrupt. + _res1 = uint21(0); // Reserved, 21 bits + } + + // UART0 Masked Interrupt Status Register, UARTMIS + register UARTMIS_t UART0_UARTMIS at 0x40034040; + register uint32 UART0_UARTMIS_raw at 0x40034040; + + type UARTICR_t { + RIMIC = false; // nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. + CTSMIC = false; // nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt. + DCDMIC = false; // nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt. + DSRMIC = false; // nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt. + RXIC = false; // Receive interrupt clear. Clears the UARTRXINTR interrupt. + TXIC = false; // Transmit interrupt clear. Clears the UARTTXINTR interrupt. + RTIC = false; // Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. + FEIC = false; // Framing error interrupt clear. Clears the UARTFEINTR interrupt. + PEIC = false; // Parity error interrupt clear. Clears the UARTPEINTR interrupt. + BEIC = false; // Break error interrupt clear. Clears the UARTBEINTR interrupt. + OEIC = false; // Overrun error interrupt clear. Clears the UARTOEINTR interrupt. + _res1 = uint21(0); // Reserved, 21 bits + } + + // UART0 Interrupt Clear Register, UARTICR + register UARTICR_t UART0_UARTICR at 0x40034044; + register uint32 UART0_UARTICR_raw at 0x40034044; + + type UARTDMACR_t { + RXDMAE = false; // Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is enabled. + TXDMAE = false; // Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + DMAONERR = false; // DMA on error. If this bit is set to 1, the DMA receive request outputs, UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is asserted. + _res1 = uint29(0); // Reserved, 29 bits + } + + // UART0 DMA Control Register, UARTDMACR + register UARTDMACR_t UART0_UARTDMACR at 0x40034048; + register uint32 UART0_UARTDMACR_raw at 0x40034048; + + type UARTPERIPHID0_t { + PARTNUMBER0 = uint8(0); // These bits read back as 0x11 + _res1 = uint24(0); // Reserved, 24 bits + } + + // UART0 UARTPeriphID0 Register + register UARTPERIPHID0_t UART0_UARTPERIPHID0 at 0x40034fe0; + register uint32 UART0_UARTPERIPHID0_raw at 0x40034fe0; + + type UARTPERIPHID1_t { + PARTNUMBER1 = uint4(0); // These bits read back as 0x0 + DESIGNER0 = uint4(0); // These bits read back as 0x1 + _res1 = uint24(0); // Reserved, 24 bits + } + + // UART0 UARTPeriphID1 Register + register UARTPERIPHID1_t UART0_UARTPERIPHID1 at 0x40034fe4; + register uint32 UART0_UARTPERIPHID1_raw at 0x40034fe4; + + type UARTPERIPHID2_t { + DESIGNER1 = uint4(0); // These bits read back as 0x4 + REVISION = uint4(0); // This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 0x2 r1p5 0x3 + _res1 = uint24(0); // Reserved, 24 bits + } + + // UART0 UARTPeriphID2 Register + register UARTPERIPHID2_t UART0_UARTPERIPHID2 at 0x40034fe8; + register uint32 UART0_UARTPERIPHID2_raw at 0x40034fe8; + + type UARTPERIPHID3_t { + CONFIGURATION = uint8(0); // These bits read back as 0x00 + _res1 = uint24(0); // Reserved, 24 bits + } + + // UART0 UARTPeriphID3 Register + register UARTPERIPHID3_t UART0_UARTPERIPHID3 at 0x40034fec; + register uint32 UART0_UARTPERIPHID3_raw at 0x40034fec; + + type UARTPCELLID0_t { + UARTPCELLID0 = uint8(0); // These bits read back as 0x0D + _res1 = uint24(0); // Reserved, 24 bits + } + + // UART0 UARTPCellID0 Register + register UARTPCELLID0_t UART0_UARTPCELLID0 at 0x40034ff0; + register uint32 UART0_UARTPCELLID0_raw at 0x40034ff0; + + type UARTPCELLID1_t { + UARTPCELLID1 = uint8(0); // These bits read back as 0xF0 + _res1 = uint24(0); // Reserved, 24 bits + } + + // UART0 UARTPCellID1 Register + register UARTPCELLID1_t UART0_UARTPCELLID1 at 0x40034ff4; + register uint32 UART0_UARTPCELLID1_raw at 0x40034ff4; + + type UARTPCELLID2_t { + UARTPCELLID2 = uint8(0); // These bits read back as 0x05 + _res1 = uint24(0); // Reserved, 24 bits + } + + // UART0 UARTPCellID2 Register + register UARTPCELLID2_t UART0_UARTPCELLID2 at 0x40034ff8; + register uint32 UART0_UARTPCELLID2_raw at 0x40034ff8; + + type UARTPCELLID3_t { + UARTPCELLID3 = uint8(0); // These bits read back as 0xB1 + _res1 = uint24(0); // Reserved, 24 bits + } + + // UART0 UARTPCellID3 Register + register UARTPCELLID3_t UART0_UARTPCELLID3 at 0x40034ffc; + register uint32 UART0_UARTPCELLID3_raw at 0x40034ffc; + + +/* Types and registers for UART1 */ + + // UART1 Data Register, UARTDR + register UARTDR_t UART1_UARTDR at 0x40038000; + register uint32 UART1_UARTDR_raw at 0x40038000; + + // UART1 Receive Status Register/Error Clear Register, UARTRSR/UARTECR + register UARTRSR_t UART1_UARTRSR at 0x40038004; + register uint32 UART1_UARTRSR_raw at 0x40038004; + + // UART1 Flag Register, UARTFR + register UARTFR_t UART1_UARTFR at 0x40038018; + register uint32 UART1_UARTFR_raw at 0x40038018; + + // UART1 IrDA Low-Power Counter Register, UARTILPR + register UARTILPR_t UART1_UARTILPR at 0x40038020; + register uint32 UART1_UARTILPR_raw at 0x40038020; + + // UART1 Integer Baud Rate Register, UARTIBRD + register UARTIBRD_t UART1_UARTIBRD at 0x40038024; + register uint32 UART1_UARTIBRD_raw at 0x40038024; + + // UART1 Fractional Baud Rate Register, UARTFBRD + register UARTFBRD_t UART1_UARTFBRD at 0x40038028; + register uint32 UART1_UARTFBRD_raw at 0x40038028; + + // UART1 Line Control Register, UARTLCR_H + register UARTLCR_H_t UART1_UARTLCR_H at 0x4003802c; + register uint32 UART1_UARTLCR_H_raw at 0x4003802c; + + // UART1 Control Register, UARTCR + register UARTCR_t UART1_UARTCR at 0x40038030; + register uint32 UART1_UARTCR_raw at 0x40038030; + + // UART1 Interrupt FIFO Level Select Register, UARTIFLS + register UARTIFLS_t UART1_UARTIFLS at 0x40038034; + register uint32 UART1_UARTIFLS_raw at 0x40038034; + + // UART1 Interrupt Mask Set/Clear Register, UARTIMSC + register UARTIMSC_t UART1_UARTIMSC at 0x40038038; + register uint32 UART1_UARTIMSC_raw at 0x40038038; + + // UART1 Raw Interrupt Status Register, UARTRIS + register UARTRIS_t UART1_UARTRIS at 0x4003803c; + register uint32 UART1_UARTRIS_raw at 0x4003803c; + + // UART1 Masked Interrupt Status Register, UARTMIS + register UARTMIS_t UART1_UARTMIS at 0x40038040; + register uint32 UART1_UARTMIS_raw at 0x40038040; + + // UART1 Interrupt Clear Register, UARTICR + register UARTICR_t UART1_UARTICR at 0x40038044; + register uint32 UART1_UARTICR_raw at 0x40038044; + + // UART1 DMA Control Register, UARTDMACR + register UARTDMACR_t UART1_UARTDMACR at 0x40038048; + register uint32 UART1_UARTDMACR_raw at 0x40038048; + + // UART1 UARTPeriphID0 Register + register UARTPERIPHID0_t UART1_UARTPERIPHID0 at 0x40038fe0; + register uint32 UART1_UARTPERIPHID0_raw at 0x40038fe0; + + // UART1 UARTPeriphID1 Register + register UARTPERIPHID1_t UART1_UARTPERIPHID1 at 0x40038fe4; + register uint32 UART1_UARTPERIPHID1_raw at 0x40038fe4; + + // UART1 UARTPeriphID2 Register + register UARTPERIPHID2_t UART1_UARTPERIPHID2 at 0x40038fe8; + register uint32 UART1_UARTPERIPHID2_raw at 0x40038fe8; + + // UART1 UARTPeriphID3 Register + register UARTPERIPHID3_t UART1_UARTPERIPHID3 at 0x40038fec; + register uint32 UART1_UARTPERIPHID3_raw at 0x40038fec; + + // UART1 UARTPCellID0 Register + register UARTPCELLID0_t UART1_UARTPCELLID0 at 0x40038ff0; + register uint32 UART1_UARTPCELLID0_raw at 0x40038ff0; + + // UART1 UARTPCellID1 Register + register UARTPCELLID1_t UART1_UARTPCELLID1 at 0x40038ff4; + register uint32 UART1_UARTPCELLID1_raw at 0x40038ff4; + + // UART1 UARTPCellID2 Register + register UARTPCELLID2_t UART1_UARTPCELLID2 at 0x40038ff8; + register uint32 UART1_UARTPCELLID2_raw at 0x40038ff8; + + // UART1 UARTPCellID3 Register + register UARTPCELLID3_t UART1_UARTPCELLID3 at 0x40038ffc; + register uint32 UART1_UARTPCELLID3_raw at 0x40038ffc; + + +/* Types and registers for ROSC */ + + enum ROSC_CTRL_ENABLE { + DISABLE = 3358, // + ENABLE = 4011 // + } + + enum ROSC_CTRL_FREQ_RANGE { + LOW = 4004, // + MEDIUM = 4005, // + HIGH = 4007, // + TOOHIGH = 4006 // + } + + type ROSC_CTRL_t { + FREQ_RANGE = uint12(0); // Controls the number of delay stages in the ROSC ring LOW uses stages 0 to 7 MEDIUM uses stages 2 to 7 HIGH uses stages 4 to 7 TOOHIGH uses stages 6 to 7 and should not be used because its frequency exceeds design specifications The clock output will not glitch when changing the range up one step at a time The clock output will glitch when changing the range down Note: the values here are gray coded which is why HIGH comes before TOOHIGH + ENABLE = uint12(0); // On power-up this field is initialised to ENABLE The system clock must be switched to another source before setting this field to DISABLE otherwise the chip will lock up The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + _res1 = uint8(0); // Reserved, 8 bits + } + + // Ring Oscillator control + register ROSC_CTRL_t ROSC_CTRL at 0x40060000; + register uint32 ROSC_CTRL_raw at 0x40060000; + + enum FREQA_PASSWD { + PASS = 38550 // + } + + type FREQA_t { + DS0 = uint3(0); // Stage 0 drive strength + _res1 = false; // Reserved, 1 bits + DS1 = uint3(0); // Stage 1 drive strength + _res2 = false; // Reserved, 1 bits + DS2 = uint3(0); // Stage 2 drive strength + _res3 = false; // Reserved, 1 bits + DS3 = uint3(0); // Stage 3 drive strength + _res4 = false; // Reserved, 1 bits + PASSWD = uint16(0); // Set to 0x9696 to apply the settings Any other value in this field will set all drive strengths to 0 + } + + // The FREQA & FREQB registers control the frequency by controlling the drive strength of each stage The drive strength has 4 levels determined by the number of bits set Increasing the number of bits set increases the drive strength and increases the oscillation frequency 0 bits set is the default drive strength 1 bit set doubles the drive strength 2 bits set triples drive strength 3 bits set quadruples drive strength + register FREQA_t FREQA at 0x40060004; + register uint32 FREQA_raw at 0x40060004; + + enum FREQB_PASSWD { + PASS = 38550 // + } + + type FREQB_t { + DS4 = uint3(0); // Stage 4 drive strength + _res1 = false; // Reserved, 1 bits + DS5 = uint3(0); // Stage 5 drive strength + _res2 = false; // Reserved, 1 bits + DS6 = uint3(0); // Stage 6 drive strength + _res3 = false; // Reserved, 1 bits + DS7 = uint3(0); // Stage 7 drive strength + _res4 = false; // Reserved, 1 bits + PASSWD = uint16(0); // Set to 0x9696 to apply the settings Any other value in this field will set all drive strengths to 0 + } + + // For a detailed description see freqa register + register FREQB_t FREQB at 0x40060008; + register uint32 FREQB_raw at 0x40060008; + + enum ROSC_DORMANT_DORMANT { + dormant = 1668246881, // + WAKE = 2002873189 // + } + + type ROSC_DORMANT_t { + DORMANT = uint32(0); // This is used to save power by pausing the ROSC On power-up this field is initialised to WAKE An invalid write will also select WAKE Warning: setup the irq before selecting dormant mode + } + + // Ring Oscillator pause control + register ROSC_DORMANT_t ROSC_DORMANT at 0x4006000c; + register uint32 ROSC_DORMANT_raw at 0x4006000c; + + enum ROSC_DIV_DIV { + PASS = 2720 // + } + + type ROSC_DIV_t { + DIV = uint12(0); // set to 0xaa0 + div where div = 0 divides by 32 div = 1-31 divides by div any other value sets div=31 this register resets to div=16 + _res1 = uint20(0); // Reserved, 20 bits + } + + // Controls the output divider + register ROSC_DIV_t ROSC_DIV at 0x40060010; + register uint32 ROSC_DIV_raw at 0x40060010; + + type PHASE_t { + SHIFT = uint2(0); // phase shift the phase-shifted output by SHIFT input clocks this can be changed on-the-fly must be set to 0 before setting div=1 + FLIP = false; // invert the phase-shifted output this is ignored when div=1 + ENABLE = false; // enable the phase-shifted output this can be changed on-the-fly + PASSWD = uint8(0); // set to 0xaa any other value enables the output with shift=0 + _res1 = uint20(0); // Reserved, 20 bits + } + + // Controls the phase shifted output + register PHASE_t PHASE at 0x40060014; + register uint32 PHASE_raw at 0x40060014; + + type ROSC_STATUS_t { + _res1 = uint12(0); // Reserved, 12 bits + ENABLED = false; // Oscillator is enabled but not necessarily running and stable this resets to 0 but transitions to 1 during chip startup + _res2 = uint3(0); // Reserved, 3 bits + DIV_RUNNING = false; // post-divider is running this resets to 0 but transitions to 1 during chip startup + _res3 = uint7(0); // Reserved, 7 bits + BADWRITE = false; // An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or FREQA or FREQB or DIV or PHASE or DORMANT + _res4 = uint6(0); // Reserved, 6 bits + STABLE = false; // Oscillator is running and stable + } + + // Ring Oscillator Status + register ROSC_STATUS_t ROSC_STATUS at 0x40060018; + register uint32 ROSC_STATUS_raw at 0x40060018; + + type RANDOMBIT_t { + RANDOMBIT = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // This just reads the state of the oscillator output so randomness is compromised if the ring oscillator is stopped or run at a harmonic of the bus frequency + register RANDOMBIT_t RANDOMBIT at 0x4006001c; + register uint32 RANDOMBIT_raw at 0x4006001c; + + type ROSC_COUNT_t { + COUNT = uint8(0); // + _res1 = uint24(0); // Reserved, 24 bits + } + + // A down counter running at the ROSC frequency which counts to zero and stops. To start the counter write a non-zero value. Can be used for short software pauses when setting up time sensitive hardware. + register ROSC_COUNT_t ROSC_COUNT at 0x40060020; + register uint32 ROSC_COUNT_raw at 0x40060020; + + +/* Types and registers for WATCHDOG */ + + type WATCHDOG_CTRL_t { + TIME = uint24(0); // Indicates the number of ticks / 2 (see errata RP2040-E1) before a watchdog reset will be triggered + PAUSE_JTAG = false; // Pause the watchdog timer when JTAG is accessing the bus fabric + PAUSE_DBG0 = false; // Pause the watchdog timer when processor 0 is in debug mode + PAUSE_DBG1 = false; // Pause the watchdog timer when processor 1 is in debug mode + _res1 = uint3(0); // Reserved, 3 bits + ENABLE = false; // When not enabled the watchdog timer is paused + TRIGGER = false; // Trigger a watchdog reset + } + + // Watchdog control The rst_wdsel register determines which subsystems are reset when the watchdog is triggered. The watchdog can be triggered in software. + register WATCHDOG_CTRL_t WATCHDOG_CTRL at 0x40058000; + register uint32 WATCHDOG_CTRL_raw at 0x40058000; + + type LOAD_t { + LOAD = uint24(0); // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Load the watchdog timer. The maximum setting is 0xffffff which corresponds to 0xffffff / 2 ticks before triggering a watchdog reset (see errata RP2040-E1). + register LOAD_t LOAD at 0x40058004; + register uint32 LOAD_raw at 0x40058004; + + type REASON_t { + TIMER = false; // + FORCE = false; // + _res1 = uint30(0); // Reserved, 30 bits + } + + // Logs the reason for the last reset. Both bits are zero for the case of a hardware reset. + register REASON_t REASON at 0x40058008; + register uint32 REASON_raw at 0x40058008; + + type SCRATCH0_t { + SCRATCH0 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH0_t SCRATCH0 at 0x4005800c; + register uint32 SCRATCH0_raw at 0x4005800c; + + type SCRATCH1_t { + SCRATCH1 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH1_t SCRATCH1 at 0x40058010; + register uint32 SCRATCH1_raw at 0x40058010; + + type SCRATCH2_t { + SCRATCH2 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH2_t SCRATCH2 at 0x40058014; + register uint32 SCRATCH2_raw at 0x40058014; + + type SCRATCH3_t { + SCRATCH3 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH3_t SCRATCH3 at 0x40058018; + register uint32 SCRATCH3_raw at 0x40058018; + + type SCRATCH4_t { + SCRATCH4 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH4_t SCRATCH4 at 0x4005801c; + register uint32 SCRATCH4_raw at 0x4005801c; + + type SCRATCH5_t { + SCRATCH5 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH5_t SCRATCH5 at 0x40058020; + register uint32 SCRATCH5_raw at 0x40058020; + + type SCRATCH6_t { + SCRATCH6 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH6_t SCRATCH6 at 0x40058024; + register uint32 SCRATCH6_raw at 0x40058024; + + type SCRATCH7_t { + SCRATCH7 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH7_t SCRATCH7 at 0x40058028; + register uint32 SCRATCH7_raw at 0x40058028; + + type TICK_t { + CYCLES = uint9(0); // Total number of clk_tick cycles before the next tick. + ENABLE = false; // start / stop tick generation + RUNNING = false; // Is the tick generator running? + COUNT = uint9(0); // Count down timer: the remaining number clk_tick cycles before the next tick is generated. + _res1 = uint12(0); // Reserved, 12 bits + } + + // Controls the tick generator + register TICK_t TICK at 0x4005802c; + register uint32 TICK_raw at 0x4005802c; + + +/* Types and registers for DMA + DMA with separate read and write masters + */ + + type CH0_READ_ADDR_t { + CH0_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 0 Read Address pointer + register CH0_READ_ADDR_t CH0_READ_ADDR at 0x50000000; + register uint32 CH0_READ_ADDR_raw at 0x50000000; + + type CH0_WRITE_ADDR_t { + CH0_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 0 Write Address pointer + register CH0_WRITE_ADDR_t CH0_WRITE_ADDR at 0x50000004; + register uint32 CH0_WRITE_ADDR_raw at 0x50000004; + + type CH0_TRANS_COUNT_t { + CH0_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 0 Transfer Count + register CH0_TRANS_COUNT_t CH0_TRANS_COUNT at 0x50000008; + register uint32 CH0_TRANS_COUNT_raw at 0x50000008; + + enum CH0_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH0_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH0_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH0_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 0 Control and Status + register CH0_CTRL_TRIG_t CH0_CTRL_TRIG at 0x5000000c; + register uint32 CH0_CTRL_TRIG_raw at 0x5000000c; + + type CH0_AL1_CTRL_t { + CH0_AL1_CTRL = uint32(0); // + } + + // Alias for channel 0 CTRL register + register CH0_AL1_CTRL_t CH0_AL1_CTRL at 0x50000010; + register uint32 CH0_AL1_CTRL_raw at 0x50000010; + + type CH0_AL1_READ_ADDR_t { + CH0_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 0 READ_ADDR register + register CH0_AL1_READ_ADDR_t CH0_AL1_READ_ADDR at 0x50000014; + register uint32 CH0_AL1_READ_ADDR_raw at 0x50000014; + + type CH0_AL1_WRITE_ADDR_t { + CH0_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 0 WRITE_ADDR register + register CH0_AL1_WRITE_ADDR_t CH0_AL1_WRITE_ADDR at 0x50000018; + register uint32 CH0_AL1_WRITE_ADDR_raw at 0x50000018; + + type CH0_AL1_TRANS_COUNT_TRIG_t { + CH0_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 0 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH0_AL1_TRANS_COUNT_TRIG_t CH0_AL1_TRANS_COUNT_TRIG at 0x5000001c; + register uint32 CH0_AL1_TRANS_COUNT_TRIG_raw at 0x5000001c; + + type CH0_AL2_CTRL_t { + CH0_AL2_CTRL = uint32(0); // + } + + // Alias for channel 0 CTRL register + register CH0_AL2_CTRL_t CH0_AL2_CTRL at 0x50000020; + register uint32 CH0_AL2_CTRL_raw at 0x50000020; + + type CH0_AL2_TRANS_COUNT_t { + CH0_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 0 TRANS_COUNT register + register CH0_AL2_TRANS_COUNT_t CH0_AL2_TRANS_COUNT at 0x50000024; + register uint32 CH0_AL2_TRANS_COUNT_raw at 0x50000024; + + type CH0_AL2_READ_ADDR_t { + CH0_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 0 READ_ADDR register + register CH0_AL2_READ_ADDR_t CH0_AL2_READ_ADDR at 0x50000028; + register uint32 CH0_AL2_READ_ADDR_raw at 0x50000028; + + type CH0_AL2_WRITE_ADDR_TRIG_t { + CH0_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 0 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH0_AL2_WRITE_ADDR_TRIG_t CH0_AL2_WRITE_ADDR_TRIG at 0x5000002c; + register uint32 CH0_AL2_WRITE_ADDR_TRIG_raw at 0x5000002c; + + type CH0_AL3_CTRL_t { + CH0_AL3_CTRL = uint32(0); // + } + + // Alias for channel 0 CTRL register + register CH0_AL3_CTRL_t CH0_AL3_CTRL at 0x50000030; + register uint32 CH0_AL3_CTRL_raw at 0x50000030; + + type CH0_AL3_WRITE_ADDR_t { + CH0_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 0 WRITE_ADDR register + register CH0_AL3_WRITE_ADDR_t CH0_AL3_WRITE_ADDR at 0x50000034; + register uint32 CH0_AL3_WRITE_ADDR_raw at 0x50000034; + + type CH0_AL3_TRANS_COUNT_t { + CH0_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 0 TRANS_COUNT register + register CH0_AL3_TRANS_COUNT_t CH0_AL3_TRANS_COUNT at 0x50000038; + register uint32 CH0_AL3_TRANS_COUNT_raw at 0x50000038; + + type CH0_AL3_READ_ADDR_TRIG_t { + CH0_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 0 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH0_AL3_READ_ADDR_TRIG_t CH0_AL3_READ_ADDR_TRIG at 0x5000003c; + register uint32 CH0_AL3_READ_ADDR_TRIG_raw at 0x5000003c; + + type CH1_READ_ADDR_t { + CH1_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 1 Read Address pointer + register CH1_READ_ADDR_t CH1_READ_ADDR at 0x50000040; + register uint32 CH1_READ_ADDR_raw at 0x50000040; + + type CH1_WRITE_ADDR_t { + CH1_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 1 Write Address pointer + register CH1_WRITE_ADDR_t CH1_WRITE_ADDR at 0x50000044; + register uint32 CH1_WRITE_ADDR_raw at 0x50000044; + + type CH1_TRANS_COUNT_t { + CH1_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 1 Transfer Count + register CH1_TRANS_COUNT_t CH1_TRANS_COUNT at 0x50000048; + register uint32 CH1_TRANS_COUNT_raw at 0x50000048; + + enum CH1_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH1_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH1_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH1_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 1 Control and Status + register CH1_CTRL_TRIG_t CH1_CTRL_TRIG at 0x5000004c; + register uint32 CH1_CTRL_TRIG_raw at 0x5000004c; + + type CH1_AL1_CTRL_t { + CH1_AL1_CTRL = uint32(0); // + } + + // Alias for channel 1 CTRL register + register CH1_AL1_CTRL_t CH1_AL1_CTRL at 0x50000050; + register uint32 CH1_AL1_CTRL_raw at 0x50000050; + + type CH1_AL1_READ_ADDR_t { + CH1_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 1 READ_ADDR register + register CH1_AL1_READ_ADDR_t CH1_AL1_READ_ADDR at 0x50000054; + register uint32 CH1_AL1_READ_ADDR_raw at 0x50000054; + + type CH1_AL1_WRITE_ADDR_t { + CH1_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 1 WRITE_ADDR register + register CH1_AL1_WRITE_ADDR_t CH1_AL1_WRITE_ADDR at 0x50000058; + register uint32 CH1_AL1_WRITE_ADDR_raw at 0x50000058; + + type CH1_AL1_TRANS_COUNT_TRIG_t { + CH1_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 1 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH1_AL1_TRANS_COUNT_TRIG_t CH1_AL1_TRANS_COUNT_TRIG at 0x5000005c; + register uint32 CH1_AL1_TRANS_COUNT_TRIG_raw at 0x5000005c; + + type CH1_AL2_CTRL_t { + CH1_AL2_CTRL = uint32(0); // + } + + // Alias for channel 1 CTRL register + register CH1_AL2_CTRL_t CH1_AL2_CTRL at 0x50000060; + register uint32 CH1_AL2_CTRL_raw at 0x50000060; + + type CH1_AL2_TRANS_COUNT_t { + CH1_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 1 TRANS_COUNT register + register CH1_AL2_TRANS_COUNT_t CH1_AL2_TRANS_COUNT at 0x50000064; + register uint32 CH1_AL2_TRANS_COUNT_raw at 0x50000064; + + type CH1_AL2_READ_ADDR_t { + CH1_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 1 READ_ADDR register + register CH1_AL2_READ_ADDR_t CH1_AL2_READ_ADDR at 0x50000068; + register uint32 CH1_AL2_READ_ADDR_raw at 0x50000068; + + type CH1_AL2_WRITE_ADDR_TRIG_t { + CH1_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 1 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH1_AL2_WRITE_ADDR_TRIG_t CH1_AL2_WRITE_ADDR_TRIG at 0x5000006c; + register uint32 CH1_AL2_WRITE_ADDR_TRIG_raw at 0x5000006c; + + type CH1_AL3_CTRL_t { + CH1_AL3_CTRL = uint32(0); // + } + + // Alias for channel 1 CTRL register + register CH1_AL3_CTRL_t CH1_AL3_CTRL at 0x50000070; + register uint32 CH1_AL3_CTRL_raw at 0x50000070; + + type CH1_AL3_WRITE_ADDR_t { + CH1_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 1 WRITE_ADDR register + register CH1_AL3_WRITE_ADDR_t CH1_AL3_WRITE_ADDR at 0x50000074; + register uint32 CH1_AL3_WRITE_ADDR_raw at 0x50000074; + + type CH1_AL3_TRANS_COUNT_t { + CH1_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 1 TRANS_COUNT register + register CH1_AL3_TRANS_COUNT_t CH1_AL3_TRANS_COUNT at 0x50000078; + register uint32 CH1_AL3_TRANS_COUNT_raw at 0x50000078; + + type CH1_AL3_READ_ADDR_TRIG_t { + CH1_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 1 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH1_AL3_READ_ADDR_TRIG_t CH1_AL3_READ_ADDR_TRIG at 0x5000007c; + register uint32 CH1_AL3_READ_ADDR_TRIG_raw at 0x5000007c; + + type CH2_READ_ADDR_t { + CH2_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 2 Read Address pointer + register CH2_READ_ADDR_t CH2_READ_ADDR at 0x50000080; + register uint32 CH2_READ_ADDR_raw at 0x50000080; + + type CH2_WRITE_ADDR_t { + CH2_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 2 Write Address pointer + register CH2_WRITE_ADDR_t CH2_WRITE_ADDR at 0x50000084; + register uint32 CH2_WRITE_ADDR_raw at 0x50000084; + + type CH2_TRANS_COUNT_t { + CH2_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 2 Transfer Count + register CH2_TRANS_COUNT_t CH2_TRANS_COUNT at 0x50000088; + register uint32 CH2_TRANS_COUNT_raw at 0x50000088; + + enum CH2_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH2_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH2_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH2_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 2 Control and Status + register CH2_CTRL_TRIG_t CH2_CTRL_TRIG at 0x5000008c; + register uint32 CH2_CTRL_TRIG_raw at 0x5000008c; + + type CH2_AL1_CTRL_t { + CH2_AL1_CTRL = uint32(0); // + } + + // Alias for channel 2 CTRL register + register CH2_AL1_CTRL_t CH2_AL1_CTRL at 0x50000090; + register uint32 CH2_AL1_CTRL_raw at 0x50000090; + + type CH2_AL1_READ_ADDR_t { + CH2_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 2 READ_ADDR register + register CH2_AL1_READ_ADDR_t CH2_AL1_READ_ADDR at 0x50000094; + register uint32 CH2_AL1_READ_ADDR_raw at 0x50000094; + + type CH2_AL1_WRITE_ADDR_t { + CH2_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 2 WRITE_ADDR register + register CH2_AL1_WRITE_ADDR_t CH2_AL1_WRITE_ADDR at 0x50000098; + register uint32 CH2_AL1_WRITE_ADDR_raw at 0x50000098; + + type CH2_AL1_TRANS_COUNT_TRIG_t { + CH2_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 2 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH2_AL1_TRANS_COUNT_TRIG_t CH2_AL1_TRANS_COUNT_TRIG at 0x5000009c; + register uint32 CH2_AL1_TRANS_COUNT_TRIG_raw at 0x5000009c; + + type CH2_AL2_CTRL_t { + CH2_AL2_CTRL = uint32(0); // + } + + // Alias for channel 2 CTRL register + register CH2_AL2_CTRL_t CH2_AL2_CTRL at 0x500000a0; + register uint32 CH2_AL2_CTRL_raw at 0x500000a0; + + type CH2_AL2_TRANS_COUNT_t { + CH2_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 2 TRANS_COUNT register + register CH2_AL2_TRANS_COUNT_t CH2_AL2_TRANS_COUNT at 0x500000a4; + register uint32 CH2_AL2_TRANS_COUNT_raw at 0x500000a4; + + type CH2_AL2_READ_ADDR_t { + CH2_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 2 READ_ADDR register + register CH2_AL2_READ_ADDR_t CH2_AL2_READ_ADDR at 0x500000a8; + register uint32 CH2_AL2_READ_ADDR_raw at 0x500000a8; + + type CH2_AL2_WRITE_ADDR_TRIG_t { + CH2_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 2 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH2_AL2_WRITE_ADDR_TRIG_t CH2_AL2_WRITE_ADDR_TRIG at 0x500000ac; + register uint32 CH2_AL2_WRITE_ADDR_TRIG_raw at 0x500000ac; + + type CH2_AL3_CTRL_t { + CH2_AL3_CTRL = uint32(0); // + } + + // Alias for channel 2 CTRL register + register CH2_AL3_CTRL_t CH2_AL3_CTRL at 0x500000b0; + register uint32 CH2_AL3_CTRL_raw at 0x500000b0; + + type CH2_AL3_WRITE_ADDR_t { + CH2_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 2 WRITE_ADDR register + register CH2_AL3_WRITE_ADDR_t CH2_AL3_WRITE_ADDR at 0x500000b4; + register uint32 CH2_AL3_WRITE_ADDR_raw at 0x500000b4; + + type CH2_AL3_TRANS_COUNT_t { + CH2_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 2 TRANS_COUNT register + register CH2_AL3_TRANS_COUNT_t CH2_AL3_TRANS_COUNT at 0x500000b8; + register uint32 CH2_AL3_TRANS_COUNT_raw at 0x500000b8; + + type CH2_AL3_READ_ADDR_TRIG_t { + CH2_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 2 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH2_AL3_READ_ADDR_TRIG_t CH2_AL3_READ_ADDR_TRIG at 0x500000bc; + register uint32 CH2_AL3_READ_ADDR_TRIG_raw at 0x500000bc; + + type CH3_READ_ADDR_t { + CH3_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 3 Read Address pointer + register CH3_READ_ADDR_t CH3_READ_ADDR at 0x500000c0; + register uint32 CH3_READ_ADDR_raw at 0x500000c0; + + type CH3_WRITE_ADDR_t { + CH3_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 3 Write Address pointer + register CH3_WRITE_ADDR_t CH3_WRITE_ADDR at 0x500000c4; + register uint32 CH3_WRITE_ADDR_raw at 0x500000c4; + + type CH3_TRANS_COUNT_t { + CH3_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 3 Transfer Count + register CH3_TRANS_COUNT_t CH3_TRANS_COUNT at 0x500000c8; + register uint32 CH3_TRANS_COUNT_raw at 0x500000c8; + + enum CH3_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH3_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH3_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH3_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 3 Control and Status + register CH3_CTRL_TRIG_t CH3_CTRL_TRIG at 0x500000cc; + register uint32 CH3_CTRL_TRIG_raw at 0x500000cc; + + type CH3_AL1_CTRL_t { + CH3_AL1_CTRL = uint32(0); // + } + + // Alias for channel 3 CTRL register + register CH3_AL1_CTRL_t CH3_AL1_CTRL at 0x500000d0; + register uint32 CH3_AL1_CTRL_raw at 0x500000d0; + + type CH3_AL1_READ_ADDR_t { + CH3_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 3 READ_ADDR register + register CH3_AL1_READ_ADDR_t CH3_AL1_READ_ADDR at 0x500000d4; + register uint32 CH3_AL1_READ_ADDR_raw at 0x500000d4; + + type CH3_AL1_WRITE_ADDR_t { + CH3_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 3 WRITE_ADDR register + register CH3_AL1_WRITE_ADDR_t CH3_AL1_WRITE_ADDR at 0x500000d8; + register uint32 CH3_AL1_WRITE_ADDR_raw at 0x500000d8; + + type CH3_AL1_TRANS_COUNT_TRIG_t { + CH3_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 3 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH3_AL1_TRANS_COUNT_TRIG_t CH3_AL1_TRANS_COUNT_TRIG at 0x500000dc; + register uint32 CH3_AL1_TRANS_COUNT_TRIG_raw at 0x500000dc; + + type CH3_AL2_CTRL_t { + CH3_AL2_CTRL = uint32(0); // + } + + // Alias for channel 3 CTRL register + register CH3_AL2_CTRL_t CH3_AL2_CTRL at 0x500000e0; + register uint32 CH3_AL2_CTRL_raw at 0x500000e0; + + type CH3_AL2_TRANS_COUNT_t { + CH3_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 3 TRANS_COUNT register + register CH3_AL2_TRANS_COUNT_t CH3_AL2_TRANS_COUNT at 0x500000e4; + register uint32 CH3_AL2_TRANS_COUNT_raw at 0x500000e4; + + type CH3_AL2_READ_ADDR_t { + CH3_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 3 READ_ADDR register + register CH3_AL2_READ_ADDR_t CH3_AL2_READ_ADDR at 0x500000e8; + register uint32 CH3_AL2_READ_ADDR_raw at 0x500000e8; + + type CH3_AL2_WRITE_ADDR_TRIG_t { + CH3_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 3 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH3_AL2_WRITE_ADDR_TRIG_t CH3_AL2_WRITE_ADDR_TRIG at 0x500000ec; + register uint32 CH3_AL2_WRITE_ADDR_TRIG_raw at 0x500000ec; + + type CH3_AL3_CTRL_t { + CH3_AL3_CTRL = uint32(0); // + } + + // Alias for channel 3 CTRL register + register CH3_AL3_CTRL_t CH3_AL3_CTRL at 0x500000f0; + register uint32 CH3_AL3_CTRL_raw at 0x500000f0; + + type CH3_AL3_WRITE_ADDR_t { + CH3_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 3 WRITE_ADDR register + register CH3_AL3_WRITE_ADDR_t CH3_AL3_WRITE_ADDR at 0x500000f4; + register uint32 CH3_AL3_WRITE_ADDR_raw at 0x500000f4; + + type CH3_AL3_TRANS_COUNT_t { + CH3_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 3 TRANS_COUNT register + register CH3_AL3_TRANS_COUNT_t CH3_AL3_TRANS_COUNT at 0x500000f8; + register uint32 CH3_AL3_TRANS_COUNT_raw at 0x500000f8; + + type CH3_AL3_READ_ADDR_TRIG_t { + CH3_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 3 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH3_AL3_READ_ADDR_TRIG_t CH3_AL3_READ_ADDR_TRIG at 0x500000fc; + register uint32 CH3_AL3_READ_ADDR_TRIG_raw at 0x500000fc; + + type CH4_READ_ADDR_t { + CH4_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 4 Read Address pointer + register CH4_READ_ADDR_t CH4_READ_ADDR at 0x50000100; + register uint32 CH4_READ_ADDR_raw at 0x50000100; + + type CH4_WRITE_ADDR_t { + CH4_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 4 Write Address pointer + register CH4_WRITE_ADDR_t CH4_WRITE_ADDR at 0x50000104; + register uint32 CH4_WRITE_ADDR_raw at 0x50000104; + + type CH4_TRANS_COUNT_t { + CH4_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 4 Transfer Count + register CH4_TRANS_COUNT_t CH4_TRANS_COUNT at 0x50000108; + register uint32 CH4_TRANS_COUNT_raw at 0x50000108; + + enum CH4_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH4_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH4_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH4_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 4 Control and Status + register CH4_CTRL_TRIG_t CH4_CTRL_TRIG at 0x5000010c; + register uint32 CH4_CTRL_TRIG_raw at 0x5000010c; + + type CH4_AL1_CTRL_t { + CH4_AL1_CTRL = uint32(0); // + } + + // Alias for channel 4 CTRL register + register CH4_AL1_CTRL_t CH4_AL1_CTRL at 0x50000110; + register uint32 CH4_AL1_CTRL_raw at 0x50000110; + + type CH4_AL1_READ_ADDR_t { + CH4_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 4 READ_ADDR register + register CH4_AL1_READ_ADDR_t CH4_AL1_READ_ADDR at 0x50000114; + register uint32 CH4_AL1_READ_ADDR_raw at 0x50000114; + + type CH4_AL1_WRITE_ADDR_t { + CH4_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 4 WRITE_ADDR register + register CH4_AL1_WRITE_ADDR_t CH4_AL1_WRITE_ADDR at 0x50000118; + register uint32 CH4_AL1_WRITE_ADDR_raw at 0x50000118; + + type CH4_AL1_TRANS_COUNT_TRIG_t { + CH4_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 4 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH4_AL1_TRANS_COUNT_TRIG_t CH4_AL1_TRANS_COUNT_TRIG at 0x5000011c; + register uint32 CH4_AL1_TRANS_COUNT_TRIG_raw at 0x5000011c; + + type CH4_AL2_CTRL_t { + CH4_AL2_CTRL = uint32(0); // + } + + // Alias for channel 4 CTRL register + register CH4_AL2_CTRL_t CH4_AL2_CTRL at 0x50000120; + register uint32 CH4_AL2_CTRL_raw at 0x50000120; + + type CH4_AL2_TRANS_COUNT_t { + CH4_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 4 TRANS_COUNT register + register CH4_AL2_TRANS_COUNT_t CH4_AL2_TRANS_COUNT at 0x50000124; + register uint32 CH4_AL2_TRANS_COUNT_raw at 0x50000124; + + type CH4_AL2_READ_ADDR_t { + CH4_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 4 READ_ADDR register + register CH4_AL2_READ_ADDR_t CH4_AL2_READ_ADDR at 0x50000128; + register uint32 CH4_AL2_READ_ADDR_raw at 0x50000128; + + type CH4_AL2_WRITE_ADDR_TRIG_t { + CH4_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 4 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH4_AL2_WRITE_ADDR_TRIG_t CH4_AL2_WRITE_ADDR_TRIG at 0x5000012c; + register uint32 CH4_AL2_WRITE_ADDR_TRIG_raw at 0x5000012c; + + type CH4_AL3_CTRL_t { + CH4_AL3_CTRL = uint32(0); // + } + + // Alias for channel 4 CTRL register + register CH4_AL3_CTRL_t CH4_AL3_CTRL at 0x50000130; + register uint32 CH4_AL3_CTRL_raw at 0x50000130; + + type CH4_AL3_WRITE_ADDR_t { + CH4_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 4 WRITE_ADDR register + register CH4_AL3_WRITE_ADDR_t CH4_AL3_WRITE_ADDR at 0x50000134; + register uint32 CH4_AL3_WRITE_ADDR_raw at 0x50000134; + + type CH4_AL3_TRANS_COUNT_t { + CH4_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 4 TRANS_COUNT register + register CH4_AL3_TRANS_COUNT_t CH4_AL3_TRANS_COUNT at 0x50000138; + register uint32 CH4_AL3_TRANS_COUNT_raw at 0x50000138; + + type CH4_AL3_READ_ADDR_TRIG_t { + CH4_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 4 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH4_AL3_READ_ADDR_TRIG_t CH4_AL3_READ_ADDR_TRIG at 0x5000013c; + register uint32 CH4_AL3_READ_ADDR_TRIG_raw at 0x5000013c; + + type CH5_READ_ADDR_t { + CH5_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 5 Read Address pointer + register CH5_READ_ADDR_t CH5_READ_ADDR at 0x50000140; + register uint32 CH5_READ_ADDR_raw at 0x50000140; + + type CH5_WRITE_ADDR_t { + CH5_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 5 Write Address pointer + register CH5_WRITE_ADDR_t CH5_WRITE_ADDR at 0x50000144; + register uint32 CH5_WRITE_ADDR_raw at 0x50000144; + + type CH5_TRANS_COUNT_t { + CH5_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 5 Transfer Count + register CH5_TRANS_COUNT_t CH5_TRANS_COUNT at 0x50000148; + register uint32 CH5_TRANS_COUNT_raw at 0x50000148; + + enum CH5_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH5_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH5_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH5_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 5 Control and Status + register CH5_CTRL_TRIG_t CH5_CTRL_TRIG at 0x5000014c; + register uint32 CH5_CTRL_TRIG_raw at 0x5000014c; + + type CH5_AL1_CTRL_t { + CH5_AL1_CTRL = uint32(0); // + } + + // Alias for channel 5 CTRL register + register CH5_AL1_CTRL_t CH5_AL1_CTRL at 0x50000150; + register uint32 CH5_AL1_CTRL_raw at 0x50000150; + + type CH5_AL1_READ_ADDR_t { + CH5_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 5 READ_ADDR register + register CH5_AL1_READ_ADDR_t CH5_AL1_READ_ADDR at 0x50000154; + register uint32 CH5_AL1_READ_ADDR_raw at 0x50000154; + + type CH5_AL1_WRITE_ADDR_t { + CH5_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 5 WRITE_ADDR register + register CH5_AL1_WRITE_ADDR_t CH5_AL1_WRITE_ADDR at 0x50000158; + register uint32 CH5_AL1_WRITE_ADDR_raw at 0x50000158; + + type CH5_AL1_TRANS_COUNT_TRIG_t { + CH5_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 5 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH5_AL1_TRANS_COUNT_TRIG_t CH5_AL1_TRANS_COUNT_TRIG at 0x5000015c; + register uint32 CH5_AL1_TRANS_COUNT_TRIG_raw at 0x5000015c; + + type CH5_AL2_CTRL_t { + CH5_AL2_CTRL = uint32(0); // + } + + // Alias for channel 5 CTRL register + register CH5_AL2_CTRL_t CH5_AL2_CTRL at 0x50000160; + register uint32 CH5_AL2_CTRL_raw at 0x50000160; + + type CH5_AL2_TRANS_COUNT_t { + CH5_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 5 TRANS_COUNT register + register CH5_AL2_TRANS_COUNT_t CH5_AL2_TRANS_COUNT at 0x50000164; + register uint32 CH5_AL2_TRANS_COUNT_raw at 0x50000164; + + type CH5_AL2_READ_ADDR_t { + CH5_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 5 READ_ADDR register + register CH5_AL2_READ_ADDR_t CH5_AL2_READ_ADDR at 0x50000168; + register uint32 CH5_AL2_READ_ADDR_raw at 0x50000168; + + type CH5_AL2_WRITE_ADDR_TRIG_t { + CH5_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 5 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH5_AL2_WRITE_ADDR_TRIG_t CH5_AL2_WRITE_ADDR_TRIG at 0x5000016c; + register uint32 CH5_AL2_WRITE_ADDR_TRIG_raw at 0x5000016c; + + type CH5_AL3_CTRL_t { + CH5_AL3_CTRL = uint32(0); // + } + + // Alias for channel 5 CTRL register + register CH5_AL3_CTRL_t CH5_AL3_CTRL at 0x50000170; + register uint32 CH5_AL3_CTRL_raw at 0x50000170; + + type CH5_AL3_WRITE_ADDR_t { + CH5_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 5 WRITE_ADDR register + register CH5_AL3_WRITE_ADDR_t CH5_AL3_WRITE_ADDR at 0x50000174; + register uint32 CH5_AL3_WRITE_ADDR_raw at 0x50000174; + + type CH5_AL3_TRANS_COUNT_t { + CH5_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 5 TRANS_COUNT register + register CH5_AL3_TRANS_COUNT_t CH5_AL3_TRANS_COUNT at 0x50000178; + register uint32 CH5_AL3_TRANS_COUNT_raw at 0x50000178; + + type CH5_AL3_READ_ADDR_TRIG_t { + CH5_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 5 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH5_AL3_READ_ADDR_TRIG_t CH5_AL3_READ_ADDR_TRIG at 0x5000017c; + register uint32 CH5_AL3_READ_ADDR_TRIG_raw at 0x5000017c; + + type CH6_READ_ADDR_t { + CH6_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 6 Read Address pointer + register CH6_READ_ADDR_t CH6_READ_ADDR at 0x50000180; + register uint32 CH6_READ_ADDR_raw at 0x50000180; + + type CH6_WRITE_ADDR_t { + CH6_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 6 Write Address pointer + register CH6_WRITE_ADDR_t CH6_WRITE_ADDR at 0x50000184; + register uint32 CH6_WRITE_ADDR_raw at 0x50000184; + + type CH6_TRANS_COUNT_t { + CH6_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 6 Transfer Count + register CH6_TRANS_COUNT_t CH6_TRANS_COUNT at 0x50000188; + register uint32 CH6_TRANS_COUNT_raw at 0x50000188; + + enum CH6_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH6_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH6_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH6_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 6 Control and Status + register CH6_CTRL_TRIG_t CH6_CTRL_TRIG at 0x5000018c; + register uint32 CH6_CTRL_TRIG_raw at 0x5000018c; + + type CH6_AL1_CTRL_t { + CH6_AL1_CTRL = uint32(0); // + } + + // Alias for channel 6 CTRL register + register CH6_AL1_CTRL_t CH6_AL1_CTRL at 0x50000190; + register uint32 CH6_AL1_CTRL_raw at 0x50000190; + + type CH6_AL1_READ_ADDR_t { + CH6_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 6 READ_ADDR register + register CH6_AL1_READ_ADDR_t CH6_AL1_READ_ADDR at 0x50000194; + register uint32 CH6_AL1_READ_ADDR_raw at 0x50000194; + + type CH6_AL1_WRITE_ADDR_t { + CH6_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 6 WRITE_ADDR register + register CH6_AL1_WRITE_ADDR_t CH6_AL1_WRITE_ADDR at 0x50000198; + register uint32 CH6_AL1_WRITE_ADDR_raw at 0x50000198; + + type CH6_AL1_TRANS_COUNT_TRIG_t { + CH6_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 6 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH6_AL1_TRANS_COUNT_TRIG_t CH6_AL1_TRANS_COUNT_TRIG at 0x5000019c; + register uint32 CH6_AL1_TRANS_COUNT_TRIG_raw at 0x5000019c; + + type CH6_AL2_CTRL_t { + CH6_AL2_CTRL = uint32(0); // + } + + // Alias for channel 6 CTRL register + register CH6_AL2_CTRL_t CH6_AL2_CTRL at 0x500001a0; + register uint32 CH6_AL2_CTRL_raw at 0x500001a0; + + type CH6_AL2_TRANS_COUNT_t { + CH6_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 6 TRANS_COUNT register + register CH6_AL2_TRANS_COUNT_t CH6_AL2_TRANS_COUNT at 0x500001a4; + register uint32 CH6_AL2_TRANS_COUNT_raw at 0x500001a4; + + type CH6_AL2_READ_ADDR_t { + CH6_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 6 READ_ADDR register + register CH6_AL2_READ_ADDR_t CH6_AL2_READ_ADDR at 0x500001a8; + register uint32 CH6_AL2_READ_ADDR_raw at 0x500001a8; + + type CH6_AL2_WRITE_ADDR_TRIG_t { + CH6_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 6 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH6_AL2_WRITE_ADDR_TRIG_t CH6_AL2_WRITE_ADDR_TRIG at 0x500001ac; + register uint32 CH6_AL2_WRITE_ADDR_TRIG_raw at 0x500001ac; + + type CH6_AL3_CTRL_t { + CH6_AL3_CTRL = uint32(0); // + } + + // Alias for channel 6 CTRL register + register CH6_AL3_CTRL_t CH6_AL3_CTRL at 0x500001b0; + register uint32 CH6_AL3_CTRL_raw at 0x500001b0; + + type CH6_AL3_WRITE_ADDR_t { + CH6_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 6 WRITE_ADDR register + register CH6_AL3_WRITE_ADDR_t CH6_AL3_WRITE_ADDR at 0x500001b4; + register uint32 CH6_AL3_WRITE_ADDR_raw at 0x500001b4; + + type CH6_AL3_TRANS_COUNT_t { + CH6_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 6 TRANS_COUNT register + register CH6_AL3_TRANS_COUNT_t CH6_AL3_TRANS_COUNT at 0x500001b8; + register uint32 CH6_AL3_TRANS_COUNT_raw at 0x500001b8; + + type CH6_AL3_READ_ADDR_TRIG_t { + CH6_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 6 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH6_AL3_READ_ADDR_TRIG_t CH6_AL3_READ_ADDR_TRIG at 0x500001bc; + register uint32 CH6_AL3_READ_ADDR_TRIG_raw at 0x500001bc; + + type CH7_READ_ADDR_t { + CH7_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 7 Read Address pointer + register CH7_READ_ADDR_t CH7_READ_ADDR at 0x500001c0; + register uint32 CH7_READ_ADDR_raw at 0x500001c0; + + type CH7_WRITE_ADDR_t { + CH7_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 7 Write Address pointer + register CH7_WRITE_ADDR_t CH7_WRITE_ADDR at 0x500001c4; + register uint32 CH7_WRITE_ADDR_raw at 0x500001c4; + + type CH7_TRANS_COUNT_t { + CH7_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 7 Transfer Count + register CH7_TRANS_COUNT_t CH7_TRANS_COUNT at 0x500001c8; + register uint32 CH7_TRANS_COUNT_raw at 0x500001c8; + + enum CH7_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH7_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH7_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH7_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 7 Control and Status + register CH7_CTRL_TRIG_t CH7_CTRL_TRIG at 0x500001cc; + register uint32 CH7_CTRL_TRIG_raw at 0x500001cc; + + type CH7_AL1_CTRL_t { + CH7_AL1_CTRL = uint32(0); // + } + + // Alias for channel 7 CTRL register + register CH7_AL1_CTRL_t CH7_AL1_CTRL at 0x500001d0; + register uint32 CH7_AL1_CTRL_raw at 0x500001d0; + + type CH7_AL1_READ_ADDR_t { + CH7_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 7 READ_ADDR register + register CH7_AL1_READ_ADDR_t CH7_AL1_READ_ADDR at 0x500001d4; + register uint32 CH7_AL1_READ_ADDR_raw at 0x500001d4; + + type CH7_AL1_WRITE_ADDR_t { + CH7_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 7 WRITE_ADDR register + register CH7_AL1_WRITE_ADDR_t CH7_AL1_WRITE_ADDR at 0x500001d8; + register uint32 CH7_AL1_WRITE_ADDR_raw at 0x500001d8; + + type CH7_AL1_TRANS_COUNT_TRIG_t { + CH7_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 7 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH7_AL1_TRANS_COUNT_TRIG_t CH7_AL1_TRANS_COUNT_TRIG at 0x500001dc; + register uint32 CH7_AL1_TRANS_COUNT_TRIG_raw at 0x500001dc; + + type CH7_AL2_CTRL_t { + CH7_AL2_CTRL = uint32(0); // + } + + // Alias for channel 7 CTRL register + register CH7_AL2_CTRL_t CH7_AL2_CTRL at 0x500001e0; + register uint32 CH7_AL2_CTRL_raw at 0x500001e0; + + type CH7_AL2_TRANS_COUNT_t { + CH7_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 7 TRANS_COUNT register + register CH7_AL2_TRANS_COUNT_t CH7_AL2_TRANS_COUNT at 0x500001e4; + register uint32 CH7_AL2_TRANS_COUNT_raw at 0x500001e4; + + type CH7_AL2_READ_ADDR_t { + CH7_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 7 READ_ADDR register + register CH7_AL2_READ_ADDR_t CH7_AL2_READ_ADDR at 0x500001e8; + register uint32 CH7_AL2_READ_ADDR_raw at 0x500001e8; + + type CH7_AL2_WRITE_ADDR_TRIG_t { + CH7_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 7 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH7_AL2_WRITE_ADDR_TRIG_t CH7_AL2_WRITE_ADDR_TRIG at 0x500001ec; + register uint32 CH7_AL2_WRITE_ADDR_TRIG_raw at 0x500001ec; + + type CH7_AL3_CTRL_t { + CH7_AL3_CTRL = uint32(0); // + } + + // Alias for channel 7 CTRL register + register CH7_AL3_CTRL_t CH7_AL3_CTRL at 0x500001f0; + register uint32 CH7_AL3_CTRL_raw at 0x500001f0; + + type CH7_AL3_WRITE_ADDR_t { + CH7_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 7 WRITE_ADDR register + register CH7_AL3_WRITE_ADDR_t CH7_AL3_WRITE_ADDR at 0x500001f4; + register uint32 CH7_AL3_WRITE_ADDR_raw at 0x500001f4; + + type CH7_AL3_TRANS_COUNT_t { + CH7_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 7 TRANS_COUNT register + register CH7_AL3_TRANS_COUNT_t CH7_AL3_TRANS_COUNT at 0x500001f8; + register uint32 CH7_AL3_TRANS_COUNT_raw at 0x500001f8; + + type CH7_AL3_READ_ADDR_TRIG_t { + CH7_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 7 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH7_AL3_READ_ADDR_TRIG_t CH7_AL3_READ_ADDR_TRIG at 0x500001fc; + register uint32 CH7_AL3_READ_ADDR_TRIG_raw at 0x500001fc; + + type CH8_READ_ADDR_t { + CH8_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 8 Read Address pointer + register CH8_READ_ADDR_t CH8_READ_ADDR at 0x50000200; + register uint32 CH8_READ_ADDR_raw at 0x50000200; + + type CH8_WRITE_ADDR_t { + CH8_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 8 Write Address pointer + register CH8_WRITE_ADDR_t CH8_WRITE_ADDR at 0x50000204; + register uint32 CH8_WRITE_ADDR_raw at 0x50000204; + + type CH8_TRANS_COUNT_t { + CH8_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 8 Transfer Count + register CH8_TRANS_COUNT_t CH8_TRANS_COUNT at 0x50000208; + register uint32 CH8_TRANS_COUNT_raw at 0x50000208; + + enum CH8_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH8_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH8_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH8_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 8 Control and Status + register CH8_CTRL_TRIG_t CH8_CTRL_TRIG at 0x5000020c; + register uint32 CH8_CTRL_TRIG_raw at 0x5000020c; + + type CH8_AL1_CTRL_t { + CH8_AL1_CTRL = uint32(0); // + } + + // Alias for channel 8 CTRL register + register CH8_AL1_CTRL_t CH8_AL1_CTRL at 0x50000210; + register uint32 CH8_AL1_CTRL_raw at 0x50000210; + + type CH8_AL1_READ_ADDR_t { + CH8_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 8 READ_ADDR register + register CH8_AL1_READ_ADDR_t CH8_AL1_READ_ADDR at 0x50000214; + register uint32 CH8_AL1_READ_ADDR_raw at 0x50000214; + + type CH8_AL1_WRITE_ADDR_t { + CH8_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 8 WRITE_ADDR register + register CH8_AL1_WRITE_ADDR_t CH8_AL1_WRITE_ADDR at 0x50000218; + register uint32 CH8_AL1_WRITE_ADDR_raw at 0x50000218; + + type CH8_AL1_TRANS_COUNT_TRIG_t { + CH8_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 8 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH8_AL1_TRANS_COUNT_TRIG_t CH8_AL1_TRANS_COUNT_TRIG at 0x5000021c; + register uint32 CH8_AL1_TRANS_COUNT_TRIG_raw at 0x5000021c; + + type CH8_AL2_CTRL_t { + CH8_AL2_CTRL = uint32(0); // + } + + // Alias for channel 8 CTRL register + register CH8_AL2_CTRL_t CH8_AL2_CTRL at 0x50000220; + register uint32 CH8_AL2_CTRL_raw at 0x50000220; + + type CH8_AL2_TRANS_COUNT_t { + CH8_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 8 TRANS_COUNT register + register CH8_AL2_TRANS_COUNT_t CH8_AL2_TRANS_COUNT at 0x50000224; + register uint32 CH8_AL2_TRANS_COUNT_raw at 0x50000224; + + type CH8_AL2_READ_ADDR_t { + CH8_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 8 READ_ADDR register + register CH8_AL2_READ_ADDR_t CH8_AL2_READ_ADDR at 0x50000228; + register uint32 CH8_AL2_READ_ADDR_raw at 0x50000228; + + type CH8_AL2_WRITE_ADDR_TRIG_t { + CH8_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 8 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH8_AL2_WRITE_ADDR_TRIG_t CH8_AL2_WRITE_ADDR_TRIG at 0x5000022c; + register uint32 CH8_AL2_WRITE_ADDR_TRIG_raw at 0x5000022c; + + type CH8_AL3_CTRL_t { + CH8_AL3_CTRL = uint32(0); // + } + + // Alias for channel 8 CTRL register + register CH8_AL3_CTRL_t CH8_AL3_CTRL at 0x50000230; + register uint32 CH8_AL3_CTRL_raw at 0x50000230; + + type CH8_AL3_WRITE_ADDR_t { + CH8_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 8 WRITE_ADDR register + register CH8_AL3_WRITE_ADDR_t CH8_AL3_WRITE_ADDR at 0x50000234; + register uint32 CH8_AL3_WRITE_ADDR_raw at 0x50000234; + + type CH8_AL3_TRANS_COUNT_t { + CH8_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 8 TRANS_COUNT register + register CH8_AL3_TRANS_COUNT_t CH8_AL3_TRANS_COUNT at 0x50000238; + register uint32 CH8_AL3_TRANS_COUNT_raw at 0x50000238; + + type CH8_AL3_READ_ADDR_TRIG_t { + CH8_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 8 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH8_AL3_READ_ADDR_TRIG_t CH8_AL3_READ_ADDR_TRIG at 0x5000023c; + register uint32 CH8_AL3_READ_ADDR_TRIG_raw at 0x5000023c; + + type CH9_READ_ADDR_t { + CH9_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 9 Read Address pointer + register CH9_READ_ADDR_t CH9_READ_ADDR at 0x50000240; + register uint32 CH9_READ_ADDR_raw at 0x50000240; + + type CH9_WRITE_ADDR_t { + CH9_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 9 Write Address pointer + register CH9_WRITE_ADDR_t CH9_WRITE_ADDR at 0x50000244; + register uint32 CH9_WRITE_ADDR_raw at 0x50000244; + + type CH9_TRANS_COUNT_t { + CH9_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 9 Transfer Count + register CH9_TRANS_COUNT_t CH9_TRANS_COUNT at 0x50000248; + register uint32 CH9_TRANS_COUNT_raw at 0x50000248; + + enum CH9_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH9_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH9_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH9_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 9 Control and Status + register CH9_CTRL_TRIG_t CH9_CTRL_TRIG at 0x5000024c; + register uint32 CH9_CTRL_TRIG_raw at 0x5000024c; + + type CH9_AL1_CTRL_t { + CH9_AL1_CTRL = uint32(0); // + } + + // Alias for channel 9 CTRL register + register CH9_AL1_CTRL_t CH9_AL1_CTRL at 0x50000250; + register uint32 CH9_AL1_CTRL_raw at 0x50000250; + + type CH9_AL1_READ_ADDR_t { + CH9_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 9 READ_ADDR register + register CH9_AL1_READ_ADDR_t CH9_AL1_READ_ADDR at 0x50000254; + register uint32 CH9_AL1_READ_ADDR_raw at 0x50000254; + + type CH9_AL1_WRITE_ADDR_t { + CH9_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 9 WRITE_ADDR register + register CH9_AL1_WRITE_ADDR_t CH9_AL1_WRITE_ADDR at 0x50000258; + register uint32 CH9_AL1_WRITE_ADDR_raw at 0x50000258; + + type CH9_AL1_TRANS_COUNT_TRIG_t { + CH9_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 9 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH9_AL1_TRANS_COUNT_TRIG_t CH9_AL1_TRANS_COUNT_TRIG at 0x5000025c; + register uint32 CH9_AL1_TRANS_COUNT_TRIG_raw at 0x5000025c; + + type CH9_AL2_CTRL_t { + CH9_AL2_CTRL = uint32(0); // + } + + // Alias for channel 9 CTRL register + register CH9_AL2_CTRL_t CH9_AL2_CTRL at 0x50000260; + register uint32 CH9_AL2_CTRL_raw at 0x50000260; + + type CH9_AL2_TRANS_COUNT_t { + CH9_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 9 TRANS_COUNT register + register CH9_AL2_TRANS_COUNT_t CH9_AL2_TRANS_COUNT at 0x50000264; + register uint32 CH9_AL2_TRANS_COUNT_raw at 0x50000264; + + type CH9_AL2_READ_ADDR_t { + CH9_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 9 READ_ADDR register + register CH9_AL2_READ_ADDR_t CH9_AL2_READ_ADDR at 0x50000268; + register uint32 CH9_AL2_READ_ADDR_raw at 0x50000268; + + type CH9_AL2_WRITE_ADDR_TRIG_t { + CH9_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 9 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH9_AL2_WRITE_ADDR_TRIG_t CH9_AL2_WRITE_ADDR_TRIG at 0x5000026c; + register uint32 CH9_AL2_WRITE_ADDR_TRIG_raw at 0x5000026c; + + type CH9_AL3_CTRL_t { + CH9_AL3_CTRL = uint32(0); // + } + + // Alias for channel 9 CTRL register + register CH9_AL3_CTRL_t CH9_AL3_CTRL at 0x50000270; + register uint32 CH9_AL3_CTRL_raw at 0x50000270; + + type CH9_AL3_WRITE_ADDR_t { + CH9_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 9 WRITE_ADDR register + register CH9_AL3_WRITE_ADDR_t CH9_AL3_WRITE_ADDR at 0x50000274; + register uint32 CH9_AL3_WRITE_ADDR_raw at 0x50000274; + + type CH9_AL3_TRANS_COUNT_t { + CH9_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 9 TRANS_COUNT register + register CH9_AL3_TRANS_COUNT_t CH9_AL3_TRANS_COUNT at 0x50000278; + register uint32 CH9_AL3_TRANS_COUNT_raw at 0x50000278; + + type CH9_AL3_READ_ADDR_TRIG_t { + CH9_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 9 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH9_AL3_READ_ADDR_TRIG_t CH9_AL3_READ_ADDR_TRIG at 0x5000027c; + register uint32 CH9_AL3_READ_ADDR_TRIG_raw at 0x5000027c; + + type CH10_READ_ADDR_t { + CH10_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 10 Read Address pointer + register CH10_READ_ADDR_t CH10_READ_ADDR at 0x50000280; + register uint32 CH10_READ_ADDR_raw at 0x50000280; + + type CH10_WRITE_ADDR_t { + CH10_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 10 Write Address pointer + register CH10_WRITE_ADDR_t CH10_WRITE_ADDR at 0x50000284; + register uint32 CH10_WRITE_ADDR_raw at 0x50000284; + + type CH10_TRANS_COUNT_t { + CH10_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 10 Transfer Count + register CH10_TRANS_COUNT_t CH10_TRANS_COUNT at 0x50000288; + register uint32 CH10_TRANS_COUNT_raw at 0x50000288; + + enum CH10_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH10_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH10_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH10_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 10 Control and Status + register CH10_CTRL_TRIG_t CH10_CTRL_TRIG at 0x5000028c; + register uint32 CH10_CTRL_TRIG_raw at 0x5000028c; + + type CH10_AL1_CTRL_t { + CH10_AL1_CTRL = uint32(0); // + } + + // Alias for channel 10 CTRL register + register CH10_AL1_CTRL_t CH10_AL1_CTRL at 0x50000290; + register uint32 CH10_AL1_CTRL_raw at 0x50000290; + + type CH10_AL1_READ_ADDR_t { + CH10_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 10 READ_ADDR register + register CH10_AL1_READ_ADDR_t CH10_AL1_READ_ADDR at 0x50000294; + register uint32 CH10_AL1_READ_ADDR_raw at 0x50000294; + + type CH10_AL1_WRITE_ADDR_t { + CH10_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 10 WRITE_ADDR register + register CH10_AL1_WRITE_ADDR_t CH10_AL1_WRITE_ADDR at 0x50000298; + register uint32 CH10_AL1_WRITE_ADDR_raw at 0x50000298; + + type CH10_AL1_TRANS_COUNT_TRIG_t { + CH10_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 10 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH10_AL1_TRANS_COUNT_TRIG_t CH10_AL1_TRANS_COUNT_TRIG at 0x5000029c; + register uint32 CH10_AL1_TRANS_COUNT_TRIG_raw at 0x5000029c; + + type CH10_AL2_CTRL_t { + CH10_AL2_CTRL = uint32(0); // + } + + // Alias for channel 10 CTRL register + register CH10_AL2_CTRL_t CH10_AL2_CTRL at 0x500002a0; + register uint32 CH10_AL2_CTRL_raw at 0x500002a0; + + type CH10_AL2_TRANS_COUNT_t { + CH10_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 10 TRANS_COUNT register + register CH10_AL2_TRANS_COUNT_t CH10_AL2_TRANS_COUNT at 0x500002a4; + register uint32 CH10_AL2_TRANS_COUNT_raw at 0x500002a4; + + type CH10_AL2_READ_ADDR_t { + CH10_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 10 READ_ADDR register + register CH10_AL2_READ_ADDR_t CH10_AL2_READ_ADDR at 0x500002a8; + register uint32 CH10_AL2_READ_ADDR_raw at 0x500002a8; + + type CH10_AL2_WRITE_ADDR_TRIG_t { + CH10_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 10 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH10_AL2_WRITE_ADDR_TRIG_t CH10_AL2_WRITE_ADDR_TRIG at 0x500002ac; + register uint32 CH10_AL2_WRITE_ADDR_TRIG_raw at 0x500002ac; + + type CH10_AL3_CTRL_t { + CH10_AL3_CTRL = uint32(0); // + } + + // Alias for channel 10 CTRL register + register CH10_AL3_CTRL_t CH10_AL3_CTRL at 0x500002b0; + register uint32 CH10_AL3_CTRL_raw at 0x500002b0; + + type CH10_AL3_WRITE_ADDR_t { + CH10_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 10 WRITE_ADDR register + register CH10_AL3_WRITE_ADDR_t CH10_AL3_WRITE_ADDR at 0x500002b4; + register uint32 CH10_AL3_WRITE_ADDR_raw at 0x500002b4; + + type CH10_AL3_TRANS_COUNT_t { + CH10_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 10 TRANS_COUNT register + register CH10_AL3_TRANS_COUNT_t CH10_AL3_TRANS_COUNT at 0x500002b8; + register uint32 CH10_AL3_TRANS_COUNT_raw at 0x500002b8; + + type CH10_AL3_READ_ADDR_TRIG_t { + CH10_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 10 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH10_AL3_READ_ADDR_TRIG_t CH10_AL3_READ_ADDR_TRIG at 0x500002bc; + register uint32 CH10_AL3_READ_ADDR_TRIG_raw at 0x500002bc; + + type CH11_READ_ADDR_t { + CH11_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 11 Read Address pointer + register CH11_READ_ADDR_t CH11_READ_ADDR at 0x500002c0; + register uint32 CH11_READ_ADDR_raw at 0x500002c0; + + type CH11_WRITE_ADDR_t { + CH11_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 11 Write Address pointer + register CH11_WRITE_ADDR_t CH11_WRITE_ADDR at 0x500002c4; + register uint32 CH11_WRITE_ADDR_raw at 0x500002c4; + + type CH11_TRANS_COUNT_t { + CH11_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 11 Transfer Count + register CH11_TRANS_COUNT_t CH11_TRANS_COUNT at 0x500002c8; + register uint32 CH11_TRANS_COUNT_raw at 0x500002c8; + + enum CH11_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH11_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH11_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } + + type CH11_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 11 Control and Status + register CH11_CTRL_TRIG_t CH11_CTRL_TRIG at 0x500002cc; + register uint32 CH11_CTRL_TRIG_raw at 0x500002cc; + + type CH11_AL1_CTRL_t { + CH11_AL1_CTRL = uint32(0); // + } + + // Alias for channel 11 CTRL register + register CH11_AL1_CTRL_t CH11_AL1_CTRL at 0x500002d0; + register uint32 CH11_AL1_CTRL_raw at 0x500002d0; + + type CH11_AL1_READ_ADDR_t { + CH11_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 11 READ_ADDR register + register CH11_AL1_READ_ADDR_t CH11_AL1_READ_ADDR at 0x500002d4; + register uint32 CH11_AL1_READ_ADDR_raw at 0x500002d4; + + type CH11_AL1_WRITE_ADDR_t { + CH11_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 11 WRITE_ADDR register + register CH11_AL1_WRITE_ADDR_t CH11_AL1_WRITE_ADDR at 0x500002d8; + register uint32 CH11_AL1_WRITE_ADDR_raw at 0x500002d8; + + type CH11_AL1_TRANS_COUNT_TRIG_t { + CH11_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 11 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH11_AL1_TRANS_COUNT_TRIG_t CH11_AL1_TRANS_COUNT_TRIG at 0x500002dc; + register uint32 CH11_AL1_TRANS_COUNT_TRIG_raw at 0x500002dc; + + type CH11_AL2_CTRL_t { + CH11_AL2_CTRL = uint32(0); // + } + + // Alias for channel 11 CTRL register + register CH11_AL2_CTRL_t CH11_AL2_CTRL at 0x500002e0; + register uint32 CH11_AL2_CTRL_raw at 0x500002e0; + + type CH11_AL2_TRANS_COUNT_t { + CH11_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 11 TRANS_COUNT register + register CH11_AL2_TRANS_COUNT_t CH11_AL2_TRANS_COUNT at 0x500002e4; + register uint32 CH11_AL2_TRANS_COUNT_raw at 0x500002e4; + + type CH11_AL2_READ_ADDR_t { + CH11_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 11 READ_ADDR register + register CH11_AL2_READ_ADDR_t CH11_AL2_READ_ADDR at 0x500002e8; + register uint32 CH11_AL2_READ_ADDR_raw at 0x500002e8; + + type CH11_AL2_WRITE_ADDR_TRIG_t { + CH11_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 11 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH11_AL2_WRITE_ADDR_TRIG_t CH11_AL2_WRITE_ADDR_TRIG at 0x500002ec; + register uint32 CH11_AL2_WRITE_ADDR_TRIG_raw at 0x500002ec; + + type CH11_AL3_CTRL_t { + CH11_AL3_CTRL = uint32(0); // + } + + // Alias for channel 11 CTRL register + register CH11_AL3_CTRL_t CH11_AL3_CTRL at 0x500002f0; + register uint32 CH11_AL3_CTRL_raw at 0x500002f0; + + type CH11_AL3_WRITE_ADDR_t { + CH11_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 11 WRITE_ADDR register + register CH11_AL3_WRITE_ADDR_t CH11_AL3_WRITE_ADDR at 0x500002f4; + register uint32 CH11_AL3_WRITE_ADDR_raw at 0x500002f4; + + type CH11_AL3_TRANS_COUNT_t { + CH11_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 11 TRANS_COUNT register + register CH11_AL3_TRANS_COUNT_t CH11_AL3_TRANS_COUNT at 0x500002f8; + register uint32 CH11_AL3_TRANS_COUNT_raw at 0x500002f8; + + type CH11_AL3_READ_ADDR_TRIG_t { + CH11_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 11 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH11_AL3_READ_ADDR_TRIG_t CH11_AL3_READ_ADDR_TRIG at 0x500002fc; + register uint32 CH11_AL3_READ_ADDR_TRIG_raw at 0x500002fc; + + type DMA_INTR_t { + INTR = uint16(0); // Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + _res1 = uint16(0); // Reserved, 16 bits + } + + // Interrupt Status (raw) + register DMA_INTR_t DMA_INTR at 0x50000400; + register uint32 DMA_INTR_raw at 0x50000400; + + type INTE0_t { + INTE0 = uint16(0); // Set bit n to pass interrupts from channel n to DMA IRQ 0. + _res1 = uint16(0); // Reserved, 16 bits + } + + // Interrupt Enables for IRQ 0 + register INTE0_t INTE0 at 0x50000404; + register uint32 INTE0_raw at 0x50000404; + + type INTF0_t { + INTF0 = uint16(0); // Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + _res1 = uint16(0); // Reserved, 16 bits + } + + // Force Interrupts + register INTF0_t INTF0 at 0x50000408; + register uint32 INTF0_raw at 0x50000408; + + type INTS0_t { + INTS0 = uint16(0); // Indicates active channel interrupt requests which are currently causing IRQ 0 to be asserted. Channel interrupts can be cleared by writing a bit mask here. + _res1 = uint16(0); // Reserved, 16 bits + } + + // Interrupt Status for IRQ 0 + register INTS0_t INTS0 at 0x5000040c; + register uint32 INTS0_raw at 0x5000040c; + + type DMA_INTR1_t { + INTR1 = uint16(0); // Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + _res1 = uint16(0); // Reserved, 16 bits + } + + // Interrupt Status (raw) + register DMA_INTR1_t DMA_INTR1 at 0x50000410; + register uint32 DMA_INTR1_raw at 0x50000410; + + type INTE1_t { + INTE1 = uint16(0); // Set bit n to pass interrupts from channel n to DMA IRQ 1. + _res1 = uint16(0); // Reserved, 16 bits + } + + // Interrupt Enables for IRQ 1 + register INTE1_t INTE1 at 0x50000414; + register uint32 INTE1_raw at 0x50000414; + + type INTF1_t { + INTF1 = uint16(0); // Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + _res1 = uint16(0); // Reserved, 16 bits + } + + // Force Interrupts for IRQ 1 + register INTF1_t INTF1 at 0x50000418; + register uint32 INTF1_raw at 0x50000418; + + type INTS1_t { + INTS1 = uint16(0); // Indicates active channel interrupt requests which are currently causing IRQ 1 to be asserted. Channel interrupts can be cleared by writing a bit mask here. + _res1 = uint16(0); // Reserved, 16 bits + } + + // Interrupt Status (masked) for IRQ 1 + register INTS1_t INTS1 at 0x5000041c; + register uint32 INTS1_raw at 0x5000041c; + + type TIMER0_t { + Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + X = uint16(0); // Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + } + + // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + register TIMER0_t TIMER0 at 0x50000420; + register uint32 TIMER0_raw at 0x50000420; + + type TIMER1_t { + Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + X = uint16(0); // Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + } + + // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + register TIMER1_t TIMER1 at 0x50000424; + register uint32 TIMER1_raw at 0x50000424; + + type TIMER2_t { + Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + X = uint16(0); // Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + } + + // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + register TIMER2_t TIMER2 at 0x50000428; + register uint32 TIMER2_raw at 0x50000428; + + type TIMER3_t { + Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + X = uint16(0); // Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + } + + // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + register TIMER3_t TIMER3 at 0x5000042c; + register uint32 TIMER3_raw at 0x5000042c; + + type MULTI_CHAN_TRIGGER_t { + MULTI_CHAN_TRIGGER = uint16(0); // Each bit in this register corresponds to a DMA channel. Writing a 1 to the relevant bit is the same as writing to that channel's trigger register; the channel will start if it is currently enabled and not already busy. + _res1 = uint16(0); // Reserved, 16 bits + } + + // Trigger one or more channels simultaneously + register MULTI_CHAN_TRIGGER_t MULTI_CHAN_TRIGGER at 0x50000430; + register uint32 MULTI_CHAN_TRIGGER_raw at 0x50000430; + + enum SNIFF_CTRL_CALC { + CRC32 = 0, // Calculate a CRC-32 (IEEE802.3 polynomial) + CRC32R = 1, // Calculate a CRC-32 (IEEE802.3 polynomial) with bit reversed data + CRC16 = 2, // Calculate a CRC-16-CCITT + CRC16R = 3, // Calculate a CRC-16-CCITT with bit reversed data + EVEN = 14, // XOR reduction over all data. == 1 if the total 1 population count is odd. + SUM = 15 // Calculate a simple 32-bit checksum (addition with a 32 bit accumulator) + } + + type SNIFF_CTRL_t { + EN = false; // Enable sniffer + DMACH = uint4(0); // DMA channel for Sniffer to observe + CALC = uint4(0); // + BSWAP = false; // Locally perform a byte reverse on the sniffed data, before feeding into checksum. Note that the sniff hardware is downstream of the DMA channel byteswap performed in the read master: if channel CTRL_BSWAP and SNIFF_CTRL_BSWAP are both enabled, their effects cancel from the sniffer's point of view. + OUT_REV = false; // If set, the result appears bit-reversed when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + OUT_INV = false; // If set, the result appears inverted (bitwise complement) when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + _res1 = uint20(0); // Reserved, 20 bits + } + + // Sniffer Control + register SNIFF_CTRL_t SNIFF_CTRL at 0x50000434; + register uint32 SNIFF_CTRL_raw at 0x50000434; + + type SNIFF_DATA_t { + SNIFF_DATA = uint32(0); // Write an initial seed value here before starting a DMA transfer on the channel indicated by SNIFF_CTRL_DMACH. The hardware will update this register each time it observes a read from the indicated channel. Once the channel completes, the final result can be read from this register. + } + + // Data accumulator for sniff hardware + register SNIFF_DATA_t SNIFF_DATA at 0x50000438; + register uint32 SNIFF_DATA_raw at 0x50000438; + + type FIFO_LEVELS_t { + TDF_LVL = uint8(0); // Current Transfer-Data-FIFO fill level + WAF_LVL = uint8(0); // Current Write-Address-FIFO fill level + RAF_LVL = uint8(0); // Current Read-Address-FIFO fill level + _res1 = uint8(0); // Reserved, 8 bits + } + + // Debug RAF, WAF, TDF levels + register FIFO_LEVELS_t FIFO_LEVELS at 0x50000440; + register uint32 FIFO_LEVELS_raw at 0x50000440; + + type CHAN_ABORT_t { + CHAN_ABORT = uint16(0); // Each bit corresponds to a channel. Writing a 1 aborts whatever transfer sequence is in progress on that channel. The bit will remain high until any in-flight transfers have been flushed through the address and data FIFOs. After writing, this register must be polled until it returns all-zero. Until this point, it is unsafe to restart the channel. + _res1 = uint16(0); // Reserved, 16 bits + } + + // Abort an in-progress transfer sequence on one or more channels + register CHAN_ABORT_t CHAN_ABORT at 0x50000444; + register uint32 CHAN_ABORT_raw at 0x50000444; + + type N_CHANNELS_t { + N_CHANNELS = uint5(0); // + _res1 = uint27(0); // Reserved, 27 bits + } + + // The number of channels this DMA instance is equipped with. This DMA supports up to 16 hardware channels, but can be configured with as few as one, to minimise silicon area. + register N_CHANNELS_t N_CHANNELS at 0x50000448; + register uint32 N_CHANNELS_raw at 0x50000448; + + type CH0_DBG_CTDREQ_t { + CH0_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH0_DBG_CTDREQ_t CH0_DBG_CTDREQ at 0x50000800; + register uint32 CH0_DBG_CTDREQ_raw at 0x50000800; + + type CH0_DBG_TCR_t { + CH0_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH0_DBG_TCR_t CH0_DBG_TCR at 0x50000804; + register uint32 CH0_DBG_TCR_raw at 0x50000804; + + type CH1_DBG_CTDREQ_t { + CH1_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH1_DBG_CTDREQ_t CH1_DBG_CTDREQ at 0x50000840; + register uint32 CH1_DBG_CTDREQ_raw at 0x50000840; + + type CH1_DBG_TCR_t { + CH1_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH1_DBG_TCR_t CH1_DBG_TCR at 0x50000844; + register uint32 CH1_DBG_TCR_raw at 0x50000844; + + type CH2_DBG_CTDREQ_t { + CH2_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH2_DBG_CTDREQ_t CH2_DBG_CTDREQ at 0x50000880; + register uint32 CH2_DBG_CTDREQ_raw at 0x50000880; + + type CH2_DBG_TCR_t { + CH2_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH2_DBG_TCR_t CH2_DBG_TCR at 0x50000884; + register uint32 CH2_DBG_TCR_raw at 0x50000884; + + type CH3_DBG_CTDREQ_t { + CH3_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH3_DBG_CTDREQ_t CH3_DBG_CTDREQ at 0x500008c0; + register uint32 CH3_DBG_CTDREQ_raw at 0x500008c0; + + type CH3_DBG_TCR_t { + CH3_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH3_DBG_TCR_t CH3_DBG_TCR at 0x500008c4; + register uint32 CH3_DBG_TCR_raw at 0x500008c4; + + type CH4_DBG_CTDREQ_t { + CH4_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH4_DBG_CTDREQ_t CH4_DBG_CTDREQ at 0x50000900; + register uint32 CH4_DBG_CTDREQ_raw at 0x50000900; + + type CH4_DBG_TCR_t { + CH4_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH4_DBG_TCR_t CH4_DBG_TCR at 0x50000904; + register uint32 CH4_DBG_TCR_raw at 0x50000904; + + type CH5_DBG_CTDREQ_t { + CH5_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH5_DBG_CTDREQ_t CH5_DBG_CTDREQ at 0x50000940; + register uint32 CH5_DBG_CTDREQ_raw at 0x50000940; + + type CH5_DBG_TCR_t { + CH5_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH5_DBG_TCR_t CH5_DBG_TCR at 0x50000944; + register uint32 CH5_DBG_TCR_raw at 0x50000944; + + type CH6_DBG_CTDREQ_t { + CH6_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH6_DBG_CTDREQ_t CH6_DBG_CTDREQ at 0x50000980; + register uint32 CH6_DBG_CTDREQ_raw at 0x50000980; + + type CH6_DBG_TCR_t { + CH6_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH6_DBG_TCR_t CH6_DBG_TCR at 0x50000984; + register uint32 CH6_DBG_TCR_raw at 0x50000984; + + type CH7_DBG_CTDREQ_t { + CH7_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH7_DBG_CTDREQ_t CH7_DBG_CTDREQ at 0x500009c0; + register uint32 CH7_DBG_CTDREQ_raw at 0x500009c0; + + type CH7_DBG_TCR_t { + CH7_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH7_DBG_TCR_t CH7_DBG_TCR at 0x500009c4; + register uint32 CH7_DBG_TCR_raw at 0x500009c4; + + type CH8_DBG_CTDREQ_t { + CH8_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH8_DBG_CTDREQ_t CH8_DBG_CTDREQ at 0x50000a00; + register uint32 CH8_DBG_CTDREQ_raw at 0x50000a00; + + type CH8_DBG_TCR_t { + CH8_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH8_DBG_TCR_t CH8_DBG_TCR at 0x50000a04; + register uint32 CH8_DBG_TCR_raw at 0x50000a04; + + type CH9_DBG_CTDREQ_t { + CH9_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH9_DBG_CTDREQ_t CH9_DBG_CTDREQ at 0x50000a40; + register uint32 CH9_DBG_CTDREQ_raw at 0x50000a40; + + type CH9_DBG_TCR_t { + CH9_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH9_DBG_TCR_t CH9_DBG_TCR at 0x50000a44; + register uint32 CH9_DBG_TCR_raw at 0x50000a44; + + type CH10_DBG_CTDREQ_t { + CH10_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH10_DBG_CTDREQ_t CH10_DBG_CTDREQ at 0x50000a80; + register uint32 CH10_DBG_CTDREQ_raw at 0x50000a80; + + type CH10_DBG_TCR_t { + CH10_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH10_DBG_TCR_t CH10_DBG_TCR at 0x50000a84; + register uint32 CH10_DBG_TCR_raw at 0x50000a84; + + type CH11_DBG_CTDREQ_t { + CH11_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH11_DBG_CTDREQ_t CH11_DBG_CTDREQ at 0x50000ac0; + register uint32 CH11_DBG_CTDREQ_raw at 0x50000ac0; + + type CH11_DBG_TCR_t { + CH11_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH11_DBG_TCR_t CH11_DBG_TCR at 0x50000ac4; + register uint32 CH11_DBG_TCR_raw at 0x50000ac4; + + +/* Types and registers for TIMER + Controls time and alarms time is a 64 bit value indicating the time in usec since power-on timeh is the top 32 bits of time & timel is the bottom 32 bits to change time write to timelw before timehw to read time read from timelr before timehr An alarm is set by setting alarm_enable and writing to the corresponding alarm register When an alarm is pending, the corresponding alarm_running signal will be high An alarm can be cancelled before it has finished by clearing the alarm_enable When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared To clear the interrupt write a 1 to the corresponding alarm_irq + */ + + type TIMEHW_t { + TIMEHW = uint32(0); // + } + + // Write to bits 63:32 of time always write timelw before timehw + register TIMEHW_t TIMEHW at 0x40054000; + register uint32 TIMEHW_raw at 0x40054000; + + type TIMELW_t { + TIMELW = uint32(0); // + } + + // Write to bits 31:0 of time writes do not get copied to time until timehw is written + register TIMELW_t TIMELW at 0x40054004; + register uint32 TIMELW_raw at 0x40054004; + + type TIMEHR_t { + TIMEHR = uint32(0); // + } + + // Read from bits 63:32 of time always read timelr before timehr + register TIMEHR_t TIMEHR at 0x40054008; + register uint32 TIMEHR_raw at 0x40054008; + + type TIMELR_t { + TIMELR = uint32(0); // + } + + // Read from bits 31:0 of time + register TIMELR_t TIMELR at 0x4005400c; + register uint32 TIMELR_raw at 0x4005400c; + + type ALARM0_t { + ALARM0 = uint32(0); // + } + + // Arm alarm 0, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM0 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. + register ALARM0_t ALARM0 at 0x40054010; + register uint32 ALARM0_raw at 0x40054010; + + type ALARM1_t { + ALARM1 = uint32(0); // + } + + // Arm alarm 1, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM1 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. + register ALARM1_t ALARM1 at 0x40054014; + register uint32 ALARM1_raw at 0x40054014; + + type ALARM2_t { + ALARM2 = uint32(0); // + } + + // Arm alarm 2, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM2 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. + register ALARM2_t ALARM2 at 0x40054018; + register uint32 ALARM2_raw at 0x40054018; + + type ALARM3_t { + ALARM3 = uint32(0); // + } + + // Arm alarm 3, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM3 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. + register ALARM3_t ALARM3 at 0x4005401c; + register uint32 ALARM3_raw at 0x4005401c; + + type ARMED_t { + ARMED = uint4(0); // + _res1 = uint28(0); // Reserved, 28 bits + } + + // Indicates the armed/disarmed status of each alarm. A write to the corresponding ALARMx register arms the alarm. Alarms automatically disarm upon firing, but writing ones here will disarm immediately without waiting to fire. + register ARMED_t ARMED at 0x40054020; + register uint32 ARMED_raw at 0x40054020; + + type TIMERAWH_t { + TIMERAWH = uint32(0); // + } + + // Raw read from bits 63:32 of time (no side effects) + register TIMERAWH_t TIMERAWH at 0x40054024; + register uint32 TIMERAWH_raw at 0x40054024; + + type TIMERAWL_t { + TIMERAWL = uint32(0); // + } + + // Raw read from bits 31:0 of time (no side effects) + register TIMERAWL_t TIMERAWL at 0x40054028; + register uint32 TIMERAWL_raw at 0x40054028; + + type DBGPAUSE_t { + _res1 = false; // Reserved, 1 bits + DBG0 = false; // Pause when processor 0 is in debug mode + DBG1 = false; // Pause when processor 1 is in debug mode + _res2 = uint29(0); // Reserved, 29 bits + } + + // Set bits high to enable pause when the corresponding debug ports are active + register DBGPAUSE_t DBGPAUSE at 0x4005402c; + register uint32 DBGPAUSE_raw at 0x4005402c; + + type PAUSE_t { + PAUSE = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Set high to pause the timer + register PAUSE_t PAUSE at 0x40054030; + register uint32 PAUSE_raw at 0x40054030; + + type TIMER_INTR_t { + ALARM_0 = false; // + ALARM_1 = false; // + ALARM_2 = false; // + ALARM_3 = false; // + _res1 = uint28(0); // Reserved, 28 bits + } + + // Raw Interrupts + register TIMER_INTR_t TIMER_INTR at 0x40054034; + register uint32 TIMER_INTR_raw at 0x40054034; + + type TIMER_INTE_t { + ALARM_0 = false; // + ALARM_1 = false; // + ALARM_2 = false; // + ALARM_3 = false; // + _res1 = uint28(0); // Reserved, 28 bits + } + + // Interrupt Enable + register TIMER_INTE_t TIMER_INTE at 0x40054038; + register uint32 TIMER_INTE_raw at 0x40054038; + + type TIMER_INTF_t { + ALARM_0 = false; // + ALARM_1 = false; // + ALARM_2 = false; // + ALARM_3 = false; // + _res1 = uint28(0); // Reserved, 28 bits + } + + // Interrupt Force + register TIMER_INTF_t TIMER_INTF at 0x4005403c; + register uint32 TIMER_INTF_raw at 0x4005403c; + + type TIMER_INTS_t { + ALARM_0 = false; // + ALARM_1 = false; // + ALARM_2 = false; // + ALARM_3 = false; // + _res1 = uint28(0); // Reserved, 28 bits + } + + // Interrupt status after masking & forcing + register TIMER_INTS_t TIMER_INTS at 0x40054040; + register uint32 TIMER_INTS_raw at 0x40054040; + + +/* Types and registers for PWM + Simple PWM + */ + + enum CH0_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } + + type CH0_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits + } + + // Control and status register + register CH0_CSR_t CH0_CSR at 0x40050000; + register uint32 CH0_CSR_raw at 0x40050000; + + type CH0_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH0_DIV_t CH0_DIV at 0x40050004; + register uint32 CH0_DIV_raw at 0x40050004; + + type CH0_CTR_t { + CH0_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Direct access to the PWM counter + register CH0_CTR_t CH0_CTR at 0x40050008; + register uint32 CH0_CTR_raw at 0x40050008; + + type CH0_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH0_CC_t CH0_CC at 0x4005000c; + register uint32 CH0_CC_raw at 0x4005000c; + + type CH0_TOP_t { + CH0_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Counter wrap value + register CH0_TOP_t CH0_TOP at 0x40050010; + register uint32 CH0_TOP_raw at 0x40050010; + + enum CH1_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } + + type CH1_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits + } + + // Control and status register + register CH1_CSR_t CH1_CSR at 0x40050014; + register uint32 CH1_CSR_raw at 0x40050014; + + type CH1_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH1_DIV_t CH1_DIV at 0x40050018; + register uint32 CH1_DIV_raw at 0x40050018; + + type CH1_CTR_t { + CH1_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Direct access to the PWM counter + register CH1_CTR_t CH1_CTR at 0x4005001c; + register uint32 CH1_CTR_raw at 0x4005001c; + + type CH1_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH1_CC_t CH1_CC at 0x40050020; + register uint32 CH1_CC_raw at 0x40050020; + + type CH1_TOP_t { + CH1_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Counter wrap value + register CH1_TOP_t CH1_TOP at 0x40050024; + register uint32 CH1_TOP_raw at 0x40050024; + + enum CH2_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } + + type CH2_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits + } + + // Control and status register + register CH2_CSR_t CH2_CSR at 0x40050028; + register uint32 CH2_CSR_raw at 0x40050028; + + type CH2_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH2_DIV_t CH2_DIV at 0x4005002c; + register uint32 CH2_DIV_raw at 0x4005002c; + + type CH2_CTR_t { + CH2_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Direct access to the PWM counter + register CH2_CTR_t CH2_CTR at 0x40050030; + register uint32 CH2_CTR_raw at 0x40050030; + + type CH2_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH2_CC_t CH2_CC at 0x40050034; + register uint32 CH2_CC_raw at 0x40050034; + + type CH2_TOP_t { + CH2_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Counter wrap value + register CH2_TOP_t CH2_TOP at 0x40050038; + register uint32 CH2_TOP_raw at 0x40050038; + + enum CH3_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } + + type CH3_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits + } + + // Control and status register + register CH3_CSR_t CH3_CSR at 0x4005003c; + register uint32 CH3_CSR_raw at 0x4005003c; + + type CH3_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH3_DIV_t CH3_DIV at 0x40050040; + register uint32 CH3_DIV_raw at 0x40050040; + + type CH3_CTR_t { + CH3_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Direct access to the PWM counter + register CH3_CTR_t CH3_CTR at 0x40050044; + register uint32 CH3_CTR_raw at 0x40050044; + + type CH3_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH3_CC_t CH3_CC at 0x40050048; + register uint32 CH3_CC_raw at 0x40050048; + + type CH3_TOP_t { + CH3_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Counter wrap value + register CH3_TOP_t CH3_TOP at 0x4005004c; + register uint32 CH3_TOP_raw at 0x4005004c; + + enum CH4_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } + + type CH4_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits + } + + // Control and status register + register CH4_CSR_t CH4_CSR at 0x40050050; + register uint32 CH4_CSR_raw at 0x40050050; + + type CH4_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH4_DIV_t CH4_DIV at 0x40050054; + register uint32 CH4_DIV_raw at 0x40050054; + + type CH4_CTR_t { + CH4_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Direct access to the PWM counter + register CH4_CTR_t CH4_CTR at 0x40050058; + register uint32 CH4_CTR_raw at 0x40050058; + + type CH4_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH4_CC_t CH4_CC at 0x4005005c; + register uint32 CH4_CC_raw at 0x4005005c; + + type CH4_TOP_t { + CH4_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Counter wrap value + register CH4_TOP_t CH4_TOP at 0x40050060; + register uint32 CH4_TOP_raw at 0x40050060; + + enum CH5_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } + + type CH5_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits + } + + // Control and status register + register CH5_CSR_t CH5_CSR at 0x40050064; + register uint32 CH5_CSR_raw at 0x40050064; + + type CH5_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH5_DIV_t CH5_DIV at 0x40050068; + register uint32 CH5_DIV_raw at 0x40050068; + + type CH5_CTR_t { + CH5_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Direct access to the PWM counter + register CH5_CTR_t CH5_CTR at 0x4005006c; + register uint32 CH5_CTR_raw at 0x4005006c; + + type CH5_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH5_CC_t CH5_CC at 0x40050070; + register uint32 CH5_CC_raw at 0x40050070; + + type CH5_TOP_t { + CH5_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Counter wrap value + register CH5_TOP_t CH5_TOP at 0x40050074; + register uint32 CH5_TOP_raw at 0x40050074; + + enum CH6_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } + + type CH6_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits + } + + // Control and status register + register CH6_CSR_t CH6_CSR at 0x40050078; + register uint32 CH6_CSR_raw at 0x40050078; + + type CH6_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH6_DIV_t CH6_DIV at 0x4005007c; + register uint32 CH6_DIV_raw at 0x4005007c; + + type CH6_CTR_t { + CH6_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Direct access to the PWM counter + register CH6_CTR_t CH6_CTR at 0x40050080; + register uint32 CH6_CTR_raw at 0x40050080; + + type CH6_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH6_CC_t CH6_CC at 0x40050084; + register uint32 CH6_CC_raw at 0x40050084; + + type CH6_TOP_t { + CH6_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Counter wrap value + register CH6_TOP_t CH6_TOP at 0x40050088; + register uint32 CH6_TOP_raw at 0x40050088; + + enum CH7_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } + + type CH7_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits + } + + // Control and status register + register CH7_CSR_t CH7_CSR at 0x4005008c; + register uint32 CH7_CSR_raw at 0x4005008c; + + type CH7_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH7_DIV_t CH7_DIV at 0x40050090; + register uint32 CH7_DIV_raw at 0x40050090; + + type CH7_CTR_t { + CH7_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Direct access to the PWM counter + register CH7_CTR_t CH7_CTR at 0x40050094; + register uint32 CH7_CTR_raw at 0x40050094; + + type CH7_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH7_CC_t CH7_CC at 0x40050098; + register uint32 CH7_CC_raw at 0x40050098; + + type CH7_TOP_t { + CH7_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Counter wrap value + register CH7_TOP_t CH7_TOP at 0x4005009c; + register uint32 CH7_TOP_raw at 0x4005009c; + + type EN_t { + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + _res1 = uint24(0); // Reserved, 24 bits + } + + // This register aliases the CSR_EN bits for all channels. Writing to this register allows multiple channels to be enabled or disabled simultaneously, so they can run in perfect sync. For each channel, there is only one physical EN register bit, which can be accessed through here or CHx_CSR. + register EN_t EN at 0x400500a0; + register uint32 EN_raw at 0x400500a0; + + type PWM_INTR_t { + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + _res1 = uint24(0); // Reserved, 24 bits + } + + // Raw Interrupts + register PWM_INTR_t PWM_INTR at 0x400500a4; + register uint32 PWM_INTR_raw at 0x400500a4; + + type PWM_INTE_t { + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + _res1 = uint24(0); // Reserved, 24 bits + } + + // Interrupt Enable + register PWM_INTE_t PWM_INTE at 0x400500a8; + register uint32 PWM_INTE_raw at 0x400500a8; + + type PWM_INTF_t { + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + _res1 = uint24(0); // Reserved, 24 bits + } + + // Interrupt Force + register PWM_INTF_t PWM_INTF at 0x400500ac; + register uint32 PWM_INTF_raw at 0x400500ac; + + type PWM_INTS_t { + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + _res1 = uint24(0); // Reserved, 24 bits + } + + // Interrupt status after masking & forcing + register PWM_INTS_t PWM_INTS at 0x400500b0; + register uint32 PWM_INTS_raw at 0x400500b0; + + +/* Types and registers for ADC + Control and data interface to SAR ADC + */ + + type ADC_CS_t { + EN = false; // Power on ADC and enable its clock. 1 - enabled. 0 - disabled. + TS_EN = false; // Power on temperature sensor. 1 - enabled. 0 - disabled. + START_ONCE = false; // Start a single conversion. Self-clearing. Ignored if start_many is asserted. + START_MANY = false; // Continuously perform conversions whilst this bit is 1. A new conversion will start immediately after the previous finishes. + _res1 = uint4(0); // Reserved, 4 bits + READY = false; // 1 if the ADC is ready to start a new conversion. Implies any previous conversion has completed. 0 whilst conversion in progress. + ERR = false; // The most recent ADC conversion encountered an error; result is undefined or noisy. + ERR_STICKY = false; // Some past ADC conversion encountered an error. Write 1 to clear. + _res2 = false; // Reserved, 1 bits + AINSEL = uint3(0); // Select analog mux input. Updated automatically in round-robin mode. + _res3 = false; // Reserved, 1 bits + RROBIN = uint5(0); // Round-robin sampling. 1 bit per channel. Set all bits to 0 to disable. Otherwise, the ADC will cycle through each enabled channel in a round-robin fashion. The first channel to be sampled will be the one currently indicated by AINSEL. AINSEL will be updated after each conversion with the newly-selected channel. + _res4 = uint11(0); // Reserved, 11 bits + } + + // ADC Control and Status + register ADC_CS_t ADC_CS at 0x4004c000; + register uint32 ADC_CS_raw at 0x4004c000; + + type RESULT_t { + RESULT = uint12(0); // + _res1 = uint20(0); // Reserved, 20 bits + } + + // Result of most recent ADC conversion + register RESULT_t RESULT at 0x4004c004; + register uint32 RESULT_raw at 0x4004c004; + + type FCS_t { + EN = false; // If 1: write result to the FIFO after each conversion. + SHIFT = false; // If 1: FIFO results are right-shifted to be one byte in size. Enables DMA to byte buffers. + ERR = false; // If 1: conversion error bit appears in the FIFO alongside the result + DREQ_EN = false; // If 1: assert DMA requests when FIFO contains data + _res1 = uint4(0); // Reserved, 4 bits + EMPTY = false; // + FULL = false; // + UNDER = false; // 1 if the FIFO has been underflowed. Write 1 to clear. + OVER = false; // 1 if the FIFO has been overflowed. Write 1 to clear. + _res2 = uint4(0); // Reserved, 4 bits + LEVEL = uint4(0); // The number of conversion results currently waiting in the FIFO + _res3 = uint4(0); // Reserved, 4 bits + THRESH = uint4(0); // DREQ/IRQ asserted when level >= threshold + _res4 = uint4(0); // Reserved, 4 bits + } + + // FIFO control and status + register FCS_t FCS at 0x4004c008; + register uint32 FCS_raw at 0x4004c008; + + type FIFO_t { + VAL = uint12(0); // + _res1 = uint3(0); // Reserved, 3 bits + ERR = false; // 1 if this particular sample experienced a conversion error. Remains in the same location if the sample is shifted. + _res2 = uint16(0); // Reserved, 16 bits + } + + // Conversion result FIFO + register FIFO_t FIFO at 0x4004c00c; + register uint32 FIFO_raw at 0x4004c00c; + + type ADC_DIV_t { + FRAC = uint8(0); // Fractional part of clock divisor. First-order delta-sigma. + INT = uint16(0); // Integer part of clock divisor. + _res1 = uint8(0); // Reserved, 8 bits + } + + // Clock divider. If non-zero, CS_START_MANY will start conversions at regular intervals rather than back-to-back. The divider is reset when either of these fields are written. Total period is 1 + INT + FRAC / 256 + register ADC_DIV_t ADC_DIV at 0x4004c010; + register uint32 ADC_DIV_raw at 0x4004c010; + + type ADC_INTR_t { + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + _res1 = uint31(0); // Reserved, 31 bits + } + + // Raw Interrupts + register ADC_INTR_t ADC_INTR at 0x4004c014; + register uint32 ADC_INTR_raw at 0x4004c014; + + type ADC_INTE_t { + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + _res1 = uint31(0); // Reserved, 31 bits + } + + // Interrupt Enable + register ADC_INTE_t ADC_INTE at 0x4004c018; + register uint32 ADC_INTE_raw at 0x4004c018; + + type ADC_INTF_t { + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + _res1 = uint31(0); // Reserved, 31 bits + } + + // Interrupt Force + register ADC_INTF_t ADC_INTF at 0x4004c01c; + register uint32 ADC_INTF_raw at 0x4004c01c; + + type ADC_INTS_t { + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + _res1 = uint31(0); // Reserved, 31 bits + } + + // Interrupt status after masking & forcing + register ADC_INTS_t ADC_INTS at 0x4004c020; + register uint32 ADC_INTS_raw at 0x4004c020; + + +/* Types and registers for I2C0 + DW_apb_i2c address block List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): IC_ULTRA_FAST_MODE ................ 0x0 IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 IC_UFM_SCL_LOW_COUNT .............. 0x0008 IC_UFM_SCL_HIGH_COUNT ............. 0x0006 IC_TX_TL .......................... 0x0 IC_TX_CMD_BLOCK ................... 0x1 IC_HAS_DMA ........................ 0x1 IC_HAS_ASYNC_FIFO ................. 0x0 IC_SMBUS_ARP ...................... 0x0 IC_FIRST_DATA_BYTE_STATUS ......... 0x1 IC_INTR_IO ........................ 0x1 IC_MASTER_MODE .................... 0x1 IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 IC_INTR_POL ....................... 0x1 IC_OPTIONAL_SAR ................... 0x0 IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 IC_DEFAULT_SLAVE_ADDR ............. 0x055 IC_DEFAULT_HS_SPKLEN .............. 0x1 IC_FS_SCL_HIGH_COUNT .............. 0x0006 IC_HS_SCL_LOW_COUNT ............... 0x0008 IC_DEVICE_ID_VALUE ................ 0x0 IC_10BITADDR_MASTER ............... 0x0 IC_CLK_FREQ_OPTIMIZATION .......... 0x0 IC_DEFAULT_FS_SPKLEN .............. 0x7 IC_ADD_ENCODED_PARAMS ............. 0x0 IC_DEFAULT_SDA_HOLD ............... 0x000001 IC_DEFAULT_SDA_SETUP .............. 0x64 IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 IC_CLOCK_PERIOD ................... 100 IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 IC_RESTART_EN ..................... 0x1 IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 IC_BUS_CLEAR_FEATURE .............. 0x0 IC_CAP_LOADING .................... 100 IC_FS_SCL_LOW_COUNT ............... 0x000d APB_DATA_WIDTH .................... 32 IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff IC_SLV_DATA_NACK_ONLY ............. 0x1 IC_10BITADDR_SLAVE ................ 0x0 IC_CLK_TYPE ....................... 0x0 IC_SMBUS_UDID_MSB ................. 0x0 IC_SMBUS_SUSPEND_ALERT ............ 0x0 IC_HS_SCL_HIGH_COUNT .............. 0x0006 IC_SLV_RESTART_DET_EN ............. 0x1 IC_SMBUS .......................... 0x0 IC_OPTIONAL_SAR_DEFAULT ........... 0x0 IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 IC_USE_COUNTS ..................... 0x0 IC_RX_BUFFER_DEPTH ................ 16 IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff IC_RX_FULL_HLD_BUS_EN ............. 0x1 IC_SLAVE_DISABLE .................. 0x1 IC_RX_TL .......................... 0x0 IC_DEVICE_ID ...................... 0x0 IC_HC_COUNT_VALUES ................ 0x0 I2C_DYNAMIC_TAR_UPDATE ............ 0 IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff IC_HS_MASTER_CODE ................. 0x1 IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff IC_SS_SCL_HIGH_COUNT .............. 0x0028 IC_SS_SCL_LOW_COUNT ............... 0x002f IC_MAX_SPEED_MODE ................. 0x2 IC_STAT_FOR_CLK_STRETCH ........... 0x0 IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 IC_DEFAULT_UFM_SPKLEN ............. 0x1 IC_TX_BUFFER_DEPTH ................ 16 + */ + + enum IC_CON_RX_FIFO_FULL_HLD_CTRL { + DISABLED = 0, // Overflow when RX_FIFO is full + ENABLED = 1 // Hold bus when RX_FIFO is full + } + + enum IC_CON_TX_EMPTY_CTRL { + DISABLED = 0, // Default behaviour of TX_EMPTY interrupt + ENABLED = 1 // Controlled generation of TX_EMPTY interrupt + } + + enum IC_CON_STOP_DET_IFADDRESSED { + DISABLED = 0, // slave issues STOP_DET intr always + ENABLED = 1 // slave issues STOP_DET intr only if addressed + } + + enum IC_CON_IC_SLAVE_DISABLE { + SLAVE_ENABLED = 0, // Slave mode is enabled + SLAVE_DISABLED = 1 // Slave mode is disabled + } + + enum IC_CON_IC_RESTART_EN { + DISABLED = 0, // Master restart disabled + ENABLED = 1 // Master restart enabled + } + + enum IC_CON_IC_10BITADDR_MASTER { + ADDR_7BITS = 0, // Master 7Bit addressing mode + ADDR_10BITS = 1 // Master 10Bit addressing mode + } + + enum IC_CON_IC_10BITADDR_SLAVE { + ADDR_7BITS = 0, // Slave 7Bit addressing + ADDR_10BITS = 1 // Slave 10Bit addressing + } + + enum IC_CON_SPEED { + STANDARD = 1, // Standard Speed mode of operation + FAST = 2, // Fast or Fast Plus mode of operation + HIGH = 3 // High Speed mode of operation + } + + enum IC_CON_MASTER_MODE { + DISABLED = 0, // Master mode is disabled + ENABLED = 1 // Master mode is enabled + } + + type IC_CON_t { + MASTER_MODE = false; // This bit controls whether the DW_apb_i2c master is enabled. NOTE: Software should ensure that if this bit is written with '1' then bit 6 should also be written with a '1'. + SPEED = uint2(0); // These bits control at which speed the DW_apb_i2c operates; its setting is relevant only if one is operating the DW_apb_i2c in master mode. Hardware protects against illegal values being programmed by software. These bits must be programmed appropriately for slave mode also, as it is used to capture correct value of spike filter as per the speed mode. This register should be programmed only with a value in the range of 1 to IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of IC_MAX_SPEED_MODE. 1: standard mode (100 kbit/s) 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s) 3: high speed mode (3.4 Mbit/s) Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 + IC_10BITADDR_SLAVE = false; // When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c responds to only 10-bit addressing transfers that match the full 10 bits of the IC_SAR register. + IC_10BITADDR_MASTER = false; // Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing + IC_RESTART_EN = false; // Determines whether RESTART conditions may be sent when acting as a master. Some older slaves do not support handling RESTART conditions; however, RESTART conditions are used in several DW_apb_i2c operations. When RESTART is disabled, the master is prohibited from performing the following functions: - Sending a START BYTE - Performing any high-speed mode operation - High-speed mode operation - Performing direction changes in combined format mode - Performing a read operation with a 10-bit address By replacing RESTART condition followed by a STOP and a subsequent START condition, split operations are broken down into multiple DW_apb_i2c transfers. If the above operations are performed, it will result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. Reset value: ENABLED + IC_SLAVE_DISABLE = false; // This bit controls whether I2C has its slave disabled, which means once the presetn signal is applied, then this bit is set and the slave is disabled. If this bit is set (slave is disabled), DW_apb_i2c functions only as a master and does not perform any action that requires a slave. NOTE: Software should ensure that if this bit is written with 0, then bit 0 should also be written with a 0. + STOP_DET_IFADDRESSED = false; // In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset value: 0x0 NOTE: During a general call address, this slave does not issue the STOP_DET interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). + TX_EMPTY_CTRL = false; // This bit controls the generation of the TX_EMPTY interrupt, as described in the IC_RAW_INTR_STAT register. Reset value: 0x0. + RX_FIFO_FULL_HLD_CTRL = false; // This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is physically full to its RX_BUFFER_DEPTH, as described in the IC_RX_FULL_HLD_BUS_EN parameter. Reset value: 0x0. + STOP_DET_IF_MASTER_ACTIVE = false; // Master issues the STOP_DET interrupt irrespective of whether master is active or not + _res1 = uint21(0); // Reserved, 21 bits + } + + // I2C0 I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only. + register IC_CON_t I2C0_IC_CON at 0x40044000; + register uint32 I2C0_IC_CON_raw at 0x40044000; + + enum IC_TAR_SPECIAL { + DISABLED = 0, // Disables programming of GENERAL_CALL or START_BYTE transmission + ENABLED = 1 // Enables programming of GENERAL_CALL or START_BYTE transmission + } + + enum IC_TAR_GC_OR_START { + GENERAL_CALL = 0, // GENERAL_CALL byte transmission + START_BYTE = 1 // START byte transmission + } + + type IC_TAR_t { + IC_TAR = uint10(0); // This is the target address for any master transaction. When transmitting a General Call, these bits are ignored. To generate a START BYTE, the CPU needs to write only once into these bits. If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared between master and slave, so full loopback is not feasible. Only one direction loopback mode is supported (simplex), not duplex. A master cannot transmit to itself; it can transmit to only a slave. + GC_OR_START = false; // If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit indicates whether a General Call or START byte command is to be performed by the DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only writes may be performed. Attempting to issue a read command results in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START BYTE Reset value: 0x0 + SPECIAL = false; // This bit indicates whether software performs a Device-ID or General Call or START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: perform special I2C command as specified in Device_ID or GC_OR_START bit Reset value: 0x0 + _res1 = uint20(0); // Reserved, 20 bits + } + + // I2C0 I2C Target Address Register This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0. Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only. + register IC_TAR_t I2C0_IC_TAR at 0x40044004; + register uint32 I2C0_IC_TAR_raw at 0x40044004; + + type IC_SAR_t { + IC_SAR = uint10(0); // The IC_SAR holds the slave address when the I2C is operating as a slave. For 7-bit addressing, only IC_SAR[6:0] is used. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. Note: The default values cannot be any of the reserved address locations: that is, 0x00 to 0x07, or 0x78 to 0x7f. The correct operation of the device is not guaranteed if you program the IC_SAR or IC_TAR to a reserved value. Refer to <> for a complete list of these reserved values. + _res1 = uint22(0); // Reserved, 22 bits + } + + // I2C0 I2C Slave Address Register + register IC_SAR_t I2C0_IC_SAR at 0x40044008; + register uint32 I2C0_IC_SAR_raw at 0x40044008; + + enum IC_DATA_CMD_FIRST_DATA_BYTE { + INACTIVE = 0, // Sequential data byte received + ACTIVE = 1 // Non sequential data byte received + } + + enum IC_DATA_CMD_RESTART { + DISABLE = 0, // Don't Issue RESTART before this command + ENABLE = 1 // Issue RESTART before this command + } + + enum IC_DATA_CMD_STOP { + DISABLE = 0, // Don't Issue STOP after this command + ENABLE = 1 // Issue STOP after this command + } + + enum IC_DATA_CMD_CMD { + WRITE = 0, // Master Write Command + READ = 1 // Master Read Command + } + + type IC_DATA_CMD_t { + DAT = uint8(0); // This register contains the data to be transmitted or received on the I2C bus. If you are writing to this register and want to perform a read, bits 7:0 (DAT) are ignored by the DW_apb_i2c. However, when you read this register, these bits return the value of data received on the DW_apb_i2c interface. Reset value: 0x0 + CMD = false; // This bit controls whether a read or a write is performed. This bit does not control the direction when the DW_apb_i2con acts as a slave. It controls only the direction when it acts as a master. When a command is entered in the TX FIFO, this bit distinguishes the write and read commands. In slave-receiver mode, this bit is a 'don't care' because writes to this register are not required. In slave-transmitter mode, a '0' indicates that the data in IC_DATA_CMD is to be transmitted. When programming this bit, you should remember the following: attempting to perform a read operation after a General Call command has been sent results in a TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs. Reset value: 0x0 + STOP = false; // This bit controls whether a STOP is issued after the byte is sent or received. - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master immediately tries to start a new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master continues the current transfer by sending/receiving data bytes according to the value of the CMD bit. If the Tx FIFO is empty, the master holds the SCL line low and stalls the bus until a new command is available in the Tx FIFO. Reset value: 0x0 + RESTART = false; // This bit controls whether a RESTART is issued before the byte is sent or received. 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received (according to the value of CMD), regardless of whether or not the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. Reset value: 0x0 + FIRST_DATA_BYTE = false; // Indicates the first data byte received after the address phase for receive transfer in Master receiver or Slave receiver mode. Reset value : 0x0 NOTE: In case of APB_DATA_WIDTH=8, 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status on 11 bit. 2. In order to read the 11 bit, the user has to perform the first data byte read [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in order to know the status of 11 bit (whether the data received in previous read is a first data byte or not). 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] (offset 0x11) if not interested in FIRST_DATA_BYTE status. + _res1 = uint20(0); // Reserved, 20 bits + } + + // I2C0 I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO. The size of the register changes as follows: Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging. + register IC_DATA_CMD_t I2C0_IC_DATA_CMD at 0x40044010; + register uint32 I2C0_IC_DATA_CMD_raw at 0x40044010; + + type IC_SS_SCL_HCNT_t { + IC_SS_SCL_HCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration'. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. NOTE: This register must not be programmed to a value higher than 65525, because DW_apb_i2c uses a 16-bit counter to flag an I2C bus idle condition when this counter reaches a value of IC_SS_SCL_HCNT + 10. + _res1 = uint16(0); // Reserved, 16 bits + } + + // I2C0 Standard Speed I2C Clock SCL High Count Register + register IC_SS_SCL_HCNT_t I2C0_IC_SS_SCL_HCNT at 0x40044014; + register uint32 I2C0_IC_SS_SCL_HCNT_raw at 0x40044014; + + type IC_SS_SCL_LCNT_t { + IC_SS_SCL_LCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration' This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 8; hardware prevents values less than this being written, and if attempted, results in 8 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of DW_apb_i2c. The lower byte must be programmed first, and then the upper byte is programmed. + _res1 = uint16(0); // Reserved, 16 bits + } + + // I2C0 Standard Speed I2C Clock SCL Low Count Register + register IC_SS_SCL_LCNT_t I2C0_IC_SS_SCL_LCNT at 0x40044018; + register uint32 I2C0_IC_SS_SCL_LCNT_raw at 0x40044018; + + type IC_FS_SCL_HCNT_t { + IC_FS_SCL_HCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for fast mode or fast mode plus. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH == 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. + _res1 = uint16(0); // Reserved, 16 bits + } + + // I2C0 Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register + register IC_FS_SCL_HCNT_t I2C0_IC_FS_SCL_HCNT at 0x4004401c; + register uint32 I2C0_IC_FS_SCL_HCNT_raw at 0x4004401c; + + type IC_FS_SCL_LCNT_t { + IC_FS_SCL_LCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for fast speed. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 8; hardware prevents values less than this being written, and if attempted results in 8 being set. For designs with APB_DATA_WIDTH = 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. If the value is less than 8 then the count value gets changed to 8. + _res1 = uint16(0); // Reserved, 16 bits + } + + // I2C0 Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register + register IC_FS_SCL_LCNT_t I2C0_IC_FS_SCL_LCNT at 0x40044020; + register uint32 I2C0_IC_FS_SCL_LCNT_raw at 0x40044020; + + enum IC_INTR_STAT_R_RESTART_DET { + INACTIVE = 0, // R_RESTART_DET interrupt is inactive + ACTIVE = 1 // R_RESTART_DET interrupt is active + } + + enum IC_INTR_STAT_R_GEN_CALL { + INACTIVE = 0, // R_GEN_CALL interrupt is inactive + ACTIVE = 1 // R_GEN_CALL interrupt is active + } + + enum IC_INTR_STAT_R_START_DET { + INACTIVE = 0, // R_START_DET interrupt is inactive + ACTIVE = 1 // R_START_DET interrupt is active + } + + enum IC_INTR_STAT_R_STOP_DET { + INACTIVE = 0, // R_STOP_DET interrupt is inactive + ACTIVE = 1 // R_STOP_DET interrupt is active + } + + enum IC_INTR_STAT_R_ACTIVITY { + INACTIVE = 0, // R_ACTIVITY interrupt is inactive + ACTIVE = 1 // R_ACTIVITY interrupt is active + } + + enum IC_INTR_STAT_R_RX_DONE { + INACTIVE = 0, // R_RX_DONE interrupt is inactive + ACTIVE = 1 // R_RX_DONE interrupt is active + } + + enum IC_INTR_STAT_R_TX_ABRT { + INACTIVE = 0, // R_TX_ABRT interrupt is inactive + ACTIVE = 1 // R_TX_ABRT interrupt is active + } + + enum IC_INTR_STAT_R_RD_REQ { + INACTIVE = 0, // R_RD_REQ interrupt is inactive + ACTIVE = 1 // R_RD_REQ interrupt is active + } + + enum IC_INTR_STAT_R_TX_EMPTY { + INACTIVE = 0, // R_TX_EMPTY interrupt is inactive + ACTIVE = 1 // R_TX_EMPTY interrupt is active + } + + enum IC_INTR_STAT_R_TX_OVER { + INACTIVE = 0, // R_TX_OVER interrupt is inactive + ACTIVE = 1 // R_TX_OVER interrupt is active + } + + enum IC_INTR_STAT_R_RX_FULL { + INACTIVE = 0, // R_RX_FULL interrupt is inactive + ACTIVE = 1 // R_RX_FULL interrupt is active + } + + enum IC_INTR_STAT_R_RX_OVER { + INACTIVE = 0, // R_RX_OVER interrupt is inactive + ACTIVE = 1 // R_RX_OVER interrupt is active + } + + enum IC_INTR_STAT_R_RX_UNDER { + INACTIVE = 0, // RX_UNDER interrupt is inactive + ACTIVE = 1 // RX_UNDER interrupt is active + } + + type IC_INTR_STAT_t { + R_RX_UNDER = false; // See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit. Reset value: 0x0 + R_RX_OVER = false; // See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit. Reset value: 0x0 + R_RX_FULL = false; // See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit. Reset value: 0x0 + R_TX_OVER = false; // See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit. Reset value: 0x0 + R_TX_EMPTY = false; // See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit. Reset value: 0x0 + R_RD_REQ = false; // See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit. Reset value: 0x0 + R_TX_ABRT = false; // See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit. Reset value: 0x0 + R_RX_DONE = false; // See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit. Reset value: 0x0 + R_ACTIVITY = false; // See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit. Reset value: 0x0 + R_STOP_DET = false; // See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit. Reset value: 0x0 + R_START_DET = false; // See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit. Reset value: 0x0 + R_GEN_CALL = false; // See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit. Reset value: 0x0 + R_RESTART_DET = false; // See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit. Reset value: 0x0 + _res1 = uint19(0); // Reserved, 19 bits + } + + // I2C0 I2C Interrupt Status Register Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. + register IC_INTR_STAT_t I2C0_IC_INTR_STAT at 0x4004402c; + register uint32 I2C0_IC_INTR_STAT_raw at 0x4004402c; + + enum IC_INTR_MASK_M_RESTART_DET { + ENABLED = 0, // RESTART_DET interrupt is masked + DISABLED = 1 // RESTART_DET interrupt is unmasked + } + + enum IC_INTR_MASK_M_GEN_CALL { + ENABLED = 0, // GEN_CALL interrupt is masked + DISABLED = 1 // GEN_CALL interrupt is unmasked + } + + enum IC_INTR_MASK_M_START_DET { + ENABLED = 0, // START_DET interrupt is masked + DISABLED = 1 // START_DET interrupt is unmasked + } + + enum IC_INTR_MASK_M_STOP_DET { + ENABLED = 0, // STOP_DET interrupt is masked + DISABLED = 1 // STOP_DET interrupt is unmasked + } + + enum IC_INTR_MASK_M_ACTIVITY { + ENABLED = 0, // ACTIVITY interrupt is masked + DISABLED = 1 // ACTIVITY interrupt is unmasked + } + + enum IC_INTR_MASK_M_RX_DONE { + ENABLED = 0, // RX_DONE interrupt is masked + DISABLED = 1 // RX_DONE interrupt is unmasked + } + + enum IC_INTR_MASK_M_TX_ABRT { + ENABLED = 0, // TX_ABORT interrupt is masked + DISABLED = 1 // TX_ABORT interrupt is unmasked + } + + enum IC_INTR_MASK_M_RD_REQ { + ENABLED = 0, // RD_REQ interrupt is masked + DISABLED = 1 // RD_REQ interrupt is unmasked + } + + enum IC_INTR_MASK_M_TX_EMPTY { + ENABLED = 0, // TX_EMPTY interrupt is masked + DISABLED = 1 // TX_EMPTY interrupt is unmasked + } + + enum IC_INTR_MASK_M_TX_OVER { + ENABLED = 0, // TX_OVER interrupt is masked + DISABLED = 1 // TX_OVER interrupt is unmasked + } + + enum IC_INTR_MASK_M_RX_FULL { + ENABLED = 0, // RX_FULL interrupt is masked + DISABLED = 1 // RX_FULL interrupt is unmasked + } + + enum IC_INTR_MASK_M_RX_OVER { + ENABLED = 0, // RX_OVER interrupt is masked + DISABLED = 1 // RX_OVER interrupt is unmasked + } + + enum IC_INTR_MASK_M_RX_UNDER { + ENABLED = 0, // RX_UNDER interrupt is masked + DISABLED = 1 // RX_UNDER interrupt is unmasked + } + + type IC_INTR_MASK_t { + M_RX_UNDER = false; // This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RX_OVER = false; // This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RX_FULL = false; // This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_TX_OVER = false; // This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_TX_EMPTY = false; // This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RD_REQ = false; // This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_TX_ABRT = false; // This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RX_DONE = false; // This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_ACTIVITY = false; // This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register. Reset value: 0x0 + M_STOP_DET = false; // This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 + M_START_DET = false; // This bit masks the R_START_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 + M_GEN_CALL = false; // This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RESTART_DET = false; // This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 + _res1 = uint19(0); // Reserved, 19 bits + } + + // I2C0 I2C Interrupt Mask Register. These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. + register IC_INTR_MASK_t I2C0_IC_INTR_MASK at 0x40044030; + register uint32 I2C0_IC_INTR_MASK_raw at 0x40044030; + + enum IC_RAW_INTR_STAT_RESTART_DET { + INACTIVE = 0, // RESTART_DET interrupt is inactive + ACTIVE = 1 // RESTART_DET interrupt is active + } + + enum IC_RAW_INTR_STAT_GEN_CALL { + INACTIVE = 0, // GEN_CALL interrupt is inactive + ACTIVE = 1 // GEN_CALL interrupt is active + } + + enum IC_RAW_INTR_STAT_START_DET { + INACTIVE = 0, // START_DET interrupt is inactive + ACTIVE = 1 // START_DET interrupt is active + } + + enum IC_RAW_INTR_STAT_STOP_DET { + INACTIVE = 0, // STOP_DET interrupt is inactive + ACTIVE = 1 // STOP_DET interrupt is active + } + + enum IC_RAW_INTR_STAT_ACTIVITY { + INACTIVE = 0, // RAW_INTR_ACTIVITY interrupt is inactive + ACTIVE = 1 // RAW_INTR_ACTIVITY interrupt is active + } + + enum IC_RAW_INTR_STAT_RX_DONE { + INACTIVE = 0, // RX_DONE interrupt is inactive + ACTIVE = 1 // RX_DONE interrupt is active + } + + enum IC_RAW_INTR_STAT_TX_ABRT { + INACTIVE = 0, // TX_ABRT interrupt is inactive + ACTIVE = 1 // TX_ABRT interrupt is active + } + + enum IC_RAW_INTR_STAT_RD_REQ { + INACTIVE = 0, // RD_REQ interrupt is inactive + ACTIVE = 1 // RD_REQ interrupt is active + } + + enum IC_RAW_INTR_STAT_TX_EMPTY { + INACTIVE = 0, // TX_EMPTY interrupt is inactive + ACTIVE = 1 // TX_EMPTY interrupt is active + } + + enum IC_RAW_INTR_STAT_TX_OVER { + INACTIVE = 0, // TX_OVER interrupt is inactive + ACTIVE = 1 // TX_OVER interrupt is active + } + + enum IC_RAW_INTR_STAT_RX_FULL { + INACTIVE = 0, // RX_FULL interrupt is inactive + ACTIVE = 1 // RX_FULL interrupt is active + } + + enum IC_RAW_INTR_STAT_RX_OVER { + INACTIVE = 0, // RX_OVER interrupt is inactive + ACTIVE = 1 // RX_OVER interrupt is active + } + + enum IC_RAW_INTR_STAT_RX_UNDER { + INACTIVE = 0, // RX_UNDER interrupt is inactive + ACTIVE = 1 // RX_UNDER interrupt is active + } + + type IC_RAW_INTR_STAT_t { + RX_UNDER = false; // Set if the processor attempts to read the receive buffer when it is empty by reading from the IC_DATA_CMD register. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. Reset value: 0x0 + RX_OVER = false; // Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an additional byte is received from an external I2C device. The DW_apb_i2c acknowledges this, but any data bytes received after the FIFO is full are lost. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never overflows. Reset value: 0x0 + RX_FULL = false; // Set when the receive buffer reaches or goes above the RX_TL threshold in the IC_RX_TL register. It is automatically cleared by hardware when buffer level goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of the activity that continues. Reset value: 0x0 + TX_OVER = false; // Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and the processor attempts to issue another I2C command by writing to the IC_DATA_CMD register. When the module is disabled, this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. Reset value: 0x0 + TX_EMPTY = false; // The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register and the transmission of the address/data from the internal shift register for the most recently popped command is completed. It is automatically cleared by hardware when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no data within it, so this bit is set to 1, provided there is activity in the master or slave state machines. When there is no longer any activity, then with ic_en=0, this bit is set to 0. Reset value: 0x0. + RD_REQ = false; // This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in a wait state (SCL=0) until this interrupt is serviced, which means that the slave has been addressed by a remote master that is asking for data to be transferred. The processor must respond to this interrupt and then write the requested data to the IC_DATA_CMD register. This bit is set to 0 just after the processor reads the IC_CLR_RD_REQ register. Reset value: 0x0 + TX_ABRT = false; // This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete the intended actions on the contents of the transmit FIFO. This situation can occur both as an I2C master or an I2C slave, and is referred to as a 'transmit abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the reason why the transmit abort takes places. Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever there is a transmit abort caused by any of the events tracked by the IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is then ready to accept more data bytes from the APB interface. Reset value: 0x0 + RX_DONE = false; // When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if the master does not acknowledge a transmitted byte. This occurs on the last byte of the transmission, indicating that the transmission is done. Reset value: 0x0 + ACTIVITY = false; // This bit captures DW_apb_i2c activity and stays set until it is cleared. There are four ways to clear it: - Disabling the DW_apb_i2c - Reading the IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once this bit is set, it stays set unless one of the four methods is used to clear it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, indicating that there was activity on the bus. Reset value: 0x0 + STOP_DET = false; // Indicates whether a STOP condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET interrupt will be issued only if slave is addressed. Note: During a general call address, this slave does not issue a STOP_DET interrupt if STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt will be issued irrespective of whether master is active or not. Reset value: 0x0 + START_DET = false; // Indicates whether a START or RESTART condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. Reset value: 0x0 + GEN_CALL = false; // Set only when a General Call address is received and it is acknowledged. It stays set until it is cleared either by disabling DW_apb_i2c or when the CPU reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data in the Rx buffer. Reset value: 0x0 + RESTART_DET = false; // Indicates whether a RESTART condition has occurred on the I2C interface when DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled only when IC_SLV_RESTART_DET_EN=1. Note: However, in high-speed mode or during a START BYTE transfer, the RESTART comes before the address field as per the I2C protocol. In this case, the slave is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does not generate the RESTART_DET interrupt. Reset value: 0x0 + _res1 = uint19(0); // Reserved, 19 bits + } + + // I2C0 I2C Raw Interrupt Status Register Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c. + register IC_RAW_INTR_STAT_t I2C0_IC_RAW_INTR_STAT at 0x40044034; + register uint32 I2C0_IC_RAW_INTR_STAT_raw at 0x40044034; + + type IC_RX_TL_t { + RX_TL = uint8(0); // Receive FIFO Threshold Level. Controls the level of entries (or above) that triggers the RX_FULL interrupt (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that hardware does not allow this value to be set to a value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. + _res1 = uint24(0); // Reserved, 24 bits + } + + // I2C0 I2C Receive FIFO Threshold Register + register IC_RX_TL_t I2C0_IC_RX_TL at 0x40044038; + register uint32 I2C0_IC_RX_TL_raw at 0x40044038; + + type IC_TX_TL_t { + TX_TL = uint8(0); // Transmit FIFO Threshold Level. Controls the level of entries (or below) that trigger the TX_EMPTY interrupt (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that it may not be set to value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and a value of 255 sets the threshold for 255 entries. + _res1 = uint24(0); // Reserved, 24 bits + } + + // I2C0 I2C Transmit FIFO Threshold Register + register IC_TX_TL_t I2C0_IC_TX_TL at 0x4004403c; + register uint32 I2C0_IC_TX_TL_raw at 0x4004403c; + + type IC_CLR_INTR_t { + CLR_INTR = false; // Read this register to clear the combined interrupt, all individual interrupts, and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable interrupts but software clearable interrupts. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear Combined and Individual Interrupt Register + register IC_CLR_INTR_t I2C0_IC_CLR_INTR at 0x40044040; + register uint32 I2C0_IC_CLR_INTR_raw at 0x40044040; + + type IC_CLR_RX_UNDER_t { + CLR_RX_UNDER = false; // Read this register to clear the RX_UNDER interrupt (bit 0) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear RX_UNDER Interrupt Register + register IC_CLR_RX_UNDER_t I2C0_IC_CLR_RX_UNDER at 0x40044044; + register uint32 I2C0_IC_CLR_RX_UNDER_raw at 0x40044044; + + type IC_CLR_RX_OVER_t { + CLR_RX_OVER = false; // Read this register to clear the RX_OVER interrupt (bit 1) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear RX_OVER Interrupt Register + register IC_CLR_RX_OVER_t I2C0_IC_CLR_RX_OVER at 0x40044048; + register uint32 I2C0_IC_CLR_RX_OVER_raw at 0x40044048; + + type IC_CLR_TX_OVER_t { + CLR_TX_OVER = false; // Read this register to clear the TX_OVER interrupt (bit 3) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear TX_OVER Interrupt Register + register IC_CLR_TX_OVER_t I2C0_IC_CLR_TX_OVER at 0x4004404c; + register uint32 I2C0_IC_CLR_TX_OVER_raw at 0x4004404c; + + type IC_CLR_RD_REQ_t { + CLR_RD_REQ = false; // Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear RD_REQ Interrupt Register + register IC_CLR_RD_REQ_t I2C0_IC_CLR_RD_REQ at 0x40044050; + register uint32 I2C0_IC_CLR_RD_REQ_raw at 0x40044050; + + type IC_CLR_TX_ABRT_t { + CLR_TX_ABRT = false; // Read this register to clear the TX_ABRT interrupt (bit 6) of the IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also releases the TX FIFO from the flushed/reset state, allowing more writes to the TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear TX_ABRT Interrupt Register + register IC_CLR_TX_ABRT_t I2C0_IC_CLR_TX_ABRT at 0x40044054; + register uint32 I2C0_IC_CLR_TX_ABRT_raw at 0x40044054; + + type IC_CLR_RX_DONE_t { + CLR_RX_DONE = false; // Read this register to clear the RX_DONE interrupt (bit 7) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear RX_DONE Interrupt Register + register IC_CLR_RX_DONE_t I2C0_IC_CLR_RX_DONE at 0x40044058; + register uint32 I2C0_IC_CLR_RX_DONE_raw at 0x40044058; + + type IC_CLR_ACTIVITY_t { + CLR_ACTIVITY = false; // Reading this register clears the ACTIVITY interrupt if the I2C is not active anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt bit continues to be set. It is automatically cleared by hardware if the module is disabled and if there is no further activity on the bus. The value read from this register to get status of the ACTIVITY interrupt (bit 8) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear ACTIVITY Interrupt Register + register IC_CLR_ACTIVITY_t I2C0_IC_CLR_ACTIVITY at 0x4004405c; + register uint32 I2C0_IC_CLR_ACTIVITY_raw at 0x4004405c; + + type IC_CLR_STOP_DET_t { + CLR_STOP_DET = false; // Read this register to clear the STOP_DET interrupt (bit 9) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear STOP_DET Interrupt Register + register IC_CLR_STOP_DET_t I2C0_IC_CLR_STOP_DET at 0x40044060; + register uint32 I2C0_IC_CLR_STOP_DET_raw at 0x40044060; + + type IC_CLR_START_DET_t { + CLR_START_DET = false; // Read this register to clear the START_DET interrupt (bit 10) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear START_DET Interrupt Register + register IC_CLR_START_DET_t I2C0_IC_CLR_START_DET at 0x40044064; + register uint32 I2C0_IC_CLR_START_DET_raw at 0x40044064; + + type IC_CLR_GEN_CALL_t { + CLR_GEN_CALL = false; // Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear GEN_CALL Interrupt Register + register IC_CLR_GEN_CALL_t I2C0_IC_CLR_GEN_CALL at 0x40044068; + register uint32 I2C0_IC_CLR_GEN_CALL_raw at 0x40044068; + + enum IC_ENABLE_TX_CMD_BLOCK { + NOT_BLOCKED = 0, // Tx Command execution not blocked + BLOCKED = 1 // Tx Command execution blocked + } + + enum IC_ENABLE_ABORT { + DISABLE = 0, // ABORT operation not in progress + ENABLED = 1 // ABORT operation in progress + } + + enum IC_ENABLE_ENABLE { + DISABLED = 0, // I2C is disabled + ENABLED = 1 // I2C is enabled + } + + type IC_ENABLE_t { + ENABLE = false; // Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable DW_apb_i2c while it is active. However, it is important that care be taken to ensure that DW_apb_i2c is disabled properly. A recommended procedure is described in 'Disabling DW_apb_i2c'. When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get flushed. - Status bits in the IC_INTR_STAT register are still active until DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well as deletes the contents of the transmit buffer after the current transfer is complete. If the module is receiving, the DW_apb_i2c stops the current transfer at the end of the current byte and does not acknowledge the transfer. In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to asynchronous (1), there is a two ic_clk delay when enabling or disabling the DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to 'Disabling DW_apb_i2c' Reset value: 0x0 + ABORT = false; // When set, the controller initiates the transfer abort. - 0: ABORT not initiated or ABORT done - 1: ABORT operation in progress The software can abort the I2C transfer in master mode by setting this bit. The software can set this bit only when ENABLE is already set; otherwise, the controller ignores any write to ABORT bit. The software cannot clear the ABORT bit once set. In response to an ABORT, the controller issues a STOP and flushes the Tx FIFO after completing the current transfer, then sets the TX_ABORT interrupt after the abort operation. The ABORT bit is cleared automatically after the abort operation. For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C Transfers'. Reset value: 0x0 + TX_CMD_BLOCK = false; // In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus automatically, as soon as the first data is available in the Tx FIFO. Note: To block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT + _res1 = uint29(0); // Reserved, 29 bits + } + + // I2C0 I2C Enable Register + register IC_ENABLE_t I2C0_IC_ENABLE at 0x4004406c; + register uint32 I2C0_IC_ENABLE_raw at 0x4004406c; + + enum IC_STATUS_SLV_ACTIVITY { + IDLE = 0, // Slave is idle + ACTIVE = 1 // Slave not idle + } + + enum IC_STATUS_MST_ACTIVITY { + IDLE = 0, // Master is idle + ACTIVE = 1 // Master not idle + } + + enum IC_STATUS_RFF { + NOT_FULL = 0, // Rx FIFO not full + FULL = 1 // Rx FIFO is full + } + + enum IC_STATUS_RFNE { + EMPTY = 0, // Rx FIFO is empty + NOT_EMPTY = 1 // Rx FIFO not empty + } + + enum IC_STATUS_TFE { + NON_EMPTY = 0, // Tx FIFO not empty + EMPTY = 1 // Tx FIFO is empty + } + + enum IC_STATUS_TFNF { + FULL = 0, // Tx FIFO is full + NOT_FULL = 1 // Tx FIFO not full + } + + enum IC_STATUS_ACTIVITY { + INACTIVE = 0, // I2C is idle + ACTIVE = 1 // I2C is active + } + + type IC_STATUS_t { + ACTIVITY = false; // I2C Activity Status. Reset value: 0x0 + TFNF = false; // Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: Transmit FIFO is not full Reset value: 0x1 + TFE = false; // Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this bit is set. When it contains one or more valid entries, this bit is cleared. This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - 1: Transmit FIFO is empty Reset value: 0x1 + RFNE = false; // Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is empty - 1: Receive FIFO is not empty Reset value: 0x0 + RFF = false; // Receive FIFO Completely Full. When the receive FIFO is completely full, this bit is set. When the receive FIFO contains one or more empty location, this bit is cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: 0x0 + MST_ACTIVITY = false; // Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is the OR of SLV_ACTIVITY and MST_ACTIVITY bits. Reset value: 0x0 + SLV_ACTIVITY = false; // Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the Slave part of DW_apb_i2c is Active Reset value: 0x0 + _res1 = uint25(0); // Reserved, 25 bits + } + + // I2C0 I2C Status Register This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt. When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 + register IC_STATUS_t I2C0_IC_STATUS at 0x40044070; + register uint32 I2C0_IC_STATUS_raw at 0x40044070; + + type IC_TXFLR_t { + TXFLR = uint5(0); // Transmit FIFO Level. Contains the number of valid data entries in the transmit FIFO. Reset value: 0x0 + _res1 = uint27(0); // Reserved, 27 bits + } + + // I2C0 I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO. + register IC_TXFLR_t I2C0_IC_TXFLR at 0x40044074; + register uint32 I2C0_IC_TXFLR_raw at 0x40044074; + + type IC_RXFLR_t { + RXFLR = uint5(0); // Receive FIFO Level. Contains the number of valid data entries in the receive FIFO. Reset value: 0x0 + _res1 = uint27(0); // Reserved, 27 bits + } + + // I2C0 I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO. + register IC_RXFLR_t I2C0_IC_RXFLR at 0x40044078; + register uint32 I2C0_IC_RXFLR_raw at 0x40044078; + + type IC_SDA_HOLD_t { + IC_SDA_TX_HOLD = uint16(0); // Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a transmitter. Reset value: IC_DEFAULT_SDA_HOLD[15:0]. + IC_SDA_RX_HOLD = uint8(0); // Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a receiver. Reset value: IC_DEFAULT_SDA_HOLD[23:16]. + _res1 = uint8(0); // Reserved, 8 bits + } + + // I2C0 I2C SDA Hold Time Length Register The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW). The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode. Writes to this register succeed only when IC_ENABLE[0]=0. The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented. The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles. + register IC_SDA_HOLD_t I2C0_IC_SDA_HOLD at 0x4004407c; + register uint32 I2C0_IC_SDA_HOLD_raw at 0x4004407c; + + enum IC_TX_ABRT_SOURCE_ABRT_USER_ABRT { + ABRT_USER_ABRT_VOID = 0, // Transfer abort detected by master- scenario not present + ABRT_USER_ABRT_GENERATED = 1 // Transfer abort detected by master + } + + enum IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX { + ABRT_SLVRD_INTX_VOID = 0, // Slave trying to transmit to remote master in read mode- scenario not present + ABRT_SLVRD_INTX_GENERATED = 1 // Slave trying to transmit to remote master in read mode + } + + enum IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST { + ABRT_SLV_ARBLOST_VOID = 0, // Slave lost arbitration to remote master- scenario not present + ABRT_SLV_ARBLOST_GENERATED = 1 // Slave lost arbitration to remote master + } + + enum IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO { + ABRT_SLVFLUSH_TXFIFO_VOID = 0, // Slave flushes existing data in TX-FIFO upon getting read command- scenario not present + ABRT_SLVFLUSH_TXFIFO_GENERATED = 1 // Slave flushes existing data in TX-FIFO upon getting read command + } + + enum IC_TX_ABRT_SOURCE_ARB_LOST { + ABRT_LOST_VOID = 0, // Master or Slave-Transmitter lost arbitration- scenario not present + ABRT_LOST_GENERATED = 1 // Master or Slave-Transmitter lost arbitration + } + + enum IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS { + ABRT_MASTER_DIS_VOID = 0, // User initiating master operation when MASTER disabled- scenario not present + ABRT_MASTER_DIS_GENERATED = 1 // User initiating master operation when MASTER disabled + } + + enum IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT { + ABRT_10B_RD_VOID = 0, // Master not trying to read in 10Bit addressing mode when RESTART disabled + ABRT_10B_RD_GENERATED = 1 // Master trying to read in 10Bit addressing mode when RESTART disabled + } + + enum IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT { + ABRT_SBYTE_NORSTRT_VOID = 0, // User trying to send START byte when RESTART disabled- scenario not present + ABRT_SBYTE_NORSTRT_GENERATED = 1 // User trying to send START byte when RESTART disabled + } + + enum IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT { + ABRT_HS_NORSTRT_VOID = 0, // User trying to switch Master to HS mode when RESTART disabled- scenario not present + ABRT_HS_NORSTRT_GENERATED = 1 // User trying to switch Master to HS mode when RESTART disabled + } + + enum IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET { + ABRT_SBYTE_ACKDET_VOID = 0, // ACK detected for START byte- scenario not present + ABRT_SBYTE_ACKDET_GENERATED = 1 // ACK detected for START byte + } + + enum IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET { + ABRT_HS_ACK_VOID = 0, // HS Master code ACKed in HS Mode- scenario not present + ABRT_HS_ACK_GENERATED = 1 // HS Master code ACKed in HS Mode + } + + enum IC_TX_ABRT_SOURCE_ABRT_GCALL_READ { + ABRT_GCALL_READ_VOID = 0, // GCALL is followed by read from bus-scenario not present + ABRT_GCALL_READ_GENERATED = 1 // GCALL is followed by read from bus + } + + enum IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK { + ABRT_GCALL_NOACK_VOID = 0, // GCALL not ACKed by any slave-scenario not present + ABRT_GCALL_NOACK_GENERATED = 1 // GCALL not ACKed by any slave + } + + enum IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK { + ABRT_TXDATA_NOACK_VOID = 0, // Transmitted data non-ACKed by addressed slave-scenario not present + ABRT_TXDATA_NOACK_GENERATED = 1 // Transmitted data not ACKed by addressed slave + } + + enum IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK { + INACTIVE = 0, // This abort is not generated + ACTIVE = 1 // Byte 2 of 10Bit Address not ACKed by any slave + } + + enum IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK { + INACTIVE = 0, // This abort is not generated + ACTIVE = 1 // Byte 1 of 10Bit Address not ACKed by any slave + } + + enum IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK { + INACTIVE = 0, // This abort is not generated + ACTIVE = 1 // This abort is generated because of NOACK for 7-bit address + } + + type IC_TX_ABRT_SOURCE_t { + ABRT_7B_ADDR_NOACK = false; // This field indicates that the Master is in 7-bit addressing mode and the address sent was not acknowledged by any slave. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_10ADDR1_NOACK = false; // This field indicates that the Master is in 10-bit address mode and the first 10-bit address byte was not acknowledged by any slave. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_10ADDR2_NOACK = false; // This field indicates that the Master is in 10-bit address mode and that the second address byte of the 10-bit address was not acknowledged by any slave. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_TXDATA_NOACK = false; // This field indicates the master-mode only bit. When the master receives an acknowledgement for the address, but when it sends data byte(s) following the address, it did not receive an acknowledge from the remote slave(s). Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter + ABRT_GCALL_NOACK = false; // This field indicates that DW_apb_i2c in master mode has sent a General Call and no slave on the bus acknowledged the General Call. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter + ABRT_GCALL_READ = false; // This field indicates that DW_apb_i2c in the master mode has sent a General Call but the user programmed the byte following the General Call to be a read from the bus (IC_DATA_CMD[9] is set to 1). Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter + ABRT_HS_ACKDET = false; // This field indicates that the Master is in High Speed mode and the High Speed Master code was acknowledged (wrong behavior). Reset value: 0x0 Role of DW_apb_i2c: Master + ABRT_SBYTE_ACKDET = false; // This field indicates that the Master has sent a START Byte and the START Byte was acknowledged (wrong behavior). Reset value: 0x0 Role of DW_apb_i2c: Master + ABRT_HS_NORSTRT = false; // This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to use the master to transfer data in High Speed mode. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_SBYTE_NORSTRT = false; // To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 clears for one cycle and then gets reasserted. When this field is set to 1, the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to send a START Byte. Reset value: 0x0 Role of DW_apb_i2c: Master + ABRT_10B_RD_NORSTRT = false; // This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the master sends a read command in 10-bit addressing mode. Reset value: 0x0 Role of DW_apb_i2c: Master-Receiver + ABRT_MASTER_DIS = false; // This field indicates that the User tries to initiate a Master operation with the Master mode disabled. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ARB_LOST = false; // This field specifies that the Master has lost arbitration, or if IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost arbitration. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + ABRT_SLVFLUSH_TXFIFO = false; // This field specifies that the Slave has received a read command and some data exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data in TX FIFO. Reset value: 0x0 Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLV_ARBLOST = false; // This field indicates that a Slave has lost the bus while transmitting data to a remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though the slave never 'owns' the bus, something could go wrong on the bus. This is a fail safe check. For instance, during a data transmission at the low-to-high transition of SCL, if what is on the data bus is not what is supposed to be transmitted, then DW_apb_i2c no longer own the bus. Reset value: 0x0 Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLVRD_INTX = false; // 1: When the processor side responds to a slave mode request for data to be transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD register. Reset value: 0x0 Role of DW_apb_i2c: Slave-Transmitter + ABRT_USER_ABRT = false; // This is a master-mode-only bit. Master has detected the transfer abort (IC_ENABLE[1]) Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter + _res1 = uint6(0); // Reserved, 6 bits + TX_FLUSH_CNT = uint9(0); // This field indicates the number of Tx FIFO Data Commands which are flushed due to TX_ABRT interrupt. It is cleared whenever I2C is disabled. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + } + + // I2C0 I2C Transmit Abort Source Register This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted. + register IC_TX_ABRT_SOURCE_t I2C0_IC_TX_ABRT_SOURCE at 0x40044080; + register uint32 I2C0_IC_TX_ABRT_SOURCE_raw at 0x40044080; + + enum IC_SLV_DATA_NACK_ONLY_NACK { + DISABLED = 0, // Slave receiver generates NACK normally + ENABLED = 1 // Slave receiver generates NACK upon data reception only + } + + type IC_SLV_DATA_NACK_ONLY_t { + NACK = false; // Generate NACK. This NACK generation only occurs when DW_apb_i2c is a slave-receiver. If this register is set to a value of 1, it can only generate a NACK after a data byte is received; hence, the data transfer is aborted and the data received is not pushed to the receive buffer. When the register is set to a value of 0, it generates NACK/ACK, depending on normal criteria. - 1: generate NACK after data byte received - 0: generate NACK/ACK normally Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Generate Slave Data NACK Register The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect. A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit. + register IC_SLV_DATA_NACK_ONLY_t I2C0_IC_SLV_DATA_NACK_ONLY at 0x40044084; + register uint32 I2C0_IC_SLV_DATA_NACK_ONLY_raw at 0x40044084; + + enum IC_DMA_CR_TDMAE { + DISABLED = 0, // transmit FIFO DMA channel disabled + ENABLED = 1 // Transmit FIFO DMA channel enabled + } + + enum IC_DMA_CR_RDMAE { + DISABLED = 0, // Receive FIFO DMA channel disabled + ENABLED = 1 // Receive FIFO DMA channel enabled + } + + type IC_DMA_CR_t { + RDMAE = false; // Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. Reset value: 0x0 + TDMAE = false; // Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. Reset value: 0x0 + _res1 = uint30(0); // Reserved, 30 bits + } + + // I2C0 DMA Control Register The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE. + register IC_DMA_CR_t I2C0_IC_DMA_CR at 0x40044088; + register uint32 I2C0_IC_DMA_CR_raw at 0x40044088; + + type IC_DMA_TDLR_t { + DMATDL = uint4(0); // Transmit Data Level. This bit field controls the level at which a DMA request is made by the transmit logic. It is equal to the watermark level; that is, the dma_tx_req signal is generated when the number of valid data entries in the transmit FIFO is equal to or below this field value, and TDMAE = 1. Reset value: 0x0 + _res1 = uint28(0); // Reserved, 28 bits + } + + // I2C0 DMA Transmit Data Level Register + register IC_DMA_TDLR_t I2C0_IC_DMA_TDLR at 0x4004408c; + register uint32 I2C0_IC_DMA_TDLR_raw at 0x4004408c; + + type IC_DMA_RDLR_t { + DMARDL = uint4(0); // Receive Data Level. This bit field controls the level at which a DMA request is made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req is generated when the number of valid data entries in the receive FIFO is equal to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is 0, then dma_rx_req is asserted when 1 or more data entries are present in the receive FIFO. Reset value: 0x0 + _res1 = uint28(0); // Reserved, 28 bits + } + + // I2C0 I2C Receive Data Level Register + register IC_DMA_RDLR_t I2C0_IC_DMA_RDLR at 0x40044090; + register uint32 I2C0_IC_DMA_RDLR_raw at 0x40044090; + + type IC_SDA_SETUP_t { + SDA_SETUP = uint8(0); // SDA Setup. It is recommended that if the required delay is 1000ns, then for an ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. IC_SDA_SETUP must be programmed with a minimum value of 2. + _res1 = uint24(0); // Reserved, 24 bits + } + + // I2C0 I2C SDA Setup Register This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2. Writes to this register succeed only when IC_ENABLE[0] = 0. Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter. + register IC_SDA_SETUP_t I2C0_IC_SDA_SETUP at 0x40044094; + register uint32 I2C0_IC_SDA_SETUP_raw at 0x40044094; + + enum IC_ACK_GENERAL_CALL_ACK_GEN_CALL { + DISABLED = 0, // Generate NACK for a General Call + ENABLED = 1 // Generate ACK for a General Call + } + + type IC_ACK_GENERAL_CALL_t { + ACK_GEN_CALL = false; // ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with a NACK (by negating ic_data_oe). + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 I2C ACK General Call Register The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address. This register is applicable only when the DW_apb_i2c is in slave mode. + register IC_ACK_GENERAL_CALL_t I2C0_IC_ACK_GENERAL_CALL at 0x40044098; + register uint32 I2C0_IC_ACK_GENERAL_CALL_raw at 0x40044098; + + enum IC_ENABLE_STATUS_SLV_RX_DATA_LOST { + INACTIVE = 0, // Slave RX Data is not lost + ACTIVE = 1 // Slave RX Data is lost + } + + enum IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY { + INACTIVE = 0, // Slave is disabled when it is idle + ACTIVE = 1 // Slave is disabled when it is active + } + + enum IC_ENABLE_STATUS_IC_EN { + DISABLED = 0, // I2C disabled + ENABLED = 1 // I2C enabled + } + + type IC_ENABLE_STATUS_t { + IC_EN = false; // ic_en Status. This bit always reflects the value driven on the output port ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely read this bit anytime. When this bit is read as 0, the CPU can safely read SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1). Reset value: 0x0 + SLV_DISABLED_WHILE_BUSY = false; // Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential or active Slave operation has been aborted due to the setting bit 0 of the IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the IC_ENABLE register while: (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation from a remote master; OR, (b) address and data bytes of the Slave-Receiver operation from a remote master. When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an I2C transfer, irrespective of whether the I2C address matches the slave address set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before IC_ENABLE is set to 0 but has not taken effect. Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit will also be set to 1. When read as 0, DW_apb_i2c is deemed to have been disabled when there is master activity, or when the I2C bus is idle. Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. Reset value: 0x0 + SLV_RX_DATA_LOST = false; // Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has been aborted with at least one data byte received from an I2C transfer due to the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed to have been actively engaged in an aborted I2C transfer (with matching address) and the data phase of the I2C transfer has been entered, even though a data byte has been responded with a NACK. Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit is also set to 1. When read as 0, DW_apb_i2c is deemed to have been disabled without being actively involved in the data phase of a Slave-Receiver transfer. Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. Reset value: 0x0 + _res1 = uint29(0); // Reserved, 29 bits + } + + // I2C0 I2C Enable Status Register The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled. If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1. If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'. Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities. + register IC_ENABLE_STATUS_t I2C0_IC_ENABLE_STATUS at 0x4004409c; + register uint32 I2C0_IC_ENABLE_STATUS_raw at 0x4004409c; + + type IC_FS_SPKLEN_t { + IC_FS_SPKLEN = uint8(0); // This register must be set before any I2C bus transaction can take place to ensure stable operation. This register sets the duration, measured in ic_clk cycles, of the longest spike in the SCL or SDA lines that will be filtered out by the spike suppression logic. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 1; hardware prevents values less than this being written, and if attempted results in 1 being set. or more information, refer to 'Spike Suppression'. + _res1 = uint24(0); // Reserved, 24 bits + } + + // I2C0 I2C SS, FS or FM+ spike suppression limit This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1. + register IC_FS_SPKLEN_t I2C0_IC_FS_SPKLEN at 0x400440a0; + register uint32 I2C0_IC_FS_SPKLEN_raw at 0x400440a0; + + type IC_CLR_RESTART_DET_t { + CLR_RESTART_DET = false; // Read this register to clear the RESTART_DET interrupt (bit 12) of IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits + } + + // I2C0 Clear RESTART_DET Interrupt Register + register IC_CLR_RESTART_DET_t I2C0_IC_CLR_RESTART_DET at 0x400440a8; + register uint32 I2C0_IC_CLR_RESTART_DET_raw at 0x400440a8; + + type IC_COMP_PARAM_1_t { + APB_DATA_WIDTH = uint2(0); // APB data bus width is 32 bits + MAX_SPEED_MODE = uint2(0); // MAX SPEED MODE = FAST MODE + HC_COUNT_VALUES = false; // Programmable count values for each mode. + INTR_IO = false; // COMBINED Interrupt outputs + HAS_DMA = false; // DMA handshaking signals are enabled + ADD_ENCODED_PARAMS = false; // Encoded parameters not visible + RX_BUFFER_DEPTH = uint8(0); // RX Buffer Depth = 16 + TX_BUFFER_DEPTH = uint8(0); // TX Buffer Depth = 16 + _res1 = uint8(0); // Reserved, 8 bits + } + + // I2C0 Component Parameter Register 1 Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters + register IC_COMP_PARAM_1_t I2C0_IC_COMP_PARAM_1 at 0x400440f4; + register uint32 I2C0_IC_COMP_PARAM_1_raw at 0x400440f4; + + type IC_COMP_VERSION_t { + IC_COMP_VERSION = uint32(0); // + } + + // I2C0 I2C Component Version Register + register IC_COMP_VERSION_t I2C0_IC_COMP_VERSION at 0x400440f8; + register uint32 I2C0_IC_COMP_VERSION_raw at 0x400440f8; + + type IC_COMP_TYPE_t { + IC_COMP_TYPE = uint32(0); // Designware Component Type number = 0x44_57_01_40. This assigned unique hex value is constant and is derived from the two ASCII letters 'DW' followed by a 16-bit unsigned number. + } + + // I2C0 I2C Component Type Register + register IC_COMP_TYPE_t I2C0_IC_COMP_TYPE at 0x400440fc; + register uint32 I2C0_IC_COMP_TYPE_raw at 0x400440fc; + + +/* Types and registers for I2C1 */ + + // I2C1 I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only. + register IC_CON_t I2C1_IC_CON at 0x40048000; + register uint32 I2C1_IC_CON_raw at 0x40048000; + + // I2C1 I2C Target Address Register This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0. Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only. + register IC_TAR_t I2C1_IC_TAR at 0x40048004; + register uint32 I2C1_IC_TAR_raw at 0x40048004; + + // I2C1 I2C Slave Address Register + register IC_SAR_t I2C1_IC_SAR at 0x40048008; + register uint32 I2C1_IC_SAR_raw at 0x40048008; + + // I2C1 I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO. The size of the register changes as follows: Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging. + register IC_DATA_CMD_t I2C1_IC_DATA_CMD at 0x40048010; + register uint32 I2C1_IC_DATA_CMD_raw at 0x40048010; + + // I2C1 Standard Speed I2C Clock SCL High Count Register + register IC_SS_SCL_HCNT_t I2C1_IC_SS_SCL_HCNT at 0x40048014; + register uint32 I2C1_IC_SS_SCL_HCNT_raw at 0x40048014; + + // I2C1 Standard Speed I2C Clock SCL Low Count Register + register IC_SS_SCL_LCNT_t I2C1_IC_SS_SCL_LCNT at 0x40048018; + register uint32 I2C1_IC_SS_SCL_LCNT_raw at 0x40048018; + + // I2C1 Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register + register IC_FS_SCL_HCNT_t I2C1_IC_FS_SCL_HCNT at 0x4004801c; + register uint32 I2C1_IC_FS_SCL_HCNT_raw at 0x4004801c; + + // I2C1 Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register + register IC_FS_SCL_LCNT_t I2C1_IC_FS_SCL_LCNT at 0x40048020; + register uint32 I2C1_IC_FS_SCL_LCNT_raw at 0x40048020; + + // I2C1 I2C Interrupt Status Register Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. + register IC_INTR_STAT_t I2C1_IC_INTR_STAT at 0x4004802c; + register uint32 I2C1_IC_INTR_STAT_raw at 0x4004802c; + + // I2C1 I2C Interrupt Mask Register. These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. + register IC_INTR_MASK_t I2C1_IC_INTR_MASK at 0x40048030; + register uint32 I2C1_IC_INTR_MASK_raw at 0x40048030; + + // I2C1 I2C Raw Interrupt Status Register Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c. + register IC_RAW_INTR_STAT_t I2C1_IC_RAW_INTR_STAT at 0x40048034; + register uint32 I2C1_IC_RAW_INTR_STAT_raw at 0x40048034; + + // I2C1 I2C Receive FIFO Threshold Register + register IC_RX_TL_t I2C1_IC_RX_TL at 0x40048038; + register uint32 I2C1_IC_RX_TL_raw at 0x40048038; + + // I2C1 I2C Transmit FIFO Threshold Register + register IC_TX_TL_t I2C1_IC_TX_TL at 0x4004803c; + register uint32 I2C1_IC_TX_TL_raw at 0x4004803c; + + // I2C1 Clear Combined and Individual Interrupt Register + register IC_CLR_INTR_t I2C1_IC_CLR_INTR at 0x40048040; + register uint32 I2C1_IC_CLR_INTR_raw at 0x40048040; + + // I2C1 Clear RX_UNDER Interrupt Register + register IC_CLR_RX_UNDER_t I2C1_IC_CLR_RX_UNDER at 0x40048044; + register uint32 I2C1_IC_CLR_RX_UNDER_raw at 0x40048044; + + // I2C1 Clear RX_OVER Interrupt Register + register IC_CLR_RX_OVER_t I2C1_IC_CLR_RX_OVER at 0x40048048; + register uint32 I2C1_IC_CLR_RX_OVER_raw at 0x40048048; + + // I2C1 Clear TX_OVER Interrupt Register + register IC_CLR_TX_OVER_t I2C1_IC_CLR_TX_OVER at 0x4004804c; + register uint32 I2C1_IC_CLR_TX_OVER_raw at 0x4004804c; + + // I2C1 Clear RD_REQ Interrupt Register + register IC_CLR_RD_REQ_t I2C1_IC_CLR_RD_REQ at 0x40048050; + register uint32 I2C1_IC_CLR_RD_REQ_raw at 0x40048050; + + // I2C1 Clear TX_ABRT Interrupt Register + register IC_CLR_TX_ABRT_t I2C1_IC_CLR_TX_ABRT at 0x40048054; + register uint32 I2C1_IC_CLR_TX_ABRT_raw at 0x40048054; + + // I2C1 Clear RX_DONE Interrupt Register + register IC_CLR_RX_DONE_t I2C1_IC_CLR_RX_DONE at 0x40048058; + register uint32 I2C1_IC_CLR_RX_DONE_raw at 0x40048058; + + // I2C1 Clear ACTIVITY Interrupt Register + register IC_CLR_ACTIVITY_t I2C1_IC_CLR_ACTIVITY at 0x4004805c; + register uint32 I2C1_IC_CLR_ACTIVITY_raw at 0x4004805c; + + // I2C1 Clear STOP_DET Interrupt Register + register IC_CLR_STOP_DET_t I2C1_IC_CLR_STOP_DET at 0x40048060; + register uint32 I2C1_IC_CLR_STOP_DET_raw at 0x40048060; + + // I2C1 Clear START_DET Interrupt Register + register IC_CLR_START_DET_t I2C1_IC_CLR_START_DET at 0x40048064; + register uint32 I2C1_IC_CLR_START_DET_raw at 0x40048064; + + // I2C1 Clear GEN_CALL Interrupt Register + register IC_CLR_GEN_CALL_t I2C1_IC_CLR_GEN_CALL at 0x40048068; + register uint32 I2C1_IC_CLR_GEN_CALL_raw at 0x40048068; + + // I2C1 I2C Enable Register + register IC_ENABLE_t I2C1_IC_ENABLE at 0x4004806c; + register uint32 I2C1_IC_ENABLE_raw at 0x4004806c; + + // I2C1 I2C Status Register This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt. When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 + register IC_STATUS_t I2C1_IC_STATUS at 0x40048070; + register uint32 I2C1_IC_STATUS_raw at 0x40048070; + + // I2C1 I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO. + register IC_TXFLR_t I2C1_IC_TXFLR at 0x40048074; + register uint32 I2C1_IC_TXFLR_raw at 0x40048074; + + // I2C1 I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO. + register IC_RXFLR_t I2C1_IC_RXFLR at 0x40048078; + register uint32 I2C1_IC_RXFLR_raw at 0x40048078; + + // I2C1 I2C SDA Hold Time Length Register The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW). The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode. Writes to this register succeed only when IC_ENABLE[0]=0. The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented. The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles. + register IC_SDA_HOLD_t I2C1_IC_SDA_HOLD at 0x4004807c; + register uint32 I2C1_IC_SDA_HOLD_raw at 0x4004807c; + + // I2C1 I2C Transmit Abort Source Register This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted. + register IC_TX_ABRT_SOURCE_t I2C1_IC_TX_ABRT_SOURCE at 0x40048080; + register uint32 I2C1_IC_TX_ABRT_SOURCE_raw at 0x40048080; + + // I2C1 Generate Slave Data NACK Register The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect. A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit. + register IC_SLV_DATA_NACK_ONLY_t I2C1_IC_SLV_DATA_NACK_ONLY at 0x40048084; + register uint32 I2C1_IC_SLV_DATA_NACK_ONLY_raw at 0x40048084; + + // I2C1 DMA Control Register The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE. + register IC_DMA_CR_t I2C1_IC_DMA_CR at 0x40048088; + register uint32 I2C1_IC_DMA_CR_raw at 0x40048088; + + // I2C1 DMA Transmit Data Level Register + register IC_DMA_TDLR_t I2C1_IC_DMA_TDLR at 0x4004808c; + register uint32 I2C1_IC_DMA_TDLR_raw at 0x4004808c; + + // I2C1 I2C Receive Data Level Register + register IC_DMA_RDLR_t I2C1_IC_DMA_RDLR at 0x40048090; + register uint32 I2C1_IC_DMA_RDLR_raw at 0x40048090; + + // I2C1 I2C SDA Setup Register This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2. Writes to this register succeed only when IC_ENABLE[0] = 0. Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter. + register IC_SDA_SETUP_t I2C1_IC_SDA_SETUP at 0x40048094; + register uint32 I2C1_IC_SDA_SETUP_raw at 0x40048094; + + // I2C1 I2C ACK General Call Register The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address. This register is applicable only when the DW_apb_i2c is in slave mode. + register IC_ACK_GENERAL_CALL_t I2C1_IC_ACK_GENERAL_CALL at 0x40048098; + register uint32 I2C1_IC_ACK_GENERAL_CALL_raw at 0x40048098; + + // I2C1 I2C Enable Status Register The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled. If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1. If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'. Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities. + register IC_ENABLE_STATUS_t I2C1_IC_ENABLE_STATUS at 0x4004809c; + register uint32 I2C1_IC_ENABLE_STATUS_raw at 0x4004809c; + + // I2C1 I2C SS, FS or FM+ spike suppression limit This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1. + register IC_FS_SPKLEN_t I2C1_IC_FS_SPKLEN at 0x400480a0; + register uint32 I2C1_IC_FS_SPKLEN_raw at 0x400480a0; + + // I2C1 Clear RESTART_DET Interrupt Register + register IC_CLR_RESTART_DET_t I2C1_IC_CLR_RESTART_DET at 0x400480a8; + register uint32 I2C1_IC_CLR_RESTART_DET_raw at 0x400480a8; + + // I2C1 Component Parameter Register 1 Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters + register IC_COMP_PARAM_1_t I2C1_IC_COMP_PARAM_1 at 0x400480f4; + register uint32 I2C1_IC_COMP_PARAM_1_raw at 0x400480f4; + + // I2C1 I2C Component Version Register + register IC_COMP_VERSION_t I2C1_IC_COMP_VERSION at 0x400480f8; + register uint32 I2C1_IC_COMP_VERSION_raw at 0x400480f8; + + // I2C1 I2C Component Type Register + register IC_COMP_TYPE_t I2C1_IC_COMP_TYPE at 0x400480fc; + register uint32 I2C1_IC_COMP_TYPE_raw at 0x400480fc; + + +/* Types and registers for SPI0 */ + + type SSPCR0_t { + DSS = uint4(0); // Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. 1110 15-bit data. 1111 16-bit data. + FRF = uint2(0); // Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame format. 10 National Microwire frame format. 11 Reserved, undefined operation. + SPO = false; // SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + SPH = false; // SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + SCR = uint8(0); // Serial clock rate. The value SCR is used to generate the transmit and receive bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and SCR is a value from 0-255. + _res1 = uint16(0); // Reserved, 16 bits + } + + // SPI0 Control register 0, SSPCR0 on page 3-4 + register SSPCR0_t SPI0_SSPCR0 at 0x4003c000; + register uint32 SPI0_SSPCR0_raw at 0x4003c000; + + type SSPCR1_t { + LBM = false; // Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit serial shifter is connected to input of receive serial shifter internally. + SSE = false; // Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation enabled. + MS = false; // Master or slave mode select. This bit can be modified only when the PrimeCell SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device configured as slave. + SOD = false; // Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast a message to all slaves in the system while ensuring that only one slave drives data onto its serial output line. In such systems the RXD lines from multiple slaves could be tied together. To operate in such systems, the SOD bit can be set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD output in slave mode. + _res1 = uint28(0); // Reserved, 28 bits + } + + // SPI0 Control register 1, SSPCR1 on page 3-5 + register SSPCR1_t SPI0_SSPCR1 at 0x4003c004; + register uint32 SPI0_SSPCR1_raw at 0x4003c004; + + type SSPDR_t { + DATA = uint16(0); // Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must right-justify data when the PrimeCell SSP is programmed for a data size that is less than 16 bits. Unused bits at the top are ignored by transmit logic. The receive logic automatically right-justifies. + _res1 = uint16(0); // Reserved, 16 bits + } + + // SPI0 Data register, SSPDR on page 3-6 + register SSPDR_t SPI0_SSPDR at 0x4003c008; + register uint32 SPI0_SSPDR_raw at 0x4003c008; + + type SSPSR_t { + TFE = false; // Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. + TNF = false; // Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not full. + RNE = false; // Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not empty. + RFF = false; // Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. + BSY = false; // PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting and/or receiving a frame or the transmit FIFO is not empty. + _res1 = uint27(0); // Reserved, 27 bits + } + + // SPI0 Status register, SSPSR on page 3-7 + register SSPSR_t SPI0_SSPSR at 0x4003c00c; + register uint32 SPI0_SSPSR_raw at 0x4003c00c; + + type SSPCPSR_t { + CPSDVSR = uint8(0); // Clock prescale divisor. Must be an even number from 2-254, depending on the frequency of SSPCLK. The least significant bit always returns zero on reads. + _res1 = uint24(0); // Reserved, 24 bits + } + + // SPI0 Clock prescale register, SSPCPSR on page 3-8 + register SSPCPSR_t SPI0_SSPCPSR at 0x4003c010; + register uint32 SPI0_SSPCPSR_raw at 0x4003c010; + + type SSPIMSC_t { + RORIM = false; // Receive overrun interrupt mask: 0 Receive FIFO written to while full condition interrupt is masked. 1 Receive FIFO written to while full condition interrupt is not masked. + RTIM = false; // Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior to timeout period interrupt is not masked. + RXIM = false; // Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not masked. + TXIM = false; // Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is not masked. + _res1 = uint28(0); // Reserved, 28 bits + } + + // SPI0 Interrupt mask set or clear register, SSPIMSC on page 3-9 + register SSPIMSC_t SPI0_SSPIMSC at 0x4003c014; + register uint32 SPI0_SSPIMSC_raw at 0x4003c014; + + type SSPRIS_t { + RORRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt + RTRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt + RXRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt + TXRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt + _res1 = uint28(0); // Reserved, 28 bits + } + + // SPI0 Raw interrupt status register, SSPRIS on page 3-10 + register SSPRIS_t SPI0_SSPRIS at 0x4003c018; + register uint32 SPI0_SSPRIS_raw at 0x4003c018; + + type SSPMIS_t { + RORMIS = false; // Gives the receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt + RTMIS = false; // Gives the receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt + RXMIS = false; // Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt + TXMIS = false; // Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt + _res1 = uint28(0); // Reserved, 28 bits + } + + // SPI0 Masked interrupt status register, SSPMIS on page 3-11 + register SSPMIS_t SPI0_SSPMIS at 0x4003c01c; + register uint32 SPI0_SSPMIS_raw at 0x4003c01c; + + type SSPICR_t { + RORIC = false; // Clears the SSPRORINTR interrupt + RTIC = false; // Clears the SSPRTINTR interrupt + _res1 = uint30(0); // Reserved, 30 bits + } + + // SPI0 Interrupt clear register, SSPICR on page 3-11 + register SSPICR_t SPI0_SSPICR at 0x4003c020; + register uint32 SPI0_SSPICR_raw at 0x4003c020; + + type SSPDMACR_t { + RXDMAE = false; // Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is enabled. + TXDMAE = false; // Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + _res1 = uint30(0); // Reserved, 30 bits + } + + // SPI0 DMA control register, SSPDMACR on page 3-12 + register SSPDMACR_t SPI0_SSPDMACR at 0x4003c024; + register uint32 SPI0_SSPDMACR_raw at 0x4003c024; + + type SSPPERIPHID0_t { + PARTNUMBER0 = uint8(0); // These bits read back as 0x22 + _res1 = uint24(0); // Reserved, 24 bits + } + + // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID0_t SPI0_SSPPERIPHID0 at 0x4003cfe0; + register uint32 SPI0_SSPPERIPHID0_raw at 0x4003cfe0; + + type SSPPERIPHID1_t { + PARTNUMBER1 = uint4(0); // These bits read back as 0x0 + DESIGNER0 = uint4(0); // These bits read back as 0x1 + _res1 = uint24(0); // Reserved, 24 bits + } + + // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID1_t SPI0_SSPPERIPHID1 at 0x4003cfe4; + register uint32 SPI0_SSPPERIPHID1_raw at 0x4003cfe4; + + type SSPPERIPHID2_t { + DESIGNER1 = uint4(0); // These bits read back as 0x4 + REVISION = uint4(0); // These bits return the peripheral revision + _res1 = uint24(0); // Reserved, 24 bits + } + + // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID2_t SPI0_SSPPERIPHID2 at 0x4003cfe8; + register uint32 SPI0_SSPPERIPHID2_raw at 0x4003cfe8; + + type SSPPERIPHID3_t { + CONFIGURATION = uint8(0); // These bits read back as 0x00 + _res1 = uint24(0); // Reserved, 24 bits + } + + // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID3_t SPI0_SSPPERIPHID3 at 0x4003cfec; + register uint32 SPI0_SSPPERIPHID3_raw at 0x4003cfec; + + type SSPPCELLID0_t { + SSPPCELLID0 = uint8(0); // These bits read back as 0x0D + _res1 = uint24(0); // Reserved, 24 bits + } + + // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID0_t SPI0_SSPPCELLID0 at 0x4003cff0; + register uint32 SPI0_SSPPCELLID0_raw at 0x4003cff0; + + type SSPPCELLID1_t { + SSPPCELLID1 = uint8(0); // These bits read back as 0xF0 + _res1 = uint24(0); // Reserved, 24 bits + } + + // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID1_t SPI0_SSPPCELLID1 at 0x4003cff4; + register uint32 SPI0_SSPPCELLID1_raw at 0x4003cff4; + + type SSPPCELLID2_t { + SSPPCELLID2 = uint8(0); // These bits read back as 0x05 + _res1 = uint24(0); // Reserved, 24 bits + } + + // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID2_t SPI0_SSPPCELLID2 at 0x4003cff8; + register uint32 SPI0_SSPPCELLID2_raw at 0x4003cff8; + + type SSPPCELLID3_t { + SSPPCELLID3 = uint8(0); // These bits read back as 0xB1 + _res1 = uint24(0); // Reserved, 24 bits + } + + // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID3_t SPI0_SSPPCELLID3 at 0x4003cffc; + register uint32 SPI0_SSPPCELLID3_raw at 0x4003cffc; + + +/* Types and registers for SPI1 */ + + // SPI1 Control register 0, SSPCR0 on page 3-4 + register SSPCR0_t SPI1_SSPCR0 at 0x40040000; + register uint32 SPI1_SSPCR0_raw at 0x40040000; + + // SPI1 Control register 1, SSPCR1 on page 3-5 + register SSPCR1_t SPI1_SSPCR1 at 0x40040004; + register uint32 SPI1_SSPCR1_raw at 0x40040004; + + // SPI1 Data register, SSPDR on page 3-6 + register SSPDR_t SPI1_SSPDR at 0x40040008; + register uint32 SPI1_SSPDR_raw at 0x40040008; + + // SPI1 Status register, SSPSR on page 3-7 + register SSPSR_t SPI1_SSPSR at 0x4004000c; + register uint32 SPI1_SSPSR_raw at 0x4004000c; + + // SPI1 Clock prescale register, SSPCPSR on page 3-8 + register SSPCPSR_t SPI1_SSPCPSR at 0x40040010; + register uint32 SPI1_SSPCPSR_raw at 0x40040010; + + // SPI1 Interrupt mask set or clear register, SSPIMSC on page 3-9 + register SSPIMSC_t SPI1_SSPIMSC at 0x40040014; + register uint32 SPI1_SSPIMSC_raw at 0x40040014; + + // SPI1 Raw interrupt status register, SSPRIS on page 3-10 + register SSPRIS_t SPI1_SSPRIS at 0x40040018; + register uint32 SPI1_SSPRIS_raw at 0x40040018; + + // SPI1 Masked interrupt status register, SSPMIS on page 3-11 + register SSPMIS_t SPI1_SSPMIS at 0x4004001c; + register uint32 SPI1_SSPMIS_raw at 0x4004001c; + + // SPI1 Interrupt clear register, SSPICR on page 3-11 + register SSPICR_t SPI1_SSPICR at 0x40040020; + register uint32 SPI1_SSPICR_raw at 0x40040020; + + // SPI1 DMA control register, SSPDMACR on page 3-12 + register SSPDMACR_t SPI1_SSPDMACR at 0x40040024; + register uint32 SPI1_SSPDMACR_raw at 0x40040024; + + // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID0_t SPI1_SSPPERIPHID0 at 0x40040fe0; + register uint32 SPI1_SSPPERIPHID0_raw at 0x40040fe0; + + // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID1_t SPI1_SSPPERIPHID1 at 0x40040fe4; + register uint32 SPI1_SSPPERIPHID1_raw at 0x40040fe4; + + // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID2_t SPI1_SSPPERIPHID2 at 0x40040fe8; + register uint32 SPI1_SSPPERIPHID2_raw at 0x40040fe8; + + // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID3_t SPI1_SSPPERIPHID3 at 0x40040fec; + register uint32 SPI1_SSPPERIPHID3_raw at 0x40040fec; + + // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID0_t SPI1_SSPPCELLID0 at 0x40040ff0; + register uint32 SPI1_SSPPCELLID0_raw at 0x40040ff0; + + // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID1_t SPI1_SSPPCELLID1 at 0x40040ff4; + register uint32 SPI1_SSPPCELLID1_raw at 0x40040ff4; + + // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID2_t SPI1_SSPPCELLID2 at 0x40040ff8; + register uint32 SPI1_SSPPCELLID2_raw at 0x40040ff8; + + // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID3_t SPI1_SSPPCELLID3 at 0x40040ffc; + register uint32 SPI1_SSPPCELLID3_raw at 0x40040ffc; + + +/* Types and registers for PIO0 + Programmable IO block + */ + + type PIO0_CTRL_t { + SM_ENABLE = uint4(0); // Enable/disable each of the four state machines by writing 1/0 to each of these four bits. When disabled, a state machine will cease executing instructions, except those written directly to SMx_INSTR by the system. Multiple bits can be set/cleared at once to run/halt multiple state machines simultaneously. + SM_RESTART = uint4(0); // Write 1 to instantly clear internal SM state which may be otherwise difficult to access and will affect future execution. Specifically, the following are cleared: input and output shift counters; the contents of the input shift register; the delay counter; the waiting-on-IRQ state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any pin write left asserted due to OUT_STICKY. The program counter, the contents of the output shift register and the X/Y scratch registers are not affected. + CLKDIV_RESTART = uint4(0); // Restart a state machine's clock divider from an initial phase of 0. Clock dividers are free-running, so once started, their output (including fractional jitter) is completely determined by the integer/fractional divisor configured in SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor are restarted simultaneously, by writing multiple 1 bits to this field, the execution clocks of those state machines will run in precise lockstep. Note that setting/clearing SM_ENABLE does not stop the clock divider from running, so once multiple state machines' clocks are synchronised, it is safe to disable/reenable a state machine, whilst keeping the clock dividers in sync. Note also that CLKDIV_RESTART can be written to whilst the state machine is running, and this is useful to resynchronise clock dividers after the divisors (SMx_CLKDIV) have been changed on-the-fly. + _res1 = uint20(0); // Reserved, 20 bits + } + + // PIO0 PIO control register + register PIO0_CTRL_t PIO0_PIO0_CTRL at 0x50200000; + register uint32 PIO0_PIO0_CTRL_raw at 0x50200000; + + type FSTAT_t { + RXFULL = uint4(0); // State machine RX FIFO is full + _res1 = uint4(0); // Reserved, 4 bits + RXEMPTY = uint4(0); // State machine RX FIFO is empty + _res2 = uint4(0); // Reserved, 4 bits + TXFULL = uint4(0); // State machine TX FIFO is full + _res3 = uint4(0); // Reserved, 4 bits + TXEMPTY = uint4(0); // State machine TX FIFO is empty + _res4 = uint4(0); // Reserved, 4 bits + } + + // PIO0 FIFO status register + register FSTAT_t PIO0_FSTAT at 0x50200004; + register uint32 PIO0_FSTAT_raw at 0x50200004; + + type FDEBUG_t { + RXSTALL = uint4(0); // State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO took place, in which case the state machine has dropped data. Write 1 to clear. + _res1 = uint4(0); // Reserved, 4 bits + RXUNDER = uint4(0); // RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to clear. Note that read-on-empty does not perturb the state of the FIFO in any way, but the data returned by reading from an empty FIFO is undefined, so this flag generally only becomes set due to some kind of software error. + _res2 = uint4(0); // Reserved, 4 bits + TXOVER = uint4(0); // TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to clear. Note that write-on-full does not alter the state or contents of the FIFO in any way, but the data that the system attempted to write is dropped, so if this flag is set, your software has quite likely dropped some data on the floor. + _res3 = uint4(0); // Reserved, 4 bits + TXSTALL = uint4(0); // State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT with autopull enabled. Write 1 to clear. + _res4 = uint4(0); // Reserved, 4 bits + } + + // PIO0 FIFO debug register + register FDEBUG_t PIO0_FDEBUG at 0x50200008; + register uint32 PIO0_FDEBUG_raw at 0x50200008; + + type FLEVEL_t { + TX0 = uint4(0); // + RX0 = uint4(0); // + TX1 = uint4(0); // + RX1 = uint4(0); // + TX2 = uint4(0); // + RX2 = uint4(0); // + TX3 = uint4(0); // + RX3 = uint4(0); // + } + + // PIO0 FIFO levels + register FLEVEL_t PIO0_FLEVEL at 0x5020000c; + register uint32 PIO0_FLEVEL_raw at 0x5020000c; + + type TXF0_t { + TXF0 = uint32(0); // + } + + // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF0_t PIO0_TXF0 at 0x50200010; + register uint32 PIO0_TXF0_raw at 0x50200010; + + type TXF1_t { + TXF1 = uint32(0); // + } + + // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF1_t PIO0_TXF1 at 0x50200014; + register uint32 PIO0_TXF1_raw at 0x50200014; + + type TXF2_t { + TXF2 = uint32(0); // + } + + // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF2_t PIO0_TXF2 at 0x50200018; + register uint32 PIO0_TXF2_raw at 0x50200018; + + type TXF3_t { + TXF3 = uint32(0); // + } + + // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF3_t PIO0_TXF3 at 0x5020001c; + register uint32 PIO0_TXF3_raw at 0x5020001c; + + type RXF0_t { + RXF0 = uint32(0); // + } + + // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF0_t PIO0_RXF0 at 0x50200020; + register uint32 PIO0_RXF0_raw at 0x50200020; + + type RXF1_t { + RXF1 = uint32(0); // + } + + // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF1_t PIO0_RXF1 at 0x50200024; + register uint32 PIO0_RXF1_raw at 0x50200024; + + type RXF2_t { + RXF2 = uint32(0); // + } + + // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF2_t PIO0_RXF2 at 0x50200028; + register uint32 PIO0_RXF2_raw at 0x50200028; + + type RXF3_t { + RXF3 = uint32(0); // + } + + // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF3_t PIO0_RXF3 at 0x5020002c; + register uint32 PIO0_RXF3_raw at 0x5020002c; + + type IRQ_t { + IRQ = uint8(0); // + _res1 = uint24(0); // Reserved, 24 bits + } + + // PIO0 State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag. Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE. + register IRQ_t PIO0_IRQ at 0x50200030; + register uint32 PIO0_IRQ_raw at 0x50200030; + + type IRQ_FORCE_t { + IRQ_FORCE = uint8(0); // + _res1 = uint24(0); // Reserved, 24 bits + } + + // PIO0 Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. + register IRQ_FORCE_t PIO0_IRQ_FORCE at 0x50200034; + register uint32 PIO0_IRQ_FORCE_raw at 0x50200034; + + type INPUT_SYNC_BYPASS_t { + INPUT_SYNC_BYPASS = uint32(0); // + } + + // PIO0 There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. 0 -> input is synchronized (default) 1 -> synchronizer is bypassed If in doubt, leave this register as all zeroes. + register INPUT_SYNC_BYPASS_t PIO0_INPUT_SYNC_BYPASS at 0x50200038; + register uint32 PIO0_INPUT_SYNC_BYPASS_raw at 0x50200038; + + type DBG_PADOUT_t { + DBG_PADOUT = uint32(0); // + } + + // PIO0 Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + register DBG_PADOUT_t PIO0_DBG_PADOUT at 0x5020003c; + register uint32 PIO0_DBG_PADOUT_raw at 0x5020003c; + + type DBG_PADOE_t { + DBG_PADOE = uint32(0); // + } + + // PIO0 Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + register DBG_PADOE_t PIO0_DBG_PADOE at 0x50200040; + register uint32 PIO0_DBG_PADOE_raw at 0x50200040; + + type DBG_CFGINFO_t { + FIFO_DEPTH = uint6(0); // The depth of the state machine TX/RX FIFOs, measured in words. Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double this depth. + _res1 = uint2(0); // Reserved, 2 bits + SM_COUNT = uint4(0); // The number of state machines this PIO instance is equipped with. + _res2 = uint4(0); // Reserved, 4 bits + IMEM_SIZE = uint6(0); // The size of the instruction memory, measured in units of one instruction + _res3 = uint10(0); // Reserved, 10 bits + } + + // PIO0 The PIO hardware has some free parameters that may vary between chip products. These should be provided in the chip datasheet, but are also exposed here. + register DBG_CFGINFO_t PIO0_DBG_CFGINFO at 0x50200044; + register uint32 PIO0_DBG_CFGINFO_raw at 0x50200044; + + type INSTR_MEM0_t { + INSTR_MEM0 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 0 + register INSTR_MEM0_t PIO0_INSTR_MEM0 at 0x50200048; + register uint32 PIO0_INSTR_MEM0_raw at 0x50200048; + + type INSTR_MEM1_t { + INSTR_MEM1 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 1 + register INSTR_MEM1_t PIO0_INSTR_MEM1 at 0x5020004c; + register uint32 PIO0_INSTR_MEM1_raw at 0x5020004c; + + type INSTR_MEM2_t { + INSTR_MEM2 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 2 + register INSTR_MEM2_t PIO0_INSTR_MEM2 at 0x50200050; + register uint32 PIO0_INSTR_MEM2_raw at 0x50200050; + + type INSTR_MEM3_t { + INSTR_MEM3 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 3 + register INSTR_MEM3_t PIO0_INSTR_MEM3 at 0x50200054; + register uint32 PIO0_INSTR_MEM3_raw at 0x50200054; + + type INSTR_MEM4_t { + INSTR_MEM4 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 4 + register INSTR_MEM4_t PIO0_INSTR_MEM4 at 0x50200058; + register uint32 PIO0_INSTR_MEM4_raw at 0x50200058; + + type INSTR_MEM5_t { + INSTR_MEM5 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 5 + register INSTR_MEM5_t PIO0_INSTR_MEM5 at 0x5020005c; + register uint32 PIO0_INSTR_MEM5_raw at 0x5020005c; + + type INSTR_MEM6_t { + INSTR_MEM6 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 6 + register INSTR_MEM6_t PIO0_INSTR_MEM6 at 0x50200060; + register uint32 PIO0_INSTR_MEM6_raw at 0x50200060; + + type INSTR_MEM7_t { + INSTR_MEM7 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 7 + register INSTR_MEM7_t PIO0_INSTR_MEM7 at 0x50200064; + register uint32 PIO0_INSTR_MEM7_raw at 0x50200064; + + type INSTR_MEM8_t { + INSTR_MEM8 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 8 + register INSTR_MEM8_t PIO0_INSTR_MEM8 at 0x50200068; + register uint32 PIO0_INSTR_MEM8_raw at 0x50200068; + + type INSTR_MEM9_t { + INSTR_MEM9 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 9 + register INSTR_MEM9_t PIO0_INSTR_MEM9 at 0x5020006c; + register uint32 PIO0_INSTR_MEM9_raw at 0x5020006c; + + type INSTR_MEM10_t { + INSTR_MEM10 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 10 + register INSTR_MEM10_t PIO0_INSTR_MEM10 at 0x50200070; + register uint32 PIO0_INSTR_MEM10_raw at 0x50200070; + + type INSTR_MEM11_t { + INSTR_MEM11 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 11 + register INSTR_MEM11_t PIO0_INSTR_MEM11 at 0x50200074; + register uint32 PIO0_INSTR_MEM11_raw at 0x50200074; + + type INSTR_MEM12_t { + INSTR_MEM12 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 12 + register INSTR_MEM12_t PIO0_INSTR_MEM12 at 0x50200078; + register uint32 PIO0_INSTR_MEM12_raw at 0x50200078; + + type INSTR_MEM13_t { + INSTR_MEM13 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 13 + register INSTR_MEM13_t PIO0_INSTR_MEM13 at 0x5020007c; + register uint32 PIO0_INSTR_MEM13_raw at 0x5020007c; + + type INSTR_MEM14_t { + INSTR_MEM14 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 14 + register INSTR_MEM14_t PIO0_INSTR_MEM14 at 0x50200080; + register uint32 PIO0_INSTR_MEM14_raw at 0x50200080; + + type INSTR_MEM15_t { + INSTR_MEM15 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 15 + register INSTR_MEM15_t PIO0_INSTR_MEM15 at 0x50200084; + register uint32 PIO0_INSTR_MEM15_raw at 0x50200084; + + type INSTR_MEM16_t { + INSTR_MEM16 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 16 + register INSTR_MEM16_t PIO0_INSTR_MEM16 at 0x50200088; + register uint32 PIO0_INSTR_MEM16_raw at 0x50200088; + + type INSTR_MEM17_t { + INSTR_MEM17 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 17 + register INSTR_MEM17_t PIO0_INSTR_MEM17 at 0x5020008c; + register uint32 PIO0_INSTR_MEM17_raw at 0x5020008c; + + type INSTR_MEM18_t { + INSTR_MEM18 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 18 + register INSTR_MEM18_t PIO0_INSTR_MEM18 at 0x50200090; + register uint32 PIO0_INSTR_MEM18_raw at 0x50200090; + + type INSTR_MEM19_t { + INSTR_MEM19 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 19 + register INSTR_MEM19_t PIO0_INSTR_MEM19 at 0x50200094; + register uint32 PIO0_INSTR_MEM19_raw at 0x50200094; + + type INSTR_MEM20_t { + INSTR_MEM20 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 20 + register INSTR_MEM20_t PIO0_INSTR_MEM20 at 0x50200098; + register uint32 PIO0_INSTR_MEM20_raw at 0x50200098; + + type INSTR_MEM21_t { + INSTR_MEM21 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 21 + register INSTR_MEM21_t PIO0_INSTR_MEM21 at 0x5020009c; + register uint32 PIO0_INSTR_MEM21_raw at 0x5020009c; + + type INSTR_MEM22_t { + INSTR_MEM22 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 22 + register INSTR_MEM22_t PIO0_INSTR_MEM22 at 0x502000a0; + register uint32 PIO0_INSTR_MEM22_raw at 0x502000a0; + + type INSTR_MEM23_t { + INSTR_MEM23 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 23 + register INSTR_MEM23_t PIO0_INSTR_MEM23 at 0x502000a4; + register uint32 PIO0_INSTR_MEM23_raw at 0x502000a4; + + type INSTR_MEM24_t { + INSTR_MEM24 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 24 + register INSTR_MEM24_t PIO0_INSTR_MEM24 at 0x502000a8; + register uint32 PIO0_INSTR_MEM24_raw at 0x502000a8; + + type INSTR_MEM25_t { + INSTR_MEM25 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 25 + register INSTR_MEM25_t PIO0_INSTR_MEM25 at 0x502000ac; + register uint32 PIO0_INSTR_MEM25_raw at 0x502000ac; + + type INSTR_MEM26_t { + INSTR_MEM26 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 26 + register INSTR_MEM26_t PIO0_INSTR_MEM26 at 0x502000b0; + register uint32 PIO0_INSTR_MEM26_raw at 0x502000b0; + + type INSTR_MEM27_t { + INSTR_MEM27 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 27 + register INSTR_MEM27_t PIO0_INSTR_MEM27 at 0x502000b4; + register uint32 PIO0_INSTR_MEM27_raw at 0x502000b4; + + type INSTR_MEM28_t { + INSTR_MEM28 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 28 + register INSTR_MEM28_t PIO0_INSTR_MEM28 at 0x502000b8; + register uint32 PIO0_INSTR_MEM28_raw at 0x502000b8; + + type INSTR_MEM29_t { + INSTR_MEM29 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 29 + register INSTR_MEM29_t PIO0_INSTR_MEM29 at 0x502000bc; + register uint32 PIO0_INSTR_MEM29_raw at 0x502000bc; + + type INSTR_MEM30_t { + INSTR_MEM30 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 30 + register INSTR_MEM30_t PIO0_INSTR_MEM30 at 0x502000c0; + register uint32 PIO0_INSTR_MEM30_raw at 0x502000c0; + + type INSTR_MEM31_t { + INSTR_MEM31 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Write-only access to instruction memory location 31 + register INSTR_MEM31_t PIO0_INSTR_MEM31 at 0x502000c4; + register uint32 PIO0_INSTR_MEM31_raw at 0x502000c4; + + type SM0_CLKDIV_t { + _res1 = uint8(0); // Reserved, 8 bits + FRAC = uint8(0); // Fractional part of clock divisor + INT = uint16(0); // Effective frequency is sysclk/(int + frac/256). Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + } + + // PIO0 Clock divisor register for state machine 0 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM0_CLKDIV_t PIO0_SM0_CLKDIV at 0x502000c8; + register uint32 PIO0_SM0_CLKDIV_raw at 0x502000c8; + + enum SM0_EXECCTRL_STATUS_SEL { + TXLEVEL = 0, // All-ones if TX FIFO level < N, otherwise all-zeroes + RXLEVEL = 1 // All-ones if RX FIFO level < N, otherwise all-zeroes + } + + type SM0_EXECCTRL_t { + STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction + STATUS_SEL = false; // Comparison used for the MOV x, STATUS instruction. + _res1 = uint2(0); // Reserved, 2 bits + WRAP_BOTTOM = uint5(0); // After reaching wrap_top, execution is wrapped to this address. + WRAP_TOP = uint5(0); // After reaching this address, execution is wrapped to wrap_bottom. If the instruction is a jump, and the jump condition is true, the jump takes priority. + OUT_STICKY = false; // Continuously assert the most recent OUT/SET to the pins + INLINE_OUT_EN = false; // If 1, use a bit of OUT data as an auxiliary write enable When used in conjunction with OUT_STICKY, writes with an enable of 0 will deassert the latest pin write. This can create useful masking/override behaviour due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + OUT_EN_SEL = uint5(0); // Which data bit to use for inline OUT enable + JMP_PIN = uint5(0); // The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + SIDE_PINDIR = false; // If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_EN = false; // If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + EXEC_STALLED = false; // If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + } + + // PIO0 Execution/behavioural settings for state machine 0 + register SM0_EXECCTRL_t PIO0_SM0_EXECCTRL at 0x502000cc; + register uint32 PIO0_SM0_EXECCTRL_raw at 0x502000cc; + + type SM0_SHIFTCTRL_t { + _res1 = uint16(0); // Reserved, 16 bits + AUTOPUSH = false; // Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPULL = false; // Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + IN_SHIFTDIR = false; // 1 = shift input shift register to right (data enters from left). 0 = to left. + OUT_SHIFTDIR = false; // 1 = shift out of output shift register to right. 0 = to left. + PUSH_THRESH = uint5(0); // Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. Write 0 for value of 32. + PULL_THRESH = uint5(0); // Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. Write 0 for value of 32. + FJOIN_TX = false; // When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. RX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + FJOIN_RX = false; // When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. TX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + } + + // PIO0 Control behaviour of the input/output shift registers for state machine 0 + register SM0_SHIFTCTRL_t PIO0_SM0_SHIFTCTRL at 0x502000d0; + register uint32 PIO0_SM0_SHIFTCTRL_raw at 0x502000d0; + + type SM0_ADDR_t { + SM0_ADDR = uint5(0); // + _res1 = uint27(0); // Reserved, 27 bits + } + + // PIO0 Current instruction address of state machine 0 + register SM0_ADDR_t PIO0_SM0_ADDR at 0x502000d4; + register uint32 PIO0_SM0_ADDR_raw at 0x502000d4; + + type SM0_INSTR_t { + SM0_INSTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Read to see the instruction currently addressed by state machine 0's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM0_INSTR_t PIO0_SM0_INSTR at 0x502000d8; + register uint32 PIO0_SM0_INSTR_raw at 0x502000d8; + + type SM0_PINCTRL_t { + OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + SET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SIDESET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + IN_BASE = uint5(0); // The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + OUT_COUNT = uint6(0); // The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + SET_COUNT = uint3(0); // The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SIDESET_COUNT = uint3(0); // The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + } + + // PIO0 State machine pin control + register SM0_PINCTRL_t PIO0_SM0_PINCTRL at 0x502000dc; + register uint32 PIO0_SM0_PINCTRL_raw at 0x502000dc; + + type SM1_CLKDIV_t { + _res1 = uint8(0); // Reserved, 8 bits + FRAC = uint8(0); // Fractional part of clock divisor + INT = uint16(0); // Effective frequency is sysclk/(int + frac/256). Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + } + + // PIO0 Clock divisor register for state machine 1 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM1_CLKDIV_t PIO0_SM1_CLKDIV at 0x502000e0; + register uint32 PIO0_SM1_CLKDIV_raw at 0x502000e0; + + enum SM1_EXECCTRL_STATUS_SEL { + TXLEVEL = 0, // All-ones if TX FIFO level < N, otherwise all-zeroes + RXLEVEL = 1 // All-ones if RX FIFO level < N, otherwise all-zeroes + } + + type SM1_EXECCTRL_t { + STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction + STATUS_SEL = false; // Comparison used for the MOV x, STATUS instruction. + _res1 = uint2(0); // Reserved, 2 bits + WRAP_BOTTOM = uint5(0); // After reaching wrap_top, execution is wrapped to this address. + WRAP_TOP = uint5(0); // After reaching this address, execution is wrapped to wrap_bottom. If the instruction is a jump, and the jump condition is true, the jump takes priority. + OUT_STICKY = false; // Continuously assert the most recent OUT/SET to the pins + INLINE_OUT_EN = false; // If 1, use a bit of OUT data as an auxiliary write enable When used in conjunction with OUT_STICKY, writes with an enable of 0 will deassert the latest pin write. This can create useful masking/override behaviour due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + OUT_EN_SEL = uint5(0); // Which data bit to use for inline OUT enable + JMP_PIN = uint5(0); // The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + SIDE_PINDIR = false; // If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_EN = false; // If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + EXEC_STALLED = false; // If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + } + + // PIO0 Execution/behavioural settings for state machine 1 + register SM1_EXECCTRL_t PIO0_SM1_EXECCTRL at 0x502000e4; + register uint32 PIO0_SM1_EXECCTRL_raw at 0x502000e4; + + type SM1_SHIFTCTRL_t { + _res1 = uint16(0); // Reserved, 16 bits + AUTOPUSH = false; // Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPULL = false; // Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + IN_SHIFTDIR = false; // 1 = shift input shift register to right (data enters from left). 0 = to left. + OUT_SHIFTDIR = false; // 1 = shift out of output shift register to right. 0 = to left. + PUSH_THRESH = uint5(0); // Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. Write 0 for value of 32. + PULL_THRESH = uint5(0); // Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. Write 0 for value of 32. + FJOIN_TX = false; // When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. RX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + FJOIN_RX = false; // When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. TX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + } + + // PIO0 Control behaviour of the input/output shift registers for state machine 1 + register SM1_SHIFTCTRL_t PIO0_SM1_SHIFTCTRL at 0x502000e8; + register uint32 PIO0_SM1_SHIFTCTRL_raw at 0x502000e8; + + type SM1_ADDR_t { + SM1_ADDR = uint5(0); // + _res1 = uint27(0); // Reserved, 27 bits + } + + // PIO0 Current instruction address of state machine 1 + register SM1_ADDR_t PIO0_SM1_ADDR at 0x502000ec; + register uint32 PIO0_SM1_ADDR_raw at 0x502000ec; + + type SM1_INSTR_t { + SM1_INSTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Read to see the instruction currently addressed by state machine 1's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM1_INSTR_t PIO0_SM1_INSTR at 0x502000f0; + register uint32 PIO0_SM1_INSTR_raw at 0x502000f0; + + type SM1_PINCTRL_t { + OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + SET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SIDESET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + IN_BASE = uint5(0); // The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + OUT_COUNT = uint6(0); // The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + SET_COUNT = uint3(0); // The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SIDESET_COUNT = uint3(0); // The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + } + + // PIO0 State machine pin control + register SM1_PINCTRL_t PIO0_SM1_PINCTRL at 0x502000f4; + register uint32 PIO0_SM1_PINCTRL_raw at 0x502000f4; + + type SM2_CLKDIV_t { + _res1 = uint8(0); // Reserved, 8 bits + FRAC = uint8(0); // Fractional part of clock divisor + INT = uint16(0); // Effective frequency is sysclk/(int + frac/256). Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + } + + // PIO0 Clock divisor register for state machine 2 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM2_CLKDIV_t PIO0_SM2_CLKDIV at 0x502000f8; + register uint32 PIO0_SM2_CLKDIV_raw at 0x502000f8; + + enum SM2_EXECCTRL_STATUS_SEL { + TXLEVEL = 0, // All-ones if TX FIFO level < N, otherwise all-zeroes + RXLEVEL = 1 // All-ones if RX FIFO level < N, otherwise all-zeroes + } + + type SM2_EXECCTRL_t { + STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction + STATUS_SEL = false; // Comparison used for the MOV x, STATUS instruction. + _res1 = uint2(0); // Reserved, 2 bits + WRAP_BOTTOM = uint5(0); // After reaching wrap_top, execution is wrapped to this address. + WRAP_TOP = uint5(0); // After reaching this address, execution is wrapped to wrap_bottom. If the instruction is a jump, and the jump condition is true, the jump takes priority. + OUT_STICKY = false; // Continuously assert the most recent OUT/SET to the pins + INLINE_OUT_EN = false; // If 1, use a bit of OUT data as an auxiliary write enable When used in conjunction with OUT_STICKY, writes with an enable of 0 will deassert the latest pin write. This can create useful masking/override behaviour due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + OUT_EN_SEL = uint5(0); // Which data bit to use for inline OUT enable + JMP_PIN = uint5(0); // The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + SIDE_PINDIR = false; // If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_EN = false; // If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + EXEC_STALLED = false; // If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + } + + // PIO0 Execution/behavioural settings for state machine 2 + register SM2_EXECCTRL_t PIO0_SM2_EXECCTRL at 0x502000fc; + register uint32 PIO0_SM2_EXECCTRL_raw at 0x502000fc; + + type SM2_SHIFTCTRL_t { + _res1 = uint16(0); // Reserved, 16 bits + AUTOPUSH = false; // Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPULL = false; // Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + IN_SHIFTDIR = false; // 1 = shift input shift register to right (data enters from left). 0 = to left. + OUT_SHIFTDIR = false; // 1 = shift out of output shift register to right. 0 = to left. + PUSH_THRESH = uint5(0); // Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. Write 0 for value of 32. + PULL_THRESH = uint5(0); // Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. Write 0 for value of 32. + FJOIN_TX = false; // When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. RX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + FJOIN_RX = false; // When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. TX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + } + + // PIO0 Control behaviour of the input/output shift registers for state machine 2 + register SM2_SHIFTCTRL_t PIO0_SM2_SHIFTCTRL at 0x50200100; + register uint32 PIO0_SM2_SHIFTCTRL_raw at 0x50200100; + + type SM2_ADDR_t { + SM2_ADDR = uint5(0); // + _res1 = uint27(0); // Reserved, 27 bits + } + + // PIO0 Current instruction address of state machine 2 + register SM2_ADDR_t PIO0_SM2_ADDR at 0x50200104; + register uint32 PIO0_SM2_ADDR_raw at 0x50200104; + + type SM2_INSTR_t { + SM2_INSTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Read to see the instruction currently addressed by state machine 2's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM2_INSTR_t PIO0_SM2_INSTR at 0x50200108; + register uint32 PIO0_SM2_INSTR_raw at 0x50200108; + + type SM2_PINCTRL_t { + OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + SET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SIDESET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + IN_BASE = uint5(0); // The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + OUT_COUNT = uint6(0); // The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + SET_COUNT = uint3(0); // The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SIDESET_COUNT = uint3(0); // The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + } + + // PIO0 State machine pin control + register SM2_PINCTRL_t PIO0_SM2_PINCTRL at 0x5020010c; + register uint32 PIO0_SM2_PINCTRL_raw at 0x5020010c; + + type SM3_CLKDIV_t { + _res1 = uint8(0); // Reserved, 8 bits + FRAC = uint8(0); // Fractional part of clock divisor + INT = uint16(0); // Effective frequency is sysclk/(int + frac/256). Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + } + + // PIO0 Clock divisor register for state machine 3 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM3_CLKDIV_t PIO0_SM3_CLKDIV at 0x50200110; + register uint32 PIO0_SM3_CLKDIV_raw at 0x50200110; + + enum SM3_EXECCTRL_STATUS_SEL { + TXLEVEL = 0, // All-ones if TX FIFO level < N, otherwise all-zeroes + RXLEVEL = 1 // All-ones if RX FIFO level < N, otherwise all-zeroes + } + + type SM3_EXECCTRL_t { + STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction + STATUS_SEL = false; // Comparison used for the MOV x, STATUS instruction. + _res1 = uint2(0); // Reserved, 2 bits + WRAP_BOTTOM = uint5(0); // After reaching wrap_top, execution is wrapped to this address. + WRAP_TOP = uint5(0); // After reaching this address, execution is wrapped to wrap_bottom. If the instruction is a jump, and the jump condition is true, the jump takes priority. + OUT_STICKY = false; // Continuously assert the most recent OUT/SET to the pins + INLINE_OUT_EN = false; // If 1, use a bit of OUT data as an auxiliary write enable When used in conjunction with OUT_STICKY, writes with an enable of 0 will deassert the latest pin write. This can create useful masking/override behaviour due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + OUT_EN_SEL = uint5(0); // Which data bit to use for inline OUT enable + JMP_PIN = uint5(0); // The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + SIDE_PINDIR = false; // If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_EN = false; // If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + EXEC_STALLED = false; // If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + } + + // PIO0 Execution/behavioural settings for state machine 3 + register SM3_EXECCTRL_t PIO0_SM3_EXECCTRL at 0x50200114; + register uint32 PIO0_SM3_EXECCTRL_raw at 0x50200114; + + type SM3_SHIFTCTRL_t { + _res1 = uint16(0); // Reserved, 16 bits + AUTOPUSH = false; // Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPULL = false; // Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + IN_SHIFTDIR = false; // 1 = shift input shift register to right (data enters from left). 0 = to left. + OUT_SHIFTDIR = false; // 1 = shift out of output shift register to right. 0 = to left. + PUSH_THRESH = uint5(0); // Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. Write 0 for value of 32. + PULL_THRESH = uint5(0); // Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. Write 0 for value of 32. + FJOIN_TX = false; // When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. RX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + FJOIN_RX = false; // When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. TX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + } + + // PIO0 Control behaviour of the input/output shift registers for state machine 3 + register SM3_SHIFTCTRL_t PIO0_SM3_SHIFTCTRL at 0x50200118; + register uint32 PIO0_SM3_SHIFTCTRL_raw at 0x50200118; + + type SM3_ADDR_t { + SM3_ADDR = uint5(0); // + _res1 = uint27(0); // Reserved, 27 bits + } + + // PIO0 Current instruction address of state machine 3 + register SM3_ADDR_t PIO0_SM3_ADDR at 0x5020011c; + register uint32 PIO0_SM3_ADDR_raw at 0x5020011c; + + type SM3_INSTR_t { + SM3_INSTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // PIO0 Read to see the instruction currently addressed by state machine 3's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM3_INSTR_t PIO0_SM3_INSTR at 0x50200120; + register uint32 PIO0_SM3_INSTR_raw at 0x50200120; + + type SM3_PINCTRL_t { + OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + SET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SIDESET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + IN_BASE = uint5(0); // The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + OUT_COUNT = uint6(0); // The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + SET_COUNT = uint3(0); // The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SIDESET_COUNT = uint3(0); // The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + } + + // PIO0 State machine pin control + register SM3_PINCTRL_t PIO0_SM3_PINCTRL at 0x50200124; + register uint32 PIO0_SM3_PINCTRL_raw at 0x50200124; + + type PIO0_INTR_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits + } + + // PIO0 Raw Interrupts + register PIO0_INTR_t PIO0_PIO0_INTR at 0x50200128; + register uint32 PIO0_PIO0_INTR_raw at 0x50200128; + + type IRQ0_INTE_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits + } + + // PIO0 Interrupt Enable for irq0 + register IRQ0_INTE_t PIO0_IRQ0_INTE at 0x5020012c; + register uint32 PIO0_IRQ0_INTE_raw at 0x5020012c; + + type IRQ0_INTF_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits + } + + // PIO0 Interrupt Force for irq0 + register IRQ0_INTF_t PIO0_IRQ0_INTF at 0x50200130; + register uint32 PIO0_IRQ0_INTF_raw at 0x50200130; + + type IRQ0_INTS_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits + } + + // PIO0 Interrupt status after masking & forcing for irq0 + register IRQ0_INTS_t PIO0_IRQ0_INTS at 0x50200134; + register uint32 PIO0_IRQ0_INTS_raw at 0x50200134; + + type IRQ1_INTE_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits + } + + // PIO0 Interrupt Enable for irq1 + register IRQ1_INTE_t PIO0_IRQ1_INTE at 0x50200138; + register uint32 PIO0_IRQ1_INTE_raw at 0x50200138; + + type IRQ1_INTF_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits + } + + // PIO0 Interrupt Force for irq1 + register IRQ1_INTF_t PIO0_IRQ1_INTF at 0x5020013c; + register uint32 PIO0_IRQ1_INTF_raw at 0x5020013c; + + type IRQ1_INTS_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits + } + + // PIO0 Interrupt status after masking & forcing for irq1 + register IRQ1_INTS_t PIO0_IRQ1_INTS at 0x50200140; + register uint32 PIO0_IRQ1_INTS_raw at 0x50200140; + + +/* Types and registers for PIO1 */ + + // PIO1 PIO control register + register PIO0_CTRL_t PIO1_CTRL at 0x50300000; + register uint32 PIO1_CTRL_raw at 0x50300000; + + // PIO1 FIFO status register + register FSTAT_t PIO1_FSTAT at 0x50300004; + register uint32 PIO1_FSTAT_raw at 0x50300004; + + // PIO1 FIFO debug register + register FDEBUG_t PIO1_FDEBUG at 0x50300008; + register uint32 PIO1_FDEBUG_raw at 0x50300008; + + // PIO1 FIFO levels + register FLEVEL_t PIO1_FLEVEL at 0x5030000c; + register uint32 PIO1_FLEVEL_raw at 0x5030000c; + + // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF0_t PIO1_TXF0 at 0x50300010; + register uint32 PIO1_TXF0_raw at 0x50300010; + + // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF1_t PIO1_TXF1 at 0x50300014; + register uint32 PIO1_TXF1_raw at 0x50300014; + + // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF2_t PIO1_TXF2 at 0x50300018; + register uint32 PIO1_TXF2_raw at 0x50300018; + + // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF3_t PIO1_TXF3 at 0x5030001c; + register uint32 PIO1_TXF3_raw at 0x5030001c; + + // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF0_t PIO1_RXF0 at 0x50300020; + register uint32 PIO1_RXF0_raw at 0x50300020; + + // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF1_t PIO1_RXF1 at 0x50300024; + register uint32 PIO1_RXF1_raw at 0x50300024; + + // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF2_t PIO1_RXF2 at 0x50300028; + register uint32 PIO1_RXF2_raw at 0x50300028; + + // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF3_t PIO1_RXF3 at 0x5030002c; + register uint32 PIO1_RXF3_raw at 0x5030002c; + + // PIO1 State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag. Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE. + register IRQ_t PIO1_IRQ at 0x50300030; + register uint32 PIO1_IRQ_raw at 0x50300030; + + // PIO1 Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. + register IRQ_FORCE_t PIO1_IRQ_FORCE at 0x50300034; + register uint32 PIO1_IRQ_FORCE_raw at 0x50300034; + + // PIO1 There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. 0 -> input is synchronized (default) 1 -> synchronizer is bypassed If in doubt, leave this register as all zeroes. + register INPUT_SYNC_BYPASS_t PIO1_INPUT_SYNC_BYPASS at 0x50300038; + register uint32 PIO1_INPUT_SYNC_BYPASS_raw at 0x50300038; + + // PIO1 Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + register DBG_PADOUT_t PIO1_DBG_PADOUT at 0x5030003c; + register uint32 PIO1_DBG_PADOUT_raw at 0x5030003c; + + // PIO1 Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + register DBG_PADOE_t PIO1_DBG_PADOE at 0x50300040; + register uint32 PIO1_DBG_PADOE_raw at 0x50300040; + + // PIO1 The PIO hardware has some free parameters that may vary between chip products. These should be provided in the chip datasheet, but are also exposed here. + register DBG_CFGINFO_t PIO1_DBG_CFGINFO at 0x50300044; + register uint32 PIO1_DBG_CFGINFO_raw at 0x50300044; + + // PIO1 Write-only access to instruction memory location 0 + register INSTR_MEM0_t PIO1_INSTR_MEM0 at 0x50300048; + register uint32 PIO1_INSTR_MEM0_raw at 0x50300048; + + // PIO1 Write-only access to instruction memory location 1 + register INSTR_MEM1_t PIO1_INSTR_MEM1 at 0x5030004c; + register uint32 PIO1_INSTR_MEM1_raw at 0x5030004c; + + // PIO1 Write-only access to instruction memory location 2 + register INSTR_MEM2_t PIO1_INSTR_MEM2 at 0x50300050; + register uint32 PIO1_INSTR_MEM2_raw at 0x50300050; + + // PIO1 Write-only access to instruction memory location 3 + register INSTR_MEM3_t PIO1_INSTR_MEM3 at 0x50300054; + register uint32 PIO1_INSTR_MEM3_raw at 0x50300054; + + // PIO1 Write-only access to instruction memory location 4 + register INSTR_MEM4_t PIO1_INSTR_MEM4 at 0x50300058; + register uint32 PIO1_INSTR_MEM4_raw at 0x50300058; + + // PIO1 Write-only access to instruction memory location 5 + register INSTR_MEM5_t PIO1_INSTR_MEM5 at 0x5030005c; + register uint32 PIO1_INSTR_MEM5_raw at 0x5030005c; + + // PIO1 Write-only access to instruction memory location 6 + register INSTR_MEM6_t PIO1_INSTR_MEM6 at 0x50300060; + register uint32 PIO1_INSTR_MEM6_raw at 0x50300060; + + // PIO1 Write-only access to instruction memory location 7 + register INSTR_MEM7_t PIO1_INSTR_MEM7 at 0x50300064; + register uint32 PIO1_INSTR_MEM7_raw at 0x50300064; + + // PIO1 Write-only access to instruction memory location 8 + register INSTR_MEM8_t PIO1_INSTR_MEM8 at 0x50300068; + register uint32 PIO1_INSTR_MEM8_raw at 0x50300068; + + // PIO1 Write-only access to instruction memory location 9 + register INSTR_MEM9_t PIO1_INSTR_MEM9 at 0x5030006c; + register uint32 PIO1_INSTR_MEM9_raw at 0x5030006c; + + // PIO1 Write-only access to instruction memory location 10 + register INSTR_MEM10_t PIO1_INSTR_MEM10 at 0x50300070; + register uint32 PIO1_INSTR_MEM10_raw at 0x50300070; + + // PIO1 Write-only access to instruction memory location 11 + register INSTR_MEM11_t PIO1_INSTR_MEM11 at 0x50300074; + register uint32 PIO1_INSTR_MEM11_raw at 0x50300074; + + // PIO1 Write-only access to instruction memory location 12 + register INSTR_MEM12_t PIO1_INSTR_MEM12 at 0x50300078; + register uint32 PIO1_INSTR_MEM12_raw at 0x50300078; + + // PIO1 Write-only access to instruction memory location 13 + register INSTR_MEM13_t PIO1_INSTR_MEM13 at 0x5030007c; + register uint32 PIO1_INSTR_MEM13_raw at 0x5030007c; + + // PIO1 Write-only access to instruction memory location 14 + register INSTR_MEM14_t PIO1_INSTR_MEM14 at 0x50300080; + register uint32 PIO1_INSTR_MEM14_raw at 0x50300080; + + // PIO1 Write-only access to instruction memory location 15 + register INSTR_MEM15_t PIO1_INSTR_MEM15 at 0x50300084; + register uint32 PIO1_INSTR_MEM15_raw at 0x50300084; + + // PIO1 Write-only access to instruction memory location 16 + register INSTR_MEM16_t PIO1_INSTR_MEM16 at 0x50300088; + register uint32 PIO1_INSTR_MEM16_raw at 0x50300088; + + // PIO1 Write-only access to instruction memory location 17 + register INSTR_MEM17_t PIO1_INSTR_MEM17 at 0x5030008c; + register uint32 PIO1_INSTR_MEM17_raw at 0x5030008c; + + // PIO1 Write-only access to instruction memory location 18 + register INSTR_MEM18_t PIO1_INSTR_MEM18 at 0x50300090; + register uint32 PIO1_INSTR_MEM18_raw at 0x50300090; + + // PIO1 Write-only access to instruction memory location 19 + register INSTR_MEM19_t PIO1_INSTR_MEM19 at 0x50300094; + register uint32 PIO1_INSTR_MEM19_raw at 0x50300094; + + // PIO1 Write-only access to instruction memory location 20 + register INSTR_MEM20_t PIO1_INSTR_MEM20 at 0x50300098; + register uint32 PIO1_INSTR_MEM20_raw at 0x50300098; + + // PIO1 Write-only access to instruction memory location 21 + register INSTR_MEM21_t PIO1_INSTR_MEM21 at 0x5030009c; + register uint32 PIO1_INSTR_MEM21_raw at 0x5030009c; + + // PIO1 Write-only access to instruction memory location 22 + register INSTR_MEM22_t PIO1_INSTR_MEM22 at 0x503000a0; + register uint32 PIO1_INSTR_MEM22_raw at 0x503000a0; + + // PIO1 Write-only access to instruction memory location 23 + register INSTR_MEM23_t PIO1_INSTR_MEM23 at 0x503000a4; + register uint32 PIO1_INSTR_MEM23_raw at 0x503000a4; + + // PIO1 Write-only access to instruction memory location 24 + register INSTR_MEM24_t PIO1_INSTR_MEM24 at 0x503000a8; + register uint32 PIO1_INSTR_MEM24_raw at 0x503000a8; + + // PIO1 Write-only access to instruction memory location 25 + register INSTR_MEM25_t PIO1_INSTR_MEM25 at 0x503000ac; + register uint32 PIO1_INSTR_MEM25_raw at 0x503000ac; + + // PIO1 Write-only access to instruction memory location 26 + register INSTR_MEM26_t PIO1_INSTR_MEM26 at 0x503000b0; + register uint32 PIO1_INSTR_MEM26_raw at 0x503000b0; + + // PIO1 Write-only access to instruction memory location 27 + register INSTR_MEM27_t PIO1_INSTR_MEM27 at 0x503000b4; + register uint32 PIO1_INSTR_MEM27_raw at 0x503000b4; + + // PIO1 Write-only access to instruction memory location 28 + register INSTR_MEM28_t PIO1_INSTR_MEM28 at 0x503000b8; + register uint32 PIO1_INSTR_MEM28_raw at 0x503000b8; + + // PIO1 Write-only access to instruction memory location 29 + register INSTR_MEM29_t PIO1_INSTR_MEM29 at 0x503000bc; + register uint32 PIO1_INSTR_MEM29_raw at 0x503000bc; + + // PIO1 Write-only access to instruction memory location 30 + register INSTR_MEM30_t PIO1_INSTR_MEM30 at 0x503000c0; + register uint32 PIO1_INSTR_MEM30_raw at 0x503000c0; + + // PIO1 Write-only access to instruction memory location 31 + register INSTR_MEM31_t PIO1_INSTR_MEM31 at 0x503000c4; + register uint32 PIO1_INSTR_MEM31_raw at 0x503000c4; + + // PIO1 Clock divisor register for state machine 0 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM0_CLKDIV_t PIO1_SM0_CLKDIV at 0x503000c8; + register uint32 PIO1_SM0_CLKDIV_raw at 0x503000c8; + + // PIO1 Execution/behavioural settings for state machine 0 + register SM0_EXECCTRL_t PIO1_SM0_EXECCTRL at 0x503000cc; + register uint32 PIO1_SM0_EXECCTRL_raw at 0x503000cc; + + // PIO1 Control behaviour of the input/output shift registers for state machine 0 + register SM0_SHIFTCTRL_t PIO1_SM0_SHIFTCTRL at 0x503000d0; + register uint32 PIO1_SM0_SHIFTCTRL_raw at 0x503000d0; + + // PIO1 Current instruction address of state machine 0 + register SM0_ADDR_t PIO1_SM0_ADDR at 0x503000d4; + register uint32 PIO1_SM0_ADDR_raw at 0x503000d4; + + // PIO1 Read to see the instruction currently addressed by state machine 0's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM0_INSTR_t PIO1_SM0_INSTR at 0x503000d8; + register uint32 PIO1_SM0_INSTR_raw at 0x503000d8; + + // PIO1 State machine pin control + register SM0_PINCTRL_t PIO1_SM0_PINCTRL at 0x503000dc; + register uint32 PIO1_SM0_PINCTRL_raw at 0x503000dc; + + // PIO1 Clock divisor register for state machine 1 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM1_CLKDIV_t PIO1_SM1_CLKDIV at 0x503000e0; + register uint32 PIO1_SM1_CLKDIV_raw at 0x503000e0; + + // PIO1 Execution/behavioural settings for state machine 1 + register SM1_EXECCTRL_t PIO1_SM1_EXECCTRL at 0x503000e4; + register uint32 PIO1_SM1_EXECCTRL_raw at 0x503000e4; + + // PIO1 Control behaviour of the input/output shift registers for state machine 1 + register SM1_SHIFTCTRL_t PIO1_SM1_SHIFTCTRL at 0x503000e8; + register uint32 PIO1_SM1_SHIFTCTRL_raw at 0x503000e8; + + // PIO1 Current instruction address of state machine 1 + register SM1_ADDR_t PIO1_SM1_ADDR at 0x503000ec; + register uint32 PIO1_SM1_ADDR_raw at 0x503000ec; + + // PIO1 Read to see the instruction currently addressed by state machine 1's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM1_INSTR_t PIO1_SM1_INSTR at 0x503000f0; + register uint32 PIO1_SM1_INSTR_raw at 0x503000f0; + + // PIO1 State machine pin control + register SM1_PINCTRL_t PIO1_SM1_PINCTRL at 0x503000f4; + register uint32 PIO1_SM1_PINCTRL_raw at 0x503000f4; + + // PIO1 Clock divisor register for state machine 2 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM2_CLKDIV_t PIO1_SM2_CLKDIV at 0x503000f8; + register uint32 PIO1_SM2_CLKDIV_raw at 0x503000f8; + + // PIO1 Execution/behavioural settings for state machine 2 + register SM2_EXECCTRL_t PIO1_SM2_EXECCTRL at 0x503000fc; + register uint32 PIO1_SM2_EXECCTRL_raw at 0x503000fc; + + // PIO1 Control behaviour of the input/output shift registers for state machine 2 + register SM2_SHIFTCTRL_t PIO1_SM2_SHIFTCTRL at 0x50300100; + register uint32 PIO1_SM2_SHIFTCTRL_raw at 0x50300100; + + // PIO1 Current instruction address of state machine 2 + register SM2_ADDR_t PIO1_SM2_ADDR at 0x50300104; + register uint32 PIO1_SM2_ADDR_raw at 0x50300104; + + // PIO1 Read to see the instruction currently addressed by state machine 2's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM2_INSTR_t PIO1_SM2_INSTR at 0x50300108; + register uint32 PIO1_SM2_INSTR_raw at 0x50300108; + + // PIO1 State machine pin control + register SM2_PINCTRL_t PIO1_SM2_PINCTRL at 0x5030010c; + register uint32 PIO1_SM2_PINCTRL_raw at 0x5030010c; + + // PIO1 Clock divisor register for state machine 3 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM3_CLKDIV_t PIO1_SM3_CLKDIV at 0x50300110; + register uint32 PIO1_SM3_CLKDIV_raw at 0x50300110; + + // PIO1 Execution/behavioural settings for state machine 3 + register SM3_EXECCTRL_t PIO1_SM3_EXECCTRL at 0x50300114; + register uint32 PIO1_SM3_EXECCTRL_raw at 0x50300114; + + // PIO1 Control behaviour of the input/output shift registers for state machine 3 + register SM3_SHIFTCTRL_t PIO1_SM3_SHIFTCTRL at 0x50300118; + register uint32 PIO1_SM3_SHIFTCTRL_raw at 0x50300118; + + // PIO1 Current instruction address of state machine 3 + register SM3_ADDR_t PIO1_SM3_ADDR at 0x5030011c; + register uint32 PIO1_SM3_ADDR_raw at 0x5030011c; + + // PIO1 Read to see the instruction currently addressed by state machine 3's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM3_INSTR_t PIO1_SM3_INSTR at 0x50300120; + register uint32 PIO1_SM3_INSTR_raw at 0x50300120; + + // PIO1 State machine pin control + register SM3_PINCTRL_t PIO1_SM3_PINCTRL at 0x50300124; + register uint32 PIO1_SM3_PINCTRL_raw at 0x50300124; + + // PIO1 Raw Interrupts + register PIO0_INTR_t PIO1_INTR at 0x50300128; + register uint32 PIO1_INTR_raw at 0x50300128; + + // PIO1 Interrupt Enable for irq0 + register IRQ0_INTE_t PIO1_IRQ0_INTE at 0x5030012c; + register uint32 PIO1_IRQ0_INTE_raw at 0x5030012c; + + // PIO1 Interrupt Force for irq0 + register IRQ0_INTF_t PIO1_IRQ0_INTF at 0x50300130; + register uint32 PIO1_IRQ0_INTF_raw at 0x50300130; + + // PIO1 Interrupt status after masking & forcing for irq0 + register IRQ0_INTS_t PIO1_IRQ0_INTS at 0x50300134; + register uint32 PIO1_IRQ0_INTS_raw at 0x50300134; + + // PIO1 Interrupt Enable for irq1 + register IRQ1_INTE_t PIO1_IRQ1_INTE at 0x50300138; + register uint32 PIO1_IRQ1_INTE_raw at 0x50300138; + + // PIO1 Interrupt Force for irq1 + register IRQ1_INTF_t PIO1_IRQ1_INTF at 0x5030013c; + register uint32 PIO1_IRQ1_INTF_raw at 0x5030013c; + + // PIO1 Interrupt status after masking & forcing for irq1 + register IRQ1_INTS_t PIO1_IRQ1_INTS at 0x50300140; + register uint32 PIO1_IRQ1_INTS_raw at 0x50300140; + + +/* Types and registers for BUSCTRL + Register block for busfabric control signals and performance counters + */ + + type BUS_PRIORITY_t { + PROC0 = false; // 0 - low priority, 1 - high priority + _res1 = uint3(0); // Reserved, 3 bits + PROC1 = false; // 0 - low priority, 1 - high priority + _res2 = uint3(0); // Reserved, 3 bits + DMA_R = false; // 0 - low priority, 1 - high priority + _res3 = uint3(0); // Reserved, 3 bits + DMA_W = false; // 0 - low priority, 1 - high priority + _res4 = uint19(0); // Reserved, 19 bits + } + + // Set the priority of each master for bus arbitration. + register BUS_PRIORITY_t BUS_PRIORITY at 0x40030000; + register uint32 BUS_PRIORITY_raw at 0x40030000; + + type BUS_PRIORITY_ACK_t { + BUS_PRIORITY_ACK = false; // Goes to 1 once all arbiters have registered the new global priority levels. Arbiters update their local priority when servicing a new nonsequential access. In normal circumstances this will happen almost immediately. + _res1 = uint31(0); // Reserved, 31 bits + } + + // Bus priority acknowledge + register BUS_PRIORITY_ACK_t BUS_PRIORITY_ACK at 0x40030004; + register uint32 BUS_PRIORITY_ACK_raw at 0x40030004; + + type PERFCTR0_t { + PERFCTR0 = uint24(0); // Busfabric saturating performance counter 0 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL0 + _res1 = uint8(0); // Reserved, 8 bits + } + + // Bus fabric performance counter 0 + register PERFCTR0_t PERFCTR0 at 0x40030008; + register uint32 PERFCTR0_raw at 0x40030008; + + enum PERFSEL0_PERFSEL0 { + apb_contested = 0, // + apb = 1, // + fastperi_contested = 2, // + fastperi = 3, // + sram5_contested = 4, // + sram5 = 5, // + sram4_contested = 6, // + sram4 = 7, // + sram3_contested = 8, // + sram3 = 9, // + sram2_contested = 10, // + sram2 = 11, // + sram1_contested = 12, // + sram1 = 13, // + sram0_contested = 14, // + sram0 = 15, // + xip_main_contested = 16, // + xip_main = 17, // + rom_contested = 18, // + rom = 19 // + } + + type PERFSEL0_t { + PERFSEL0 = uint5(0); // Select an event for PERFCTR0. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + _res1 = uint27(0); // Reserved, 27 bits + } + + // Bus fabric performance event select for PERFCTR0 + register PERFSEL0_t PERFSEL0 at 0x4003000c; + register uint32 PERFSEL0_raw at 0x4003000c; + + type PERFCTR1_t { + PERFCTR1 = uint24(0); // Busfabric saturating performance counter 1 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL1 + _res1 = uint8(0); // Reserved, 8 bits + } + + // Bus fabric performance counter 1 + register PERFCTR1_t PERFCTR1 at 0x40030010; + register uint32 PERFCTR1_raw at 0x40030010; + + enum PERFSEL1_PERFSEL1 { + apb_contested = 0, // + apb = 1, // + fastperi_contested = 2, // + fastperi = 3, // + sram5_contested = 4, // + sram5 = 5, // + sram4_contested = 6, // + sram4 = 7, // + sram3_contested = 8, // + sram3 = 9, // + sram2_contested = 10, // + sram2 = 11, // + sram1_contested = 12, // + sram1 = 13, // + sram0_contested = 14, // + sram0 = 15, // + xip_main_contested = 16, // + xip_main = 17, // + rom_contested = 18, // + rom = 19 // + } + + type PERFSEL1_t { + PERFSEL1 = uint5(0); // Select an event for PERFCTR1. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + _res1 = uint27(0); // Reserved, 27 bits + } + + // Bus fabric performance event select for PERFCTR1 + register PERFSEL1_t PERFSEL1 at 0x40030014; + register uint32 PERFSEL1_raw at 0x40030014; + + type PERFCTR2_t { + PERFCTR2 = uint24(0); // Busfabric saturating performance counter 2 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL2 + _res1 = uint8(0); // Reserved, 8 bits + } + + // Bus fabric performance counter 2 + register PERFCTR2_t PERFCTR2 at 0x40030018; + register uint32 PERFCTR2_raw at 0x40030018; + + enum PERFSEL2_PERFSEL2 { + apb_contested = 0, // + apb = 1, // + fastperi_contested = 2, // + fastperi = 3, // + sram5_contested = 4, // + sram5 = 5, // + sram4_contested = 6, // + sram4 = 7, // + sram3_contested = 8, // + sram3 = 9, // + sram2_contested = 10, // + sram2 = 11, // + sram1_contested = 12, // + sram1 = 13, // + sram0_contested = 14, // + sram0 = 15, // + xip_main_contested = 16, // + xip_main = 17, // + rom_contested = 18, // + rom = 19 // + } + + type PERFSEL2_t { + PERFSEL2 = uint5(0); // Select an event for PERFCTR2. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + _res1 = uint27(0); // Reserved, 27 bits + } + + // Bus fabric performance event select for PERFCTR2 + register PERFSEL2_t PERFSEL2 at 0x4003001c; + register uint32 PERFSEL2_raw at 0x4003001c; + + type PERFCTR3_t { + PERFCTR3 = uint24(0); // Busfabric saturating performance counter 3 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL3 + _res1 = uint8(0); // Reserved, 8 bits + } + + // Bus fabric performance counter 3 + register PERFCTR3_t PERFCTR3 at 0x40030020; + register uint32 PERFCTR3_raw at 0x40030020; + + enum PERFSEL3_PERFSEL3 { + apb_contested = 0, // + apb = 1, // + fastperi_contested = 2, // + fastperi = 3, // + sram5_contested = 4, // + sram5 = 5, // + sram4_contested = 6, // + sram4 = 7, // + sram3_contested = 8, // + sram3 = 9, // + sram2_contested = 10, // + sram2 = 11, // + sram1_contested = 12, // + sram1 = 13, // + sram0_contested = 14, // + sram0 = 15, // + xip_main_contested = 16, // + xip_main = 17, // + rom_contested = 18, // + rom = 19 // + } + + type PERFSEL3_t { + PERFSEL3 = uint5(0); // Select an event for PERFCTR3. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + _res1 = uint27(0); // Reserved, 27 bits + } + + // Bus fabric performance event select for PERFCTR3 + register PERFSEL3_t PERFSEL3 at 0x40030024; + register uint32 PERFSEL3_raw at 0x40030024; + + +/* Types and registers for SIO + Single-cycle IO block Provides core-local and inter-core hardware for the two processors, with single-cycle access. + */ + + type SIO_CPUID_t { + CPUID = uint32(0); // Value is 0 when read from processor core 0, and 1 when read from processor core 1. + } + + // Processor core identifier + register SIO_CPUID_t SIO_CPUID at 0xd0000000; + register uint32 SIO_CPUID_raw at 0xd0000000; + + type GPIO_IN_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // Input value for GPIO pins + register GPIO_IN_t GPIO_IN at 0xd0000004; + register uint32 GPIO_IN_raw at 0xd0000004; + + type GPIO_HI_IN_t { + GPIO_HI_IN = uint6(0); // Input value on QSPI IO in order 0..5: SCLK, SSn, SD0, SD1, SD2, SD3 + _res1 = uint26(0); // Reserved, 26 bits + } + + // Input value for QSPI pins + register GPIO_HI_IN_t GPIO_HI_IN at 0xd0000008; + register uint32 GPIO_HI_IN_raw at 0xd0000008; + + type GPIO_OUT_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output value: Set output level (1/0 -> high/low) for GPIO0...29. Reading back gives the last value written, NOT the input value from the pins. If core 0 and core 1 both write to GPIO_OUT simultaneously (or to a SET/CLR/XOR alias), the result is as though the write from core 0 took place first, and the write from core 1 was then applied to that intermediate result. + register GPIO_OUT_t GPIO_OUT at 0xd0000010; + register uint32 GPIO_OUT_raw at 0xd0000010; + + type GPIO_OUT_SET_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output value set: Perform an atomic bit-set on GPIO_OUT, i.e. `GPIO_OUT |= wdata` + register GPIO_OUT_SET_t GPIO_OUT_SET at 0xd0000014; + register uint32 GPIO_OUT_SET_raw at 0xd0000014; + + type GPIO_OUT_CLR_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output value clear + register GPIO_OUT_CLR_t GPIO_OUT_CLR at 0xd0000018; + register uint32 GPIO_OUT_CLR_raw at 0xd0000018; + + type GPIO_OUT_XOR_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output value XOR + register GPIO_OUT_XOR_t GPIO_OUT_XOR at 0xd000001c; + register uint32 GPIO_OUT_XOR_raw at 0xd000001c; + + type GPIO_OE_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output enable: Set output enable (1/0 -> output/input) for GPIO0...29. + register GPIO_OE_t GPIO_OE at 0xd0000020; + register uint32 GPIO_OE_raw at 0xd0000020; + + type GPIO_OE_SET_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output enable set: Perform an atomic bit-set on GPIO_OE, i.e. `GPIO_OE |= wdata` + register GPIO_OE_SET_t GPIO_OE_SET at 0xd0000024; + register uint32 GPIO_OE_SET_raw at 0xd0000024; + + type GPIO_OE_CLR_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output enable clear: Perform an atomic bit-clear on GPIO_OE, i.e. `GPIO_OE &= ~wdata` + register GPIO_OE_CLR_t GPIO_OE_CLR at 0xd0000028; + register uint32 GPIO_OE_CLR_raw at 0xd0000028; + + type GPIO_OE_XOR_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output enable XOR: Perform an atomic bitwise XOR on GPIO_OE, i.e. `GPIO_OE ^= wdata` + register GPIO_OE_XOR_t GPIO_OE_XOR at 0xd000002c; + register uint32 GPIO_OE_XOR_raw at 0xd000002c; + + type GPIO_HI_OUT_t { + GPIO_HI_OUT = uint6(0); // Set output level (1/0 -> high/low) for QSPI IO0...5. Reading back gives the last value written, NOT the input value from the pins. If core 0 and core 1 both write to GPIO_HI_OUT simultaneously (or to a SET/CLR/XOR alias), the result is as though the write from core 0 took place first, and the write from core 1 was then applied to that intermediate result. + _res1 = uint26(0); // Reserved, 26 bits + } + + // QSPI output value + register GPIO_HI_OUT_t GPIO_HI_OUT at 0xd0000030; + register uint32 GPIO_HI_OUT_raw at 0xd0000030; + + type GPIO_HI_OUT_SET_t { + GPIO_HI_OUT_SET = uint6(0); // Perform an atomic bit-set on GPIO_HI_OUT, i.e. `GPIO_HI_OUT |= wdata` + _res1 = uint26(0); // Reserved, 26 bits + } + + // QSPI output value set + register GPIO_HI_OUT_SET_t GPIO_HI_OUT_SET at 0xd0000034; + register uint32 GPIO_HI_OUT_SET_raw at 0xd0000034; + + type GPIO_HI_OUT_CLR_t { + GPIO_HI_OUT_CLR = uint6(0); // Perform an atomic bit-clear on GPIO_HI_OUT, i.e. `GPIO_HI_OUT &= ~wdata` + _res1 = uint26(0); // Reserved, 26 bits + } + + // QSPI output value clear + register GPIO_HI_OUT_CLR_t GPIO_HI_OUT_CLR at 0xd0000038; + register uint32 GPIO_HI_OUT_CLR_raw at 0xd0000038; + + type GPIO_HI_OUT_XOR_t { + GPIO_HI_OUT_XOR = uint6(0); // Perform an atomic bitwise XOR on GPIO_HI_OUT, i.e. `GPIO_HI_OUT ^= wdata` + _res1 = uint26(0); // Reserved, 26 bits + } + + // QSPI output value XOR + register GPIO_HI_OUT_XOR_t GPIO_HI_OUT_XOR at 0xd000003c; + register uint32 GPIO_HI_OUT_XOR_raw at 0xd000003c; + + type GPIO_HI_OE_t { + GPIO_HI_OE = uint6(0); // Set output enable (1/0 -> output/input) for QSPI IO0...5. Reading back gives the last value written. If core 0 and core 1 both write to GPIO_HI_OE simultaneously (or to a SET/CLR/XOR alias), the result is as though the write from core 0 took place first, and the write from core 1 was then applied to that intermediate result. + _res1 = uint26(0); // Reserved, 26 bits + } + + // QSPI output enable + register GPIO_HI_OE_t GPIO_HI_OE at 0xd0000040; + register uint32 GPIO_HI_OE_raw at 0xd0000040; + + type GPIO_HI_OE_SET_t { + GPIO_HI_OE_SET = uint6(0); // Perform an atomic bit-set on GPIO_HI_OE, i.e. `GPIO_HI_OE |= wdata` + _res1 = uint26(0); // Reserved, 26 bits + } + + // QSPI output enable set + register GPIO_HI_OE_SET_t GPIO_HI_OE_SET at 0xd0000044; + register uint32 GPIO_HI_OE_SET_raw at 0xd0000044; + + type GPIO_HI_OE_CLR_t { + GPIO_HI_OE_CLR = uint6(0); // Perform an atomic bit-clear on GPIO_HI_OE, i.e. `GPIO_HI_OE &= ~wdata` + _res1 = uint26(0); // Reserved, 26 bits + } + + // QSPI output enable clear + register GPIO_HI_OE_CLR_t GPIO_HI_OE_CLR at 0xd0000048; + register uint32 GPIO_HI_OE_CLR_raw at 0xd0000048; + + type GPIO_HI_OE_XOR_t { + GPIO_HI_OE_XOR = uint6(0); // Perform an atomic bitwise XOR on GPIO_HI_OE, i.e. `GPIO_HI_OE ^= wdata` + _res1 = uint26(0); // Reserved, 26 bits + } + + // QSPI output enable XOR + register GPIO_HI_OE_XOR_t GPIO_HI_OE_XOR at 0xd000004c; + register uint32 GPIO_HI_OE_XOR_raw at 0xd000004c; + + type FIFO_ST_t { + VLD = false; // Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid) + RDY = false; // Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more data) + WOF = false; // Sticky flag indicating the TX FIFO was written when full. This write was ignored by the FIFO. + ROE = false; // Sticky flag indicating the RX FIFO was read when empty. This read was ignored by the FIFO. + _res1 = uint28(0); // Reserved, 28 bits + } + + // Status register for inter-core FIFOs (mailboxes). There is one FIFO in the core 0 -> core 1 direction, and one core 1 -> core 0. Both are 32 bits wide and 8 words deep. Core 0 can see the read side of the 1->0 FIFO (RX), and the write side of 0->1 FIFO (TX). Core 1 can see the read side of the 0->1 FIFO (RX), and the write side of 1->0 FIFO (TX). The SIO IRQ for each core is the logical OR of the VLD, WOF and ROE fields of its FIFO_ST register. + register FIFO_ST_t FIFO_ST at 0xd0000050; + register uint32 FIFO_ST_raw at 0xd0000050; + + type FIFO_WR_t { + FIFO_WR = uint32(0); // + } + + // Write access to this core's TX FIFO + register FIFO_WR_t FIFO_WR at 0xd0000054; + register uint32 FIFO_WR_raw at 0xd0000054; + + type FIFO_RD_t { + FIFO_RD = uint32(0); // + } + + // Read access to this core's RX FIFO + register FIFO_RD_t FIFO_RD at 0xd0000058; + register uint32 FIFO_RD_raw at 0xd0000058; + + type SPINLOCK_ST_t { + SPINLOCK_ST = uint32(0); // + } + + // Spinlock state A bitmap containing the state of all 32 spinlocks (1=locked). Mainly intended for debugging. + register SPINLOCK_ST_t SPINLOCK_ST at 0xd000005c; + register uint32 SPINLOCK_ST_raw at 0xd000005c; + + type DIV_UDIVIDEND_t { + DIV_UDIVIDEND = uint32(0); // + } + + // Divider unsigned dividend Write to the DIVIDEND operand of the divider, i.e. the p in `p / q`. Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias starts an unsigned calculation, and the S alias starts a signed calculation. + register DIV_UDIVIDEND_t DIV_UDIVIDEND at 0xd0000060; + register uint32 DIV_UDIVIDEND_raw at 0xd0000060; + + type DIV_UDIVISOR_t { + DIV_UDIVISOR = uint32(0); // + } + + // Divider unsigned divisor Write to the DIVISOR operand of the divider, i.e. the q in `p / q`. Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. UDIVISOR/SDIVISOR are aliases of the same internal register. The U alias starts an unsigned calculation, and the S alias starts a signed calculation. + register DIV_UDIVISOR_t DIV_UDIVISOR at 0xd0000064; + register uint32 DIV_UDIVISOR_raw at 0xd0000064; + + type DIV_SDIVIDEND_t { + DIV_SDIVIDEND = uint32(0); // + } + + // Divider signed dividend The same as UDIVIDEND, but starts a signed calculation, rather than unsigned. + register DIV_SDIVIDEND_t DIV_SDIVIDEND at 0xd0000068; + register uint32 DIV_SDIVIDEND_raw at 0xd0000068; + + type DIV_SDIVISOR_t { + DIV_SDIVISOR = uint32(0); // + } + + // Divider signed divisor The same as UDIVISOR, but starts a signed calculation, rather than unsigned. + register DIV_SDIVISOR_t DIV_SDIVISOR at 0xd000006c; + register uint32 DIV_SDIVISOR_raw at 0xd000006c; + + type DIV_QUOTIENT_t { + DIV_QUOTIENT = uint32(0); // + } + + // Divider result quotient The result of `DIVIDEND / DIVISOR` (division). Contents undefined while CSR_READY is low. For signed calculations, QUOTIENT is negative when the signs of DIVIDEND and DIVISOR differ. This register can be written to directly, for context save/restore purposes. This halts any in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. Reading from QUOTIENT clears the CSR_DIRTY flag, so should read results in the order REMAINDER, QUOTIENT if CSR_DIRTY is used. + register DIV_QUOTIENT_t DIV_QUOTIENT at 0xd0000070; + register uint32 DIV_QUOTIENT_raw at 0xd0000070; + + type DIV_REMAINDER_t { + DIV_REMAINDER = uint32(0); // + } + + // Divider result remainder The result of `DIVIDEND % DIVISOR` (modulo). Contents undefined while CSR_READY is low. For signed calculations, REMAINDER is negative only when DIVIDEND is negative. This register can be written to directly, for context save/restore purposes. This halts any in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. + register DIV_REMAINDER_t DIV_REMAINDER at 0xd0000074; + register uint32 DIV_REMAINDER_raw at 0xd0000074; + + type DIV_CSR_t { + READY = false; // Reads as 0 when a calculation is in progress, 1 otherwise. Writing an operand (xDIVIDEND, xDIVISOR) will immediately start a new calculation, no matter if one is already in progress. Writing to a result register will immediately terminate any in-progress calculation and set the READY and DIRTY flags. + DIRTY = false; // Changes to 1 when any register is written, and back to 0 when QUOTIENT is read. Software can use this flag to make save/restore more efficient (skip if not DIRTY). If the flag is used in this way, it's recommended to either read QUOTIENT only, or REMAINDER and then QUOTIENT, to prevent data loss on context switch. + _res1 = uint30(0); // Reserved, 30 bits + } + + // Control and status register for divider. + register DIV_CSR_t DIV_CSR at 0xd0000078; + register uint32 DIV_CSR_raw at 0xd0000078; + + type INTERP0_ACCUM0_t { + INTERP0_ACCUM0 = uint32(0); // + } + + // Read/write access to accumulator 0 + register INTERP0_ACCUM0_t INTERP0_ACCUM0 at 0xd0000080; + register uint32 INTERP0_ACCUM0_raw at 0xd0000080; + + type INTERP0_ACCUM1_t { + INTERP0_ACCUM1 = uint32(0); // + } + + // Read/write access to accumulator 1 + register INTERP0_ACCUM1_t INTERP0_ACCUM1 at 0xd0000084; + register uint32 INTERP0_ACCUM1_raw at 0xd0000084; + + type INTERP0_BASE0_t { + INTERP0_BASE0 = uint32(0); // + } + + // Read/write access to BASE0 register. + register INTERP0_BASE0_t INTERP0_BASE0 at 0xd0000088; + register uint32 INTERP0_BASE0_raw at 0xd0000088; + + type INTERP0_BASE1_t { + INTERP0_BASE1 = uint32(0); // + } + + // Read/write access to BASE1 register. + register INTERP0_BASE1_t INTERP0_BASE1 at 0xd000008c; + register uint32 INTERP0_BASE1_raw at 0xd000008c; + + type INTERP0_BASE2_t { + INTERP0_BASE2 = uint32(0); // + } + + // Read/write access to BASE2 register. + register INTERP0_BASE2_t INTERP0_BASE2 at 0xd0000090; + register uint32 INTERP0_BASE2_raw at 0xd0000090; + + type INTERP0_POP_LANE0_t { + INTERP0_POP_LANE0 = uint32(0); // + } + + // Read LANE0 result, and simultaneously write lane results to both accumulators (POP). + register INTERP0_POP_LANE0_t INTERP0_POP_LANE0 at 0xd0000094; + register uint32 INTERP0_POP_LANE0_raw at 0xd0000094; + + type INTERP0_POP_LANE1_t { + INTERP0_POP_LANE1 = uint32(0); // + } + + // Read LANE1 result, and simultaneously write lane results to both accumulators (POP). + register INTERP0_POP_LANE1_t INTERP0_POP_LANE1 at 0xd0000098; + register uint32 INTERP0_POP_LANE1_raw at 0xd0000098; + + type INTERP0_POP_FULL_t { + INTERP0_POP_FULL = uint32(0); // + } + + // Read FULL result, and simultaneously write lane results to both accumulators (POP). + register INTERP0_POP_FULL_t INTERP0_POP_FULL at 0xd000009c; + register uint32 INTERP0_POP_FULL_raw at 0xd000009c; + + type INTERP0_PEEK_LANE0_t { + INTERP0_PEEK_LANE0 = uint32(0); // + } + + // Read LANE0 result, without altering any internal state (PEEK). + register INTERP0_PEEK_LANE0_t INTERP0_PEEK_LANE0 at 0xd00000a0; + register uint32 INTERP0_PEEK_LANE0_raw at 0xd00000a0; + + type INTERP0_PEEK_LANE1_t { + INTERP0_PEEK_LANE1 = uint32(0); // + } + + // Read LANE1 result, without altering any internal state (PEEK). + register INTERP0_PEEK_LANE1_t INTERP0_PEEK_LANE1 at 0xd00000a4; + register uint32 INTERP0_PEEK_LANE1_raw at 0xd00000a4; + + type INTERP0_PEEK_FULL_t { + INTERP0_PEEK_FULL = uint32(0); // + } + + // Read FULL result, without altering any internal state (PEEK). + register INTERP0_PEEK_FULL_t INTERP0_PEEK_FULL at 0xd00000a8; + register uint32 INTERP0_PEEK_FULL_raw at 0xd00000a8; + + type INTERP0_CTRL_LANE0_t { + SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking + MASK_LSB = uint5(0); // The least-significant bit allowed to pass by the mask (inclusive) + MASK_MSB = uint5(0); // The most-significant bit allowed to pass by the mask (inclusive) Setting MSB < LSB may cause chip to turn inside-out + SIGNED = false; // If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. + CROSS_INPUT = false; // If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_RESULT = false; // If 1, feed the opposite lane's result into this lane's accumulator on POP. + ADD_RAW = false; // If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. + FORCE_MSB = uint2(0); // ORed into bits 29:28 of the lane result presented to the processor on the bus. No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence of pointers into flash or SRAM. + BLEND = false; // Only present on INTERP0 on each core. If BLEND mode is enabled: - LANE1 result is a linear interpolation between BASE0 and BASE1, controlled by the 8 LSBs of lane 1 shift and mask value (a fractional number between 0 and 255/256ths) - LANE0 result does not have BASE0 added (yields only the 8 LSBs of lane 1 shift+mask value) - FULL result does not have lane 1 shift+mask value added (BASE2 + lane 0 shift+mask) LANE1 SIGNED flag controls whether the interpolation is signed or unsigned. + _res1 = false; // Reserved, 1 bits + OVERF0 = false; // Indicates if any masked-off MSBs in ACCUM0 are set. + OVERF1 = false; // Indicates if any masked-off MSBs in ACCUM1 are set. + OVERF = false; // Set if either OVERF0 or OVERF1 is set. + _res2 = uint6(0); // Reserved, 6 bits + } + + // Control register for lane 0 + register INTERP0_CTRL_LANE0_t INTERP0_CTRL_LANE0 at 0xd00000ac; + register uint32 INTERP0_CTRL_LANE0_raw at 0xd00000ac; + + type INTERP0_CTRL_LANE1_t { + SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking + MASK_LSB = uint5(0); // The least-significant bit allowed to pass by the mask (inclusive) + MASK_MSB = uint5(0); // The most-significant bit allowed to pass by the mask (inclusive) Setting MSB < LSB may cause chip to turn inside-out + SIGNED = false; // If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. + CROSS_INPUT = false; // If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_RESULT = false; // If 1, feed the opposite lane's result into this lane's accumulator on POP. + ADD_RAW = false; // If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. + FORCE_MSB = uint2(0); // ORed into bits 29:28 of the lane result presented to the processor on the bus. No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence of pointers into flash or SRAM. + _res1 = uint11(0); // Reserved, 11 bits + } + + // Control register for lane 1 + register INTERP0_CTRL_LANE1_t INTERP0_CTRL_LANE1 at 0xd00000b0; + register uint32 INTERP0_CTRL_LANE1_raw at 0xd00000b0; + + type INTERP0_ACCUM0_ADD_t { + INTERP0_ACCUM0_ADD = uint24(0); // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Values written here are atomically added to ACCUM0 Reading yields lane 0's raw shift and mask value (BASE0 not added). + register INTERP0_ACCUM0_ADD_t INTERP0_ACCUM0_ADD at 0xd00000b4; + register uint32 INTERP0_ACCUM0_ADD_raw at 0xd00000b4; + + type INTERP0_ACCUM1_ADD_t { + INTERP0_ACCUM1_ADD = uint24(0); // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Values written here are atomically added to ACCUM1 Reading yields lane 1's raw shift and mask value (BASE1 not added). + register INTERP0_ACCUM1_ADD_t INTERP0_ACCUM1_ADD at 0xd00000b8; + register uint32 INTERP0_ACCUM1_ADD_raw at 0xd00000b8; + + type INTERP0_BASE_1AND0_t { + INTERP0_BASE_1AND0 = uint32(0); // + } + + // On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + register INTERP0_BASE_1AND0_t INTERP0_BASE_1AND0 at 0xd00000bc; + register uint32 INTERP0_BASE_1AND0_raw at 0xd00000bc; + + type INTERP1_ACCUM0_t { + INTERP1_ACCUM0 = uint32(0); // + } + + // Read/write access to accumulator 0 + register INTERP1_ACCUM0_t INTERP1_ACCUM0 at 0xd00000c0; + register uint32 INTERP1_ACCUM0_raw at 0xd00000c0; + + type INTERP1_ACCUM1_t { + INTERP1_ACCUM1 = uint32(0); // + } + + // Read/write access to accumulator 1 + register INTERP1_ACCUM1_t INTERP1_ACCUM1 at 0xd00000c4; + register uint32 INTERP1_ACCUM1_raw at 0xd00000c4; + + type INTERP1_BASE0_t { + INTERP1_BASE0 = uint32(0); // + } + + // Read/write access to BASE0 register. + register INTERP1_BASE0_t INTERP1_BASE0 at 0xd00000c8; + register uint32 INTERP1_BASE0_raw at 0xd00000c8; + + type INTERP1_BASE1_t { + INTERP1_BASE1 = uint32(0); // + } + + // Read/write access to BASE1 register. + register INTERP1_BASE1_t INTERP1_BASE1 at 0xd00000cc; + register uint32 INTERP1_BASE1_raw at 0xd00000cc; + + type INTERP1_BASE2_t { + INTERP1_BASE2 = uint32(0); // + } + + // Read/write access to BASE2 register. + register INTERP1_BASE2_t INTERP1_BASE2 at 0xd00000d0; + register uint32 INTERP1_BASE2_raw at 0xd00000d0; + + type INTERP1_POP_LANE0_t { + INTERP1_POP_LANE0 = uint32(0); // + } + + // Read LANE0 result, and simultaneously write lane results to both accumulators (POP). + register INTERP1_POP_LANE0_t INTERP1_POP_LANE0 at 0xd00000d4; + register uint32 INTERP1_POP_LANE0_raw at 0xd00000d4; + + type INTERP1_POP_LANE1_t { + INTERP1_POP_LANE1 = uint32(0); // + } + + // Read LANE1 result, and simultaneously write lane results to both accumulators (POP). + register INTERP1_POP_LANE1_t INTERP1_POP_LANE1 at 0xd00000d8; + register uint32 INTERP1_POP_LANE1_raw at 0xd00000d8; + + type INTERP1_POP_FULL_t { + INTERP1_POP_FULL = uint32(0); // + } + + // Read FULL result, and simultaneously write lane results to both accumulators (POP). + register INTERP1_POP_FULL_t INTERP1_POP_FULL at 0xd00000dc; + register uint32 INTERP1_POP_FULL_raw at 0xd00000dc; + + type INTERP1_PEEK_LANE0_t { + INTERP1_PEEK_LANE0 = uint32(0); // + } + + // Read LANE0 result, without altering any internal state (PEEK). + register INTERP1_PEEK_LANE0_t INTERP1_PEEK_LANE0 at 0xd00000e0; + register uint32 INTERP1_PEEK_LANE0_raw at 0xd00000e0; + + type INTERP1_PEEK_LANE1_t { + INTERP1_PEEK_LANE1 = uint32(0); // + } + + // Read LANE1 result, without altering any internal state (PEEK). + register INTERP1_PEEK_LANE1_t INTERP1_PEEK_LANE1 at 0xd00000e4; + register uint32 INTERP1_PEEK_LANE1_raw at 0xd00000e4; + + type INTERP1_PEEK_FULL_t { + INTERP1_PEEK_FULL = uint32(0); // + } + + // Read FULL result, without altering any internal state (PEEK). + register INTERP1_PEEK_FULL_t INTERP1_PEEK_FULL at 0xd00000e8; + register uint32 INTERP1_PEEK_FULL_raw at 0xd00000e8; + + type INTERP1_CTRL_LANE0_t { + SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking + MASK_LSB = uint5(0); // The least-significant bit allowed to pass by the mask (inclusive) + MASK_MSB = uint5(0); // The most-significant bit allowed to pass by the mask (inclusive) Setting MSB < LSB may cause chip to turn inside-out + SIGNED = false; // If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. + CROSS_INPUT = false; // If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_RESULT = false; // If 1, feed the opposite lane's result into this lane's accumulator on POP. + ADD_RAW = false; // If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. + FORCE_MSB = uint2(0); // ORed into bits 29:28 of the lane result presented to the processor on the bus. No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence of pointers into flash or SRAM. + _res1 = false; // Reserved, 1 bits + CLAMP = false; // Only present on INTERP1 on each core. If CLAMP mode is enabled: - LANE0 result is shifted and masked ACCUM0, clamped by a lower bound of BASE0 and an upper bound of BASE1. - Signedness of these comparisons is determined by LANE0_CTRL_SIGNED + OVERF0 = false; // Indicates if any masked-off MSBs in ACCUM0 are set. + OVERF1 = false; // Indicates if any masked-off MSBs in ACCUM1 are set. + OVERF = false; // Set if either OVERF0 or OVERF1 is set. + _res2 = uint6(0); // Reserved, 6 bits + } + + // Control register for lane 0 + register INTERP1_CTRL_LANE0_t INTERP1_CTRL_LANE0 at 0xd00000ec; + register uint32 INTERP1_CTRL_LANE0_raw at 0xd00000ec; + + type INTERP1_CTRL_LANE1_t { + SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking + MASK_LSB = uint5(0); // The least-significant bit allowed to pass by the mask (inclusive) + MASK_MSB = uint5(0); // The most-significant bit allowed to pass by the mask (inclusive) Setting MSB < LSB may cause chip to turn inside-out + SIGNED = false; // If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. + CROSS_INPUT = false; // If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_RESULT = false; // If 1, feed the opposite lane's result into this lane's accumulator on POP. + ADD_RAW = false; // If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. + FORCE_MSB = uint2(0); // ORed into bits 29:28 of the lane result presented to the processor on the bus. No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence of pointers into flash or SRAM. + _res1 = uint11(0); // Reserved, 11 bits + } + + // Control register for lane 1 + register INTERP1_CTRL_LANE1_t INTERP1_CTRL_LANE1 at 0xd00000f0; + register uint32 INTERP1_CTRL_LANE1_raw at 0xd00000f0; + + type INTERP1_ACCUM0_ADD_t { + INTERP1_ACCUM0_ADD = uint24(0); // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Values written here are atomically added to ACCUM0 Reading yields lane 0's raw shift and mask value (BASE0 not added). + register INTERP1_ACCUM0_ADD_t INTERP1_ACCUM0_ADD at 0xd00000f4; + register uint32 INTERP1_ACCUM0_ADD_raw at 0xd00000f4; + + type INTERP1_ACCUM1_ADD_t { + INTERP1_ACCUM1_ADD = uint24(0); // + _res1 = uint8(0); // Reserved, 8 bits + } + + // Values written here are atomically added to ACCUM1 Reading yields lane 1's raw shift and mask value (BASE1 not added). + register INTERP1_ACCUM1_ADD_t INTERP1_ACCUM1_ADD at 0xd00000f8; + register uint32 INTERP1_ACCUM1_ADD_raw at 0xd00000f8; + + type INTERP1_BASE_1AND0_t { + INTERP1_BASE_1AND0 = uint32(0); // + } + + // On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + register INTERP1_BASE_1AND0_t INTERP1_BASE_1AND0 at 0xd00000fc; + register uint32 INTERP1_BASE_1AND0_raw at 0xd00000fc; + + type SPINLOCK0_t { + SPINLOCK0 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK0_t SPINLOCK0 at 0xd0000100; + register uint32 SPINLOCK0_raw at 0xd0000100; + + type SPINLOCK1_t { + SPINLOCK1 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK1_t SPINLOCK1 at 0xd0000104; + register uint32 SPINLOCK1_raw at 0xd0000104; + + type SPINLOCK2_t { + SPINLOCK2 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK2_t SPINLOCK2 at 0xd0000108; + register uint32 SPINLOCK2_raw at 0xd0000108; + + type SPINLOCK3_t { + SPINLOCK3 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK3_t SPINLOCK3 at 0xd000010c; + register uint32 SPINLOCK3_raw at 0xd000010c; + + type SPINLOCK4_t { + SPINLOCK4 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK4_t SPINLOCK4 at 0xd0000110; + register uint32 SPINLOCK4_raw at 0xd0000110; + + type SPINLOCK5_t { + SPINLOCK5 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK5_t SPINLOCK5 at 0xd0000114; + register uint32 SPINLOCK5_raw at 0xd0000114; + + type SPINLOCK6_t { + SPINLOCK6 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK6_t SPINLOCK6 at 0xd0000118; + register uint32 SPINLOCK6_raw at 0xd0000118; + + type SPINLOCK7_t { + SPINLOCK7 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK7_t SPINLOCK7 at 0xd000011c; + register uint32 SPINLOCK7_raw at 0xd000011c; + + type SPINLOCK8_t { + SPINLOCK8 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK8_t SPINLOCK8 at 0xd0000120; + register uint32 SPINLOCK8_raw at 0xd0000120; + + type SPINLOCK9_t { + SPINLOCK9 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK9_t SPINLOCK9 at 0xd0000124; + register uint32 SPINLOCK9_raw at 0xd0000124; + + type SPINLOCK10_t { + SPINLOCK10 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK10_t SPINLOCK10 at 0xd0000128; + register uint32 SPINLOCK10_raw at 0xd0000128; + + type SPINLOCK11_t { + SPINLOCK11 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK11_t SPINLOCK11 at 0xd000012c; + register uint32 SPINLOCK11_raw at 0xd000012c; + + type SPINLOCK12_t { + SPINLOCK12 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK12_t SPINLOCK12 at 0xd0000130; + register uint32 SPINLOCK12_raw at 0xd0000130; + + type SPINLOCK13_t { + SPINLOCK13 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK13_t SPINLOCK13 at 0xd0000134; + register uint32 SPINLOCK13_raw at 0xd0000134; + + type SPINLOCK14_t { + SPINLOCK14 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK14_t SPINLOCK14 at 0xd0000138; + register uint32 SPINLOCK14_raw at 0xd0000138; + + type SPINLOCK15_t { + SPINLOCK15 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK15_t SPINLOCK15 at 0xd000013c; + register uint32 SPINLOCK15_raw at 0xd000013c; + + type SPINLOCK16_t { + SPINLOCK16 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK16_t SPINLOCK16 at 0xd0000140; + register uint32 SPINLOCK16_raw at 0xd0000140; + + type SPINLOCK17_t { + SPINLOCK17 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK17_t SPINLOCK17 at 0xd0000144; + register uint32 SPINLOCK17_raw at 0xd0000144; + + type SPINLOCK18_t { + SPINLOCK18 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK18_t SPINLOCK18 at 0xd0000148; + register uint32 SPINLOCK18_raw at 0xd0000148; + + type SPINLOCK19_t { + SPINLOCK19 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK19_t SPINLOCK19 at 0xd000014c; + register uint32 SPINLOCK19_raw at 0xd000014c; + + type SPINLOCK20_t { + SPINLOCK20 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK20_t SPINLOCK20 at 0xd0000150; + register uint32 SPINLOCK20_raw at 0xd0000150; + + type SPINLOCK21_t { + SPINLOCK21 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK21_t SPINLOCK21 at 0xd0000154; + register uint32 SPINLOCK21_raw at 0xd0000154; + + type SPINLOCK22_t { + SPINLOCK22 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK22_t SPINLOCK22 at 0xd0000158; + register uint32 SPINLOCK22_raw at 0xd0000158; + + type SPINLOCK23_t { + SPINLOCK23 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK23_t SPINLOCK23 at 0xd000015c; + register uint32 SPINLOCK23_raw at 0xd000015c; + + type SPINLOCK24_t { + SPINLOCK24 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK24_t SPINLOCK24 at 0xd0000160; + register uint32 SPINLOCK24_raw at 0xd0000160; + + type SPINLOCK25_t { + SPINLOCK25 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK25_t SPINLOCK25 at 0xd0000164; + register uint32 SPINLOCK25_raw at 0xd0000164; + + type SPINLOCK26_t { + SPINLOCK26 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK26_t SPINLOCK26 at 0xd0000168; + register uint32 SPINLOCK26_raw at 0xd0000168; + + type SPINLOCK27_t { + SPINLOCK27 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK27_t SPINLOCK27 at 0xd000016c; + register uint32 SPINLOCK27_raw at 0xd000016c; + + type SPINLOCK28_t { + SPINLOCK28 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK28_t SPINLOCK28 at 0xd0000170; + register uint32 SPINLOCK28_raw at 0xd0000170; + + type SPINLOCK29_t { + SPINLOCK29 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK29_t SPINLOCK29 at 0xd0000174; + register uint32 SPINLOCK29_raw at 0xd0000174; + + type SPINLOCK30_t { + SPINLOCK30 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK30_t SPINLOCK30 at 0xd0000178; + register uint32 SPINLOCK30_raw at 0xd0000178; + + type SPINLOCK31_t { + SPINLOCK31 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK31_t SPINLOCK31 at 0xd000017c; + register uint32 SPINLOCK31_raw at 0xd000017c; + + +/* Types and registers for USB + USB FS/LS controller device registers + */ + + type ADDR_ENDP_t { + ADDRESS = uint7(0); // In device mode, the address that the device should respond to. Set in response to a SET_ADDR setup packet from the host. In host mode set to the address of the device to communicate with. + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Device endpoint to send data to. Only valid for HOST mode. + _res2 = uint12(0); // Reserved, 12 bits + } + + // Device address and endpoint control + register ADDR_ENDP_t ADDR_ENDP at 0x50110000; + register uint32 ADDR_ENDP_raw at 0x50110000; + + type ADDR_ENDP1_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 1. Only valid for HOST mode. + register ADDR_ENDP1_t ADDR_ENDP1 at 0x50110004; + register uint32 ADDR_ENDP1_raw at 0x50110004; + + type ADDR_ENDP2_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 2. Only valid for HOST mode. + register ADDR_ENDP2_t ADDR_ENDP2 at 0x50110008; + register uint32 ADDR_ENDP2_raw at 0x50110008; + + type ADDR_ENDP3_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 3. Only valid for HOST mode. + register ADDR_ENDP3_t ADDR_ENDP3 at 0x5011000c; + register uint32 ADDR_ENDP3_raw at 0x5011000c; + + type ADDR_ENDP4_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 4. Only valid for HOST mode. + register ADDR_ENDP4_t ADDR_ENDP4 at 0x50110010; + register uint32 ADDR_ENDP4_raw at 0x50110010; + + type ADDR_ENDP5_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 5. Only valid for HOST mode. + register ADDR_ENDP5_t ADDR_ENDP5 at 0x50110014; + register uint32 ADDR_ENDP5_raw at 0x50110014; + + type ADDR_ENDP6_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 6. Only valid for HOST mode. + register ADDR_ENDP6_t ADDR_ENDP6 at 0x50110018; + register uint32 ADDR_ENDP6_raw at 0x50110018; + + type ADDR_ENDP7_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 7. Only valid for HOST mode. + register ADDR_ENDP7_t ADDR_ENDP7 at 0x5011001c; + register uint32 ADDR_ENDP7_raw at 0x5011001c; + + type ADDR_ENDP8_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 8. Only valid for HOST mode. + register ADDR_ENDP8_t ADDR_ENDP8 at 0x50110020; + register uint32 ADDR_ENDP8_raw at 0x50110020; + + type ADDR_ENDP9_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 9. Only valid for HOST mode. + register ADDR_ENDP9_t ADDR_ENDP9 at 0x50110024; + register uint32 ADDR_ENDP9_raw at 0x50110024; + + type ADDR_ENDP10_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 10. Only valid for HOST mode. + register ADDR_ENDP10_t ADDR_ENDP10 at 0x50110028; + register uint32 ADDR_ENDP10_raw at 0x50110028; + + type ADDR_ENDP11_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 11. Only valid for HOST mode. + register ADDR_ENDP11_t ADDR_ENDP11 at 0x5011002c; + register uint32 ADDR_ENDP11_raw at 0x5011002c; + + type ADDR_ENDP12_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 12. Only valid for HOST mode. + register ADDR_ENDP12_t ADDR_ENDP12 at 0x50110030; + register uint32 ADDR_ENDP12_raw at 0x50110030; + + type ADDR_ENDP13_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 13. Only valid for HOST mode. + register ADDR_ENDP13_t ADDR_ENDP13 at 0x50110034; + register uint32 ADDR_ENDP13_raw at 0x50110034; + + type ADDR_ENDP14_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 14. Only valid for HOST mode. + register ADDR_ENDP14_t ADDR_ENDP14 at 0x50110038; + register uint32 ADDR_ENDP14_raw at 0x50110038; + + type ADDR_ENDP15_t { + ADDRESS = uint7(0); // Device address + _res1 = uint9(0); // Reserved, 9 bits + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res2 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits + } + + // Interrupt endpoint 15. Only valid for HOST mode. + register ADDR_ENDP15_t ADDR_ENDP15 at 0x5011003c; + register uint32 ADDR_ENDP15_raw at 0x5011003c; + + type MAIN_CTRL_t { + CONTROLLER_EN = false; // Enable controller + HOST_NDEVICE = false; // Device mode = 0, Host mode = 1 + _res1 = uint29(0); // Reserved, 29 bits + SIM_TIMING = false; // Reduced timings for simulation + } + + // Main control register + register MAIN_CTRL_t MAIN_CTRL at 0x50110040; + register uint32 MAIN_CTRL_raw at 0x50110040; + + type SOF_WR_t { + COUNT = uint11(0); // + _res1 = uint21(0); // Reserved, 21 bits + } + + // Set the SOF (Start of Frame) frame number in the host controller. The SOF packet is sent every 1ms and the host will increment the frame number by 1 each time. + register SOF_WR_t SOF_WR at 0x50110044; + register uint32 SOF_WR_raw at 0x50110044; + + type SOF_RD_t { + COUNT = uint11(0); // + _res1 = uint21(0); // Reserved, 21 bits + } + + // Read the last SOF (Start of Frame) frame number seen. In device mode the last SOF received from the host. In host mode the last SOF sent by the host. + register SOF_RD_t SOF_RD at 0x50110048; + register uint32 SOF_RD_raw at 0x50110048; + + type SIE_CTRL_t { + START_TRANS = false; // Host: Start transaction + SEND_SETUP = false; // Host: Send Setup packet + SEND_DATA = false; // Host: Send transaction (OUT from host) + RECEIVE_DATA = false; // Host: Receive transaction (IN to host) + STOP_TRANS = false; // Host: Stop transaction + _res1 = false; // Reserved, 1 bits + PREAMBLE_EN = false; // Host: Preable enable for LS device on FS hub + _res2 = false; // Reserved, 1 bits + SOF_SYNC = false; // Host: Delay packet(s) until after SOF + SOF_EN = false; // Host: Enable SOF generation (for full speed bus) + KEEP_ALIVE_EN = false; // Host: Enable keep alive packet (for low speed bus) + VBUS_EN = false; // Host: Enable VBUS + RESUME = false; // Device: Remote wakeup. Device can initiate its own resume after suspend. + RESET_BUS = false; // Host: Reset bus + _res3 = false; // Reserved, 1 bits + PULLDOWN_EN = false; // Host: Enable pull down resistors + PULLUP_EN = false; // Device: Enable pull up resistor + RPU_OPT = false; // Device: Pull-up strength (0=1K2, 1=2k3) + TRANSCEIVER_PD = false; // Power down bus transceiver + _res4 = uint5(0); // Reserved, 5 bits + DIRECT_DM = false; // Direct control of DM + DIRECT_DP = false; // Direct control of DP + DIRECT_EN = false; // Direct bus drive enable + EP0_INT_NAK = false; // Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a NAK + EP0_INT_2BUF = false; // Device: Set bit in BUFF_STATUS for every 2 buffers completed on EP0 + EP0_INT_1BUF = false; // Device: Set bit in BUFF_STATUS for every buffer completed on EP0 + EP0_DOUBLE_BUF = false; // Device: EP0 single buffered = 0, double buffered = 1 + EP0_INT_STALL = false; // Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a STALL + } + + // SIE control register + register SIE_CTRL_t SIE_CTRL at 0x5011004c; + register uint32 SIE_CTRL_raw at 0x5011004c; + + type SIE_STATUS_t { + VBUS_DETECTED = false; // Device: VBUS Detected + _res1 = false; // Reserved, 1 bits + LINE_STATE = uint2(0); // USB bus line state + SUSPENDED = false; // Bus in suspended state. Valid for device and host. Host and device will go into suspend if neither Keep Alive / SOF frames are enabled. + _res2 = uint3(0); // Reserved, 3 bits + SPEED = uint2(0); // Host: device speed. Disconnected = 00, LS = 01, FS = 10 + VBUS_OVER_CURR = false; // VBUS over current detected + RESUME = false; // Host: Device has initiated a remote resume. Device: host has initiated a resume. + _res3 = uint4(0); // Reserved, 4 bits + CONNECTED = false; // Device: connected + SETUP_REC = false; // Device: Setup packet received + TRANS_COMPLETE = false; // Transaction complete. Raised by device if: * An IN or OUT packet is sent with the `LAST_BUFF` bit set in the buffer control register Raised by host if: * A setup packet is sent when no data in or data out transaction follows * An IN packet is received and the `LAST_BUFF` bit is set in the buffer control register * An IN packet is received with zero length * An OUT packet is sent and the `LAST_BUFF` bit is set + BUS_RESET = false; // Device: bus reset received + _res4 = uint4(0); // Reserved, 4 bits + CRC_ERROR = false; // CRC Error. Raised by the Serial RX engine. + BIT_STUFF_ERROR = false; // Bit Stuff Error. Raised by the Serial RX engine. + RX_OVERFLOW = false; // RX overflow is raised by the Serial RX engine if the incoming data is too fast. + RX_TIMEOUT = false; // RX timeout is raised by both the host and device if an ACK is not received in the maximum time specified by the USB spec. + NAK_REC = false; // Host: NAK received + STALL_REC = false; // Host: STALL received + ACK_REC = false; // ACK received. Raised by both host and device. + DATA_SEQ_ERROR = false; // Data Sequence Error. The device can raise a sequence error in the following conditions: * A SETUP packet is received followed by a DATA1 packet (data phase should always be DATA0) * An OUT packet is received from the host but doesn't match the data pid in the buffer control register read from DPSRAM The host can raise a data sequence error in the following conditions: * An IN packet from the device has the wrong data PID + } + + // SIE status register + register SIE_STATUS_t SIE_STATUS at 0x50110050; + register uint32 SIE_STATUS_raw at 0x50110050; + + type INT_EP_CTRL_t { + _res1 = false; // Reserved, 1 bits + INT_EP_ACTIVE = uint15(0); // Host: Enable interrupt endpoint 1 => 15 + _res2 = uint16(0); // Reserved, 16 bits + } + + // interrupt endpoint control register + register INT_EP_CTRL_t INT_EP_CTRL at 0x50110054; + register uint32 INT_EP_CTRL_raw at 0x50110054; + + type BUFF_STATUS_t { + EP0_IN = false; // + EP0_OUT = false; // + EP1_IN = false; // + EP1_OUT = false; // + EP2_IN = false; // + EP2_OUT = false; // + EP3_IN = false; // + EP3_OUT = false; // + EP4_IN = false; // + EP4_OUT = false; // + EP5_IN = false; // + EP5_OUT = false; // + EP6_IN = false; // + EP6_OUT = false; // + EP7_IN = false; // + EP7_OUT = false; // + EP8_IN = false; // + EP8_OUT = false; // + EP9_IN = false; // + EP9_OUT = false; // + EP10_IN = false; // + EP10_OUT = false; // + EP11_IN = false; // + EP11_OUT = false; // + EP12_IN = false; // + EP12_OUT = false; // + EP13_IN = false; // + EP13_OUT = false; // + EP14_IN = false; // + EP14_OUT = false; // + EP15_IN = false; // + EP15_OUT = false; // + } + + // Buffer status register. A bit set here indicates that a buffer has completed on the endpoint (if the buffer interrupt is enabled). It is possible for 2 buffers to be completed, so clearing the buffer status bit may instantly re set it on the next clock cycle. + register BUFF_STATUS_t BUFF_STATUS at 0x50110058; + register uint32 BUFF_STATUS_raw at 0x50110058; + + type BUFF_CPU_SHOULD_HANDLE_t { + EP0_IN = false; // + EP0_OUT = false; // + EP1_IN = false; // + EP1_OUT = false; // + EP2_IN = false; // + EP2_OUT = false; // + EP3_IN = false; // + EP3_OUT = false; // + EP4_IN = false; // + EP4_OUT = false; // + EP5_IN = false; // + EP5_OUT = false; // + EP6_IN = false; // + EP6_OUT = false; // + EP7_IN = false; // + EP7_OUT = false; // + EP8_IN = false; // + EP8_OUT = false; // + EP9_IN = false; // + EP9_OUT = false; // + EP10_IN = false; // + EP10_OUT = false; // + EP11_IN = false; // + EP11_OUT = false; // + EP12_IN = false; // + EP12_OUT = false; // + EP13_IN = false; // + EP13_OUT = false; // + EP14_IN = false; // + EP14_OUT = false; // + EP15_IN = false; // + EP15_OUT = false; // + } + + // Which of the double buffers should be handled. Only valid if using an interrupt per buffer (i.e. not per 2 buffers). Not valid for host interrupt endpoint polling because they are only single buffered. + register BUFF_CPU_SHOULD_HANDLE_t BUFF_CPU_SHOULD_HANDLE at 0x5011005c; + register uint32 BUFF_CPU_SHOULD_HANDLE_raw at 0x5011005c; + + type EP_ABORT_t { + EP0_IN = false; // + EP0_OUT = false; // + EP1_IN = false; // + EP1_OUT = false; // + EP2_IN = false; // + EP2_OUT = false; // + EP3_IN = false; // + EP3_OUT = false; // + EP4_IN = false; // + EP4_OUT = false; // + EP5_IN = false; // + EP5_OUT = false; // + EP6_IN = false; // + EP6_OUT = false; // + EP7_IN = false; // + EP7_OUT = false; // + EP8_IN = false; // + EP8_OUT = false; // + EP9_IN = false; // + EP9_OUT = false; // + EP10_IN = false; // + EP10_OUT = false; // + EP11_IN = false; // + EP11_OUT = false; // + EP12_IN = false; // + EP12_OUT = false; // + EP13_IN = false; // + EP13_OUT = false; // + EP14_IN = false; // + EP14_OUT = false; // + EP15_IN = false; // + EP15_OUT = false; // + } + + // Device only: Can be set to ignore the buffer control register for this endpoint in case you would like to revoke a buffer. A NAK will be sent for every access to the endpoint until this bit is cleared. A corresponding bit in `EP_ABORT_DONE` is set when it is safe to modify the buffer control register. + register EP_ABORT_t EP_ABORT at 0x50110060; + register uint32 EP_ABORT_raw at 0x50110060; + + type EP_ABORT_DONE_t { + EP0_IN = false; // + EP0_OUT = false; // + EP1_IN = false; // + EP1_OUT = false; // + EP2_IN = false; // + EP2_OUT = false; // + EP3_IN = false; // + EP3_OUT = false; // + EP4_IN = false; // + EP4_OUT = false; // + EP5_IN = false; // + EP5_OUT = false; // + EP6_IN = false; // + EP6_OUT = false; // + EP7_IN = false; // + EP7_OUT = false; // + EP8_IN = false; // + EP8_OUT = false; // + EP9_IN = false; // + EP9_OUT = false; // + EP10_IN = false; // + EP10_OUT = false; // + EP11_IN = false; // + EP11_OUT = false; // + EP12_IN = false; // + EP12_OUT = false; // + EP13_IN = false; // + EP13_OUT = false; // + EP14_IN = false; // + EP14_OUT = false; // + EP15_IN = false; // + EP15_OUT = false; // + } + + // Device only: Used in conjunction with `EP_ABORT`. Set once an endpoint is idle so the programmer knows it is safe to modify the buffer control register. + register EP_ABORT_DONE_t EP_ABORT_DONE at 0x50110064; + register uint32 EP_ABORT_DONE_raw at 0x50110064; + + type EP_STALL_ARM_t { + EP0_IN = false; // + EP0_OUT = false; // + _res1 = uint30(0); // Reserved, 30 bits + } + + // Device: this bit must be set in conjunction with the `STALL` bit in the buffer control register to send a STALL on EP0. The device controller clears these bits when a SETUP packet is received because the USB spec requires that a STALL condition is cleared when a SETUP packet is received. + register EP_STALL_ARM_t EP_STALL_ARM at 0x50110068; + register uint32 EP_STALL_ARM_raw at 0x50110068; + + type NAK_POLL_t { + DELAY_LS = uint10(0); // NAK polling interval for a low speed device + _res1 = uint6(0); // Reserved, 6 bits + DELAY_FS = uint10(0); // NAK polling interval for a full speed device + _res2 = uint6(0); // Reserved, 6 bits + } + + // Used by the host controller. Sets the wait time in microseconds before trying again if the device replies with a NAK. + register NAK_POLL_t NAK_POLL at 0x5011006c; + register uint32 NAK_POLL_raw at 0x5011006c; + + type EP_STATUS_STALL_NAK_t { + EP0_IN = false; // + EP0_OUT = false; // + EP1_IN = false; // + EP1_OUT = false; // + EP2_IN = false; // + EP2_OUT = false; // + EP3_IN = false; // + EP3_OUT = false; // + EP4_IN = false; // + EP4_OUT = false; // + EP5_IN = false; // + EP5_OUT = false; // + EP6_IN = false; // + EP6_OUT = false; // + EP7_IN = false; // + EP7_OUT = false; // + EP8_IN = false; // + EP8_OUT = false; // + EP9_IN = false; // + EP9_OUT = false; // + EP10_IN = false; // + EP10_OUT = false; // + EP11_IN = false; // + EP11_OUT = false; // + EP12_IN = false; // + EP12_OUT = false; // + EP13_IN = false; // + EP13_OUT = false; // + EP14_IN = false; // + EP14_OUT = false; // + EP15_IN = false; // + EP15_OUT = false; // + } + + // Device: bits are set when the `IRQ_ON_NAK` or `IRQ_ON_STALL` bits are set. For EP0 this comes from `SIE_CTRL`. For all other endpoints it comes from the endpoint control register. + register EP_STATUS_STALL_NAK_t EP_STATUS_STALL_NAK at 0x50110070; + register uint32 EP_STATUS_STALL_NAK_raw at 0x50110070; + + type USB_MUXING_t { + TO_PHY = false; // + TO_EXTPHY = false; // + TO_DIGITAL_PAD = false; // + SOFTCON = false; // + _res1 = uint28(0); // Reserved, 28 bits + } + + // Where to connect the USB controller. Should be to_phy by default. + register USB_MUXING_t USB_MUXING at 0x50110074; + register uint32 USB_MUXING_raw at 0x50110074; + + type USB_PWR_t { + VBUS_EN = false; // + VBUS_EN_OVERRIDE_EN = false; // + VBUS_DETECT = false; // + VBUS_DETECT_OVERRIDE_EN = false; // + OVERCURR_DETECT = false; // + OVERCURR_DETECT_EN = false; // + _res1 = uint26(0); // Reserved, 26 bits + } + + // Overrides for the power signals in the event that the VBUS signals are not hooked up to GPIO. Set the value of the override and then the override enable so switch over to the override value. + register USB_PWR_t USB_PWR at 0x50110078; + register uint32 USB_PWR_raw at 0x50110078; + + type USBPHY_DIRECT_t { + DP_PULLUP_HISEL = false; // when dp_pullup_en is set high, this enables second resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + DP_PULLUP_EN = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + DP_PULLDN_EN = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller 1 - Enable Rpd on DPP + _res1 = false; // Reserved, 1 bits + DM_PULLUP_HISEL = false; // when dm_pullup_en is set high, this enables second resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + DM_PULLUP_EN = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller 1 - Enable Rpu on DPM + DM_PULLDN_EN = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller 1 - Enable Rpd on DPM + _res2 = false; // Reserved, 1 bits + TX_DP_OE = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller TX_SEMODE=0, OE for DPP/DPM diff pair. 0 - DPP/DPM in Hi-Z state; 1 - DPP/DPM driving TX_SEMODE=1, OE for DPP only. 0 - DPP in Hi-Z state; 1 - DPP driving + TX_DM_OE = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller TX_SEMODE=0, Ignored. TX_SEMODE=1, OE for DPM only. 0 - DPM in Hi-Z state; 1 - DPM driving + TX_DP = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller TX_SEMODE=0, Drives DPP/DPM diff pair. TX_DP_OE=1 to enable drive. DPP=TX_DP, DPM=~TX_DP TX_SEMODE=1, Drives DPP only. TX_DP_OE=1 to enable drive. DPP=TX_DP + TX_DM = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller TX_SEMODE=0, Ignored TX_SEMODE=1, Drives DPM only. TX_DM_OE=1 to enable drive. DPM=TX_DM + RX_PD = false; // + TX_PD = false; // + TX_FSSLEW = false; // + TX_DIFFMODE = false; // + RX_DD = false; // Status bit from USB PHY RX Diff data + RX_DP = false; // Status bit from USB PHY DPP pin state + RX_DM = false; // Status bit from USB PHY DPM pin state + DP_OVCN = false; // Status bit from USB PHY + DM_OVCN = false; // Status bit from USB PHY + DP_OVV = false; // Status bit from USB PHY + DM_OVV = false; // Status bit from USB PHY + _res3 = uint9(0); // Reserved, 9 bits + } + + // Note that most functions are driven directly from usb_fsls controller. This register allows more detailed control/status from the USB PHY. Useful for debug but not expected to be used in normal operation Use in conjunction with usbphy_direct_override register + register USBPHY_DIRECT_t USBPHY_DIRECT at 0x5011007c; + register uint32 USBPHY_DIRECT_raw at 0x5011007c; + + type USBPHY_DIRECT_OVERRIDE_t { + DP_PULLUP_HISEL_OVERRIDE_EN = false; // + DM_PULLUP_HISEL_OVERRIDE_EN = false; // + DP_PULLUP_EN_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + DP_PULLDN_EN_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + DM_PULLDN_EN_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + TX_DP_OE_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + TX_DM_OE_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + TX_DP_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + TX_DM_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + RX_PD_OVERRIDE_EN = false; // + TX_PD_OVERRIDE_EN = false; // + TX_FSSLEW_OVERRIDE_EN = false; // + DM_PULLUP_OVERRIDE_EN = false; // + _res1 = uint2(0); // Reserved, 2 bits + TX_DIFFMODE_OVERRIDE_EN = false; // + _res2 = uint16(0); // Reserved, 16 bits + } + + // + register USBPHY_DIRECT_OVERRIDE_t USBPHY_DIRECT_OVERRIDE at 0x50110080; + register uint32 USBPHY_DIRECT_OVERRIDE_raw at 0x50110080; + + type USBPHY_TRIM_t { + DP_PULLDN_TRIM = uint5(0); // Value to drive to USB PHY DP pulldown resistor trim control Experimental data suggests that the reset value will work, but this register allows adjustment if required + _res1 = uint3(0); // Reserved, 3 bits + DM_PULLDN_TRIM = uint5(0); // Value to drive to USB PHY DM pulldown resistor trim control Experimental data suggests that the reset value will work, but this register allows adjustment if required + _res2 = uint19(0); // Reserved, 19 bits + } + + // Note that most functions are driven directly from usb_fsls controller. This register allows more detailed control/status from the USB PHY. Useful for debug but not expected to be used in normal operation + register USBPHY_TRIM_t USBPHY_TRIM at 0x50110084; + register uint32 USBPHY_TRIM_raw at 0x50110084; + + type USB_INTR_t { + HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_RESUME = false; // Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + HOST_SOF = false; // Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + TRANS_COMPLETE = false; // Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + BUFF_STATUS = false; // Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + ERROR_DATA_SEQ = false; // Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_RX_TIMEOUT = false; // Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_OVERFLOW = false; // Source: SIE_STATUS.RX_OVERFLOW + ERROR_BIT_STUFF = false; // Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_CRC = false; // Source: SIE_STATUS.CRC_ERROR + STALL = false; // Source: SIE_STATUS.STALL_REC + VBUS_DETECT = false; // Source: SIE_STATUS.VBUS_DETECT + BUS_RESET = false; // Source: SIE_STATUS.BUS_RESET + DEV_CONN_DIS = false; // Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_SUSPEND = false; // Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_RESUME_FROM_HOST = false; // Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + SETUP_REQ = false; // Device. Source: SIE_STATUS.SETUP_REC + DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + _res1 = uint12(0); // Reserved, 12 bits + } + + // Raw Interrupts + register USB_INTR_t USB_INTR at 0x5011008c; + register uint32 USB_INTR_raw at 0x5011008c; + + type USB_INTE_t { + HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_RESUME = false; // Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + HOST_SOF = false; // Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + TRANS_COMPLETE = false; // Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + BUFF_STATUS = false; // Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + ERROR_DATA_SEQ = false; // Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_RX_TIMEOUT = false; // Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_OVERFLOW = false; // Source: SIE_STATUS.RX_OVERFLOW + ERROR_BIT_STUFF = false; // Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_CRC = false; // Source: SIE_STATUS.CRC_ERROR + STALL = false; // Source: SIE_STATUS.STALL_REC + VBUS_DETECT = false; // Source: SIE_STATUS.VBUS_DETECT + BUS_RESET = false; // Source: SIE_STATUS.BUS_RESET + DEV_CONN_DIS = false; // Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_SUSPEND = false; // Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_RESUME_FROM_HOST = false; // Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + SETUP_REQ = false; // Device. Source: SIE_STATUS.SETUP_REC + DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + _res1 = uint12(0); // Reserved, 12 bits + } + + // Interrupt Enable + register USB_INTE_t USB_INTE at 0x50110090; + register uint32 USB_INTE_raw at 0x50110090; + + type USB_INTF_t { + HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_RESUME = false; // Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + HOST_SOF = false; // Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + TRANS_COMPLETE = false; // Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + BUFF_STATUS = false; // Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + ERROR_DATA_SEQ = false; // Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_RX_TIMEOUT = false; // Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_OVERFLOW = false; // Source: SIE_STATUS.RX_OVERFLOW + ERROR_BIT_STUFF = false; // Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_CRC = false; // Source: SIE_STATUS.CRC_ERROR + STALL = false; // Source: SIE_STATUS.STALL_REC + VBUS_DETECT = false; // Source: SIE_STATUS.VBUS_DETECT + BUS_RESET = false; // Source: SIE_STATUS.BUS_RESET + DEV_CONN_DIS = false; // Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_SUSPEND = false; // Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_RESUME_FROM_HOST = false; // Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + SETUP_REQ = false; // Device. Source: SIE_STATUS.SETUP_REC + DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + _res1 = uint12(0); // Reserved, 12 bits + } + + // Interrupt Force + register USB_INTF_t USB_INTF at 0x50110094; + register uint32 USB_INTF_raw at 0x50110094; + + type USB_INTS_t { + HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_RESUME = false; // Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + HOST_SOF = false; // Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + TRANS_COMPLETE = false; // Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + BUFF_STATUS = false; // Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + ERROR_DATA_SEQ = false; // Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_RX_TIMEOUT = false; // Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_OVERFLOW = false; // Source: SIE_STATUS.RX_OVERFLOW + ERROR_BIT_STUFF = false; // Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_CRC = false; // Source: SIE_STATUS.CRC_ERROR + STALL = false; // Source: SIE_STATUS.STALL_REC + VBUS_DETECT = false; // Source: SIE_STATUS.VBUS_DETECT + BUS_RESET = false; // Source: SIE_STATUS.BUS_RESET + DEV_CONN_DIS = false; // Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_SUSPEND = false; // Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_RESUME_FROM_HOST = false; // Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + SETUP_REQ = false; // Device. Source: SIE_STATUS.SETUP_REC + DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + _res1 = uint12(0); // Reserved, 12 bits + } + + // Interrupt status after masking & forcing + register USB_INTS_t USB_INTS at 0x50110098; + register uint32 USB_INTS_raw at 0x50110098; + + +/* Types and registers for USB_DPRAM + DPRAM layout for USB device. + */ + + type SETUP_PACKET_LOW_t { + BMREQUESTTYPE = uint8(0); // + BREQUEST = uint8(0); // + WVALUE = uint16(0); // + } + + // Bytes 0-3 of the SETUP packet from the host. + register SETUP_PACKET_LOW_t SETUP_PACKET_LOW at 0x50100000; + register uint32 SETUP_PACKET_LOW_raw at 0x50100000; + + type SETUP_PACKET_HIGH_t { + WINDEX = uint16(0); // + WLENGTH = uint16(0); // + } + + // Bytes 4-7 of the setup packet from the host. + register SETUP_PACKET_HIGH_t SETUP_PACKET_HIGH at 0x50100004; + register uint32 SETUP_PACKET_HIGH_raw at 0x50100004; + + enum EP1_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP1_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP1_IN_CONTROL_t EP1_IN_CONTROL at 0x50100008; + register uint32 EP1_IN_CONTROL_raw at 0x50100008; + + enum EP1_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP1_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP1_OUT_CONTROL_t EP1_OUT_CONTROL at 0x5010000c; + register uint32 EP1_OUT_CONTROL_raw at 0x5010000c; + + enum EP2_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP2_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP2_IN_CONTROL_t EP2_IN_CONTROL at 0x50100010; + register uint32 EP2_IN_CONTROL_raw at 0x50100010; + + enum EP2_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP2_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP2_OUT_CONTROL_t EP2_OUT_CONTROL at 0x50100014; + register uint32 EP2_OUT_CONTROL_raw at 0x50100014; + + enum EP3_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP3_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP3_IN_CONTROL_t EP3_IN_CONTROL at 0x50100018; + register uint32 EP3_IN_CONTROL_raw at 0x50100018; + + enum EP3_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP3_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP3_OUT_CONTROL_t EP3_OUT_CONTROL at 0x5010001c; + register uint32 EP3_OUT_CONTROL_raw at 0x5010001c; + + enum EP4_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP4_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP4_IN_CONTROL_t EP4_IN_CONTROL at 0x50100020; + register uint32 EP4_IN_CONTROL_raw at 0x50100020; + + enum EP4_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP4_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP4_OUT_CONTROL_t EP4_OUT_CONTROL at 0x50100024; + register uint32 EP4_OUT_CONTROL_raw at 0x50100024; + + enum EP5_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP5_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP5_IN_CONTROL_t EP5_IN_CONTROL at 0x50100028; + register uint32 EP5_IN_CONTROL_raw at 0x50100028; + + enum EP5_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP5_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP5_OUT_CONTROL_t EP5_OUT_CONTROL at 0x5010002c; + register uint32 EP5_OUT_CONTROL_raw at 0x5010002c; + + enum EP6_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP6_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP6_IN_CONTROL_t EP6_IN_CONTROL at 0x50100030; + register uint32 EP6_IN_CONTROL_raw at 0x50100030; + + enum EP6_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP6_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP6_OUT_CONTROL_t EP6_OUT_CONTROL at 0x50100034; + register uint32 EP6_OUT_CONTROL_raw at 0x50100034; + + enum EP7_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP7_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP7_IN_CONTROL_t EP7_IN_CONTROL at 0x50100038; + register uint32 EP7_IN_CONTROL_raw at 0x50100038; + + enum EP7_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP7_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP7_OUT_CONTROL_t EP7_OUT_CONTROL at 0x5010003c; + register uint32 EP7_OUT_CONTROL_raw at 0x5010003c; + + enum EP8_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP8_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP8_IN_CONTROL_t EP8_IN_CONTROL at 0x50100040; + register uint32 EP8_IN_CONTROL_raw at 0x50100040; + + enum EP8_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP8_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP8_OUT_CONTROL_t EP8_OUT_CONTROL at 0x50100044; + register uint32 EP8_OUT_CONTROL_raw at 0x50100044; + + enum EP9_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP9_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP9_IN_CONTROL_t EP9_IN_CONTROL at 0x50100048; + register uint32 EP9_IN_CONTROL_raw at 0x50100048; + + enum EP9_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP9_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP9_OUT_CONTROL_t EP9_OUT_CONTROL at 0x5010004c; + register uint32 EP9_OUT_CONTROL_raw at 0x5010004c; + + enum EP10_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP10_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP10_IN_CONTROL_t EP10_IN_CONTROL at 0x50100050; + register uint32 EP10_IN_CONTROL_raw at 0x50100050; + + enum EP10_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP10_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP10_OUT_CONTROL_t EP10_OUT_CONTROL at 0x50100054; + register uint32 EP10_OUT_CONTROL_raw at 0x50100054; + + enum EP11_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP11_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP11_IN_CONTROL_t EP11_IN_CONTROL at 0x50100058; + register uint32 EP11_IN_CONTROL_raw at 0x50100058; + + enum EP11_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP11_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP11_OUT_CONTROL_t EP11_OUT_CONTROL at 0x5010005c; + register uint32 EP11_OUT_CONTROL_raw at 0x5010005c; + + enum EP12_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP12_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP12_IN_CONTROL_t EP12_IN_CONTROL at 0x50100060; + register uint32 EP12_IN_CONTROL_raw at 0x50100060; + + enum EP12_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP12_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP12_OUT_CONTROL_t EP12_OUT_CONTROL at 0x50100064; + register uint32 EP12_OUT_CONTROL_raw at 0x50100064; + + enum EP13_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP13_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP13_IN_CONTROL_t EP13_IN_CONTROL at 0x50100068; + register uint32 EP13_IN_CONTROL_raw at 0x50100068; + + enum EP13_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP13_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP13_OUT_CONTROL_t EP13_OUT_CONTROL at 0x5010006c; + register uint32 EP13_OUT_CONTROL_raw at 0x5010006c; + + enum EP14_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP14_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP14_IN_CONTROL_t EP14_IN_CONTROL at 0x50100070; + register uint32 EP14_IN_CONTROL_raw at 0x50100070; + + enum EP14_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP14_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP14_OUT_CONTROL_t EP14_OUT_CONTROL at 0x50100074; + register uint32 EP14_OUT_CONTROL_raw at 0x50100074; + + enum EP15_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP15_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP15_IN_CONTROL_t EP15_IN_CONTROL at 0x50100078; + register uint32 EP15_IN_CONTROL_raw at 0x50100078; + + enum EP15_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } + + type EP15_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP15_OUT_CONTROL_t EP15_OUT_CONTROL at 0x5010007c; + register uint32 EP15_OUT_CONTROL_raw at 0x5010007c; + + enum EP0_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP0_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP0_IN_BUFFER_CONTROL_t EP0_IN_BUFFER_CONTROL at 0x50100080; + register uint32 EP0_IN_BUFFER_CONTROL_raw at 0x50100080; + + enum EP0_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP0_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP0_OUT_BUFFER_CONTROL_t EP0_OUT_BUFFER_CONTROL at 0x50100084; + register uint32 EP0_OUT_BUFFER_CONTROL_raw at 0x50100084; + + enum EP1_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP1_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP1_IN_BUFFER_CONTROL_t EP1_IN_BUFFER_CONTROL at 0x50100088; + register uint32 EP1_IN_BUFFER_CONTROL_raw at 0x50100088; + + enum EP1_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP1_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP1_OUT_BUFFER_CONTROL_t EP1_OUT_BUFFER_CONTROL at 0x5010008c; + register uint32 EP1_OUT_BUFFER_CONTROL_raw at 0x5010008c; + + enum EP2_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP2_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP2_IN_BUFFER_CONTROL_t EP2_IN_BUFFER_CONTROL at 0x50100090; + register uint32 EP2_IN_BUFFER_CONTROL_raw at 0x50100090; + + enum EP2_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP2_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP2_OUT_BUFFER_CONTROL_t EP2_OUT_BUFFER_CONTROL at 0x50100094; + register uint32 EP2_OUT_BUFFER_CONTROL_raw at 0x50100094; + + enum EP3_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP3_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP3_IN_BUFFER_CONTROL_t EP3_IN_BUFFER_CONTROL at 0x50100098; + register uint32 EP3_IN_BUFFER_CONTROL_raw at 0x50100098; + + enum EP3_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP3_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP3_OUT_BUFFER_CONTROL_t EP3_OUT_BUFFER_CONTROL at 0x5010009c; + register uint32 EP3_OUT_BUFFER_CONTROL_raw at 0x5010009c; + + enum EP4_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP4_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP4_IN_BUFFER_CONTROL_t EP4_IN_BUFFER_CONTROL at 0x501000a0; + register uint32 EP4_IN_BUFFER_CONTROL_raw at 0x501000a0; + + enum EP4_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP4_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP4_OUT_BUFFER_CONTROL_t EP4_OUT_BUFFER_CONTROL at 0x501000a4; + register uint32 EP4_OUT_BUFFER_CONTROL_raw at 0x501000a4; + + enum EP5_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP5_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP5_IN_BUFFER_CONTROL_t EP5_IN_BUFFER_CONTROL at 0x501000a8; + register uint32 EP5_IN_BUFFER_CONTROL_raw at 0x501000a8; + + enum EP5_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP5_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP5_OUT_BUFFER_CONTROL_t EP5_OUT_BUFFER_CONTROL at 0x501000ac; + register uint32 EP5_OUT_BUFFER_CONTROL_raw at 0x501000ac; + + enum EP6_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP6_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP6_IN_BUFFER_CONTROL_t EP6_IN_BUFFER_CONTROL at 0x501000b0; + register uint32 EP6_IN_BUFFER_CONTROL_raw at 0x501000b0; + + enum EP6_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP6_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP6_OUT_BUFFER_CONTROL_t EP6_OUT_BUFFER_CONTROL at 0x501000b4; + register uint32 EP6_OUT_BUFFER_CONTROL_raw at 0x501000b4; + + enum EP7_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP7_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP7_IN_BUFFER_CONTROL_t EP7_IN_BUFFER_CONTROL at 0x501000b8; + register uint32 EP7_IN_BUFFER_CONTROL_raw at 0x501000b8; + + enum EP7_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP7_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP7_OUT_BUFFER_CONTROL_t EP7_OUT_BUFFER_CONTROL at 0x501000bc; + register uint32 EP7_OUT_BUFFER_CONTROL_raw at 0x501000bc; + + enum EP8_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP8_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP8_IN_BUFFER_CONTROL_t EP8_IN_BUFFER_CONTROL at 0x501000c0; + register uint32 EP8_IN_BUFFER_CONTROL_raw at 0x501000c0; + + enum EP8_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP8_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP8_OUT_BUFFER_CONTROL_t EP8_OUT_BUFFER_CONTROL at 0x501000c4; + register uint32 EP8_OUT_BUFFER_CONTROL_raw at 0x501000c4; + + enum EP9_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP9_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP9_IN_BUFFER_CONTROL_t EP9_IN_BUFFER_CONTROL at 0x501000c8; + register uint32 EP9_IN_BUFFER_CONTROL_raw at 0x501000c8; + + enum EP9_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP9_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP9_OUT_BUFFER_CONTROL_t EP9_OUT_BUFFER_CONTROL at 0x501000cc; + register uint32 EP9_OUT_BUFFER_CONTROL_raw at 0x501000cc; + + enum EP10_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP10_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP10_IN_BUFFER_CONTROL_t EP10_IN_BUFFER_CONTROL at 0x501000d0; + register uint32 EP10_IN_BUFFER_CONTROL_raw at 0x501000d0; + + enum EP10_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP10_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP10_OUT_BUFFER_CONTROL_t EP10_OUT_BUFFER_CONTROL at 0x501000d4; + register uint32 EP10_OUT_BUFFER_CONTROL_raw at 0x501000d4; + + enum EP11_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP11_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP11_IN_BUFFER_CONTROL_t EP11_IN_BUFFER_CONTROL at 0x501000d8; + register uint32 EP11_IN_BUFFER_CONTROL_raw at 0x501000d8; + + enum EP11_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP11_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP11_OUT_BUFFER_CONTROL_t EP11_OUT_BUFFER_CONTROL at 0x501000dc; + register uint32 EP11_OUT_BUFFER_CONTROL_raw at 0x501000dc; + + enum EP12_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP12_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP12_IN_BUFFER_CONTROL_t EP12_IN_BUFFER_CONTROL at 0x501000e0; + register uint32 EP12_IN_BUFFER_CONTROL_raw at 0x501000e0; + + enum EP12_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP12_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP12_OUT_BUFFER_CONTROL_t EP12_OUT_BUFFER_CONTROL at 0x501000e4; + register uint32 EP12_OUT_BUFFER_CONTROL_raw at 0x501000e4; + + enum EP13_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP13_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP13_IN_BUFFER_CONTROL_t EP13_IN_BUFFER_CONTROL at 0x501000e8; + register uint32 EP13_IN_BUFFER_CONTROL_raw at 0x501000e8; + + enum EP13_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP13_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP13_OUT_BUFFER_CONTROL_t EP13_OUT_BUFFER_CONTROL at 0x501000ec; + register uint32 EP13_OUT_BUFFER_CONTROL_raw at 0x501000ec; + + enum EP14_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP14_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP14_IN_BUFFER_CONTROL_t EP14_IN_BUFFER_CONTROL at 0x501000f0; + register uint32 EP14_IN_BUFFER_CONTROL_raw at 0x501000f0; + + enum EP14_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP14_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP14_OUT_BUFFER_CONTROL_t EP14_OUT_BUFFER_CONTROL at 0x501000f4; + register uint32 EP14_OUT_BUFFER_CONTROL_raw at 0x501000f4; + + enum EP15_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP15_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP15_IN_BUFFER_CONTROL_t EP15_IN_BUFFER_CONTROL at 0x501000f8; + register uint32 EP15_IN_BUFFER_CONTROL_raw at 0x501000f8; + + enum EP15_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } + + type EP15_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP15_OUT_BUFFER_CONTROL_t EP15_OUT_BUFFER_CONTROL at 0x501000fc; + register uint32 EP15_OUT_BUFFER_CONTROL_raw at 0x501000fc; + + +/* Types and registers for TBMAN + Testbench manager. Allows the programmer to know what platform their software is running on. + */ + + type TBMAN_PLATFORM_t { + ASIC = false; // Indicates the platform is an ASIC + FPGA = false; // Indicates the platform is an FPGA + _res1 = uint30(0); // Reserved, 30 bits + } + + // Indicates the type of platform in use + register TBMAN_PLATFORM_t TBMAN_PLATFORM at 0x4006c000; + register uint32 TBMAN_PLATFORM_raw at 0x4006c000; + + +/* Types and registers for VREG_AND_CHIP_RESET + control and status for on-chip voltage regulator and chip level reset subsystem + */ + + type VREG_t { + EN = false; // enable 0=not enabled, 1=enabled + HIZ = false; // high impedance mode select 0=not in high impedance mode, 1=in high impedance mode + _res1 = uint2(0); // Reserved, 2 bits + VSEL = uint4(0); // output voltage select 0000 to 0101 - 0.80V 0110 - 0.85V 0111 - 0.90V 1000 - 0.95V 1001 - 1.00V 1010 - 1.05V 1011 - 1.10V (default) 1100 - 1.15V 1101 - 1.20V 1110 - 1.25V 1111 - 1.30V + _res2 = uint4(0); // Reserved, 4 bits + ROK = false; // regulation status 0=not in regulation, 1=in regulation + _res3 = uint19(0); // Reserved, 19 bits + } + + // Voltage regulator control and status + register VREG_t VREG at 0x40064000; + register uint32 VREG_raw at 0x40064000; + + type BOD_t { + EN = false; // enable 0=not enabled, 1=enabled + _res1 = uint3(0); // Reserved, 3 bits + VSEL = uint4(0); // threshold select 0000 - 0.473V 0001 - 0.516V 0010 - 0.559V 0011 - 0.602V 0100 - 0.645V 0101 - 0.688V 0110 - 0.731V 0111 - 0.774V 1000 - 0.817V 1001 - 0.860V (default) 1010 - 0.903V 1011 - 0.946V 1100 - 0.989V 1101 - 1.032V 1110 - 1.075V 1111 - 1.118V + _res2 = uint24(0); // Reserved, 24 bits + } + + // brown-out detection control + register BOD_t BOD at 0x40064004; + register uint32 BOD_raw at 0x40064004; + + type CHIP_RESET_t { + _res1 = uint8(0); // Reserved, 8 bits + HAD_POR = false; // Last reset was from the power-on reset or brown-out detection blocks + _res2 = uint7(0); // Reserved, 7 bits + HAD_RUN = false; // Last reset was from the RUN pin + _res3 = uint3(0); // Reserved, 3 bits + HAD_PSM_RESTART = false; // Last reset was from the debug port + _res4 = uint3(0); // Reserved, 3 bits + PSM_RESTART_FLAG = false; // This is set by psm_restart from the debugger. Its purpose is to branch bootcode to a safe mode when the debugger has issued a psm_restart in order to recover from a boot lock-up. In the safe mode the debugger can repair the boot code, clear this flag then reboot the processor. + _res5 = uint7(0); // Reserved, 7 bits + } + + // Chip reset control and status + register CHIP_RESET_t CHIP_RESET at 0x40064008; + register uint32 CHIP_RESET_raw at 0x40064008; + + +/* Types and registers for RTC + Register block to control RTC + */ + + type CLKDIV_M1_t { + CLKDIV_M1 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits + } + + // Divider minus 1 for the 1 second counter. Safe to change the value when RTC is not enabled. + register CLKDIV_M1_t CLKDIV_M1 at 0x4005c000; + register uint32 CLKDIV_M1_raw at 0x4005c000; + + type SETUP_0_t { + DAY = uint5(0); // Day of the month (1..31) + _res1 = uint3(0); // Reserved, 3 bits + MONTH = uint4(0); // Month (1..12) + YEAR = uint12(0); // Year + _res2 = uint8(0); // Reserved, 8 bits + } + + // RTC setup register 0 + register SETUP_0_t SETUP_0 at 0x4005c004; + register uint32 SETUP_0_raw at 0x4005c004; + + type SETUP_1_t { + SEC = uint6(0); // Seconds + _res1 = uint2(0); // Reserved, 2 bits + MIN = uint6(0); // Minutes + _res2 = uint2(0); // Reserved, 2 bits + HOUR = uint5(0); // Hours + _res3 = uint3(0); // Reserved, 3 bits + DOTW = uint3(0); // Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7 + _res4 = uint5(0); // Reserved, 5 bits + } + + // RTC setup register 1 + register SETUP_1_t SETUP_1 at 0x4005c008; + register uint32 SETUP_1_raw at 0x4005c008; + + type RTC_CTRL_t { + RTC_ENABLE = false; // Enable RTC + RTC_ACTIVE = false; // RTC enabled (running) + _res1 = uint2(0); // Reserved, 2 bits + LOAD = false; // Load RTC + _res2 = uint3(0); // Reserved, 3 bits + FORCE_NOTLEAPYEAR = false; // If set, leapyear is forced off. Useful for years divisible by 100 but not by 400 + _res3 = uint23(0); // Reserved, 23 bits + } + + // RTC Control and status + register RTC_CTRL_t RTC_CTRL at 0x4005c00c; + register uint32 RTC_CTRL_raw at 0x4005c00c; + + type IRQ_SETUP_0_t { + DAY = uint5(0); // Day of the month (1..31) + _res1 = uint3(0); // Reserved, 3 bits + MONTH = uint4(0); // Month (1..12) + YEAR = uint12(0); // Year + DAY_ENA = false; // Enable day matching + MONTH_ENA = false; // Enable month matching + YEAR_ENA = false; // Enable year matching + _res2 = false; // Reserved, 1 bits + MATCH_ENA = false; // Global match enable. Don't change any other value while this one is enabled + MATCH_ACTIVE = false; // + _res3 = uint2(0); // Reserved, 2 bits + } + + // Interrupt setup register 0 + register IRQ_SETUP_0_t IRQ_SETUP_0 at 0x4005c010; + register uint32 IRQ_SETUP_0_raw at 0x4005c010; + + type IRQ_SETUP_1_t { + SEC = uint6(0); // Seconds + _res1 = uint2(0); // Reserved, 2 bits + MIN = uint6(0); // Minutes + _res2 = uint2(0); // Reserved, 2 bits + HOUR = uint5(0); // Hours + _res3 = uint3(0); // Reserved, 3 bits + DOTW = uint3(0); // Day of the week + _res4 = false; // Reserved, 1 bits + SEC_ENA = false; // Enable second matching + MIN_ENA = false; // Enable minute matching + HOUR_ENA = false; // Enable hour matching + DOTW_ENA = false; // Enable day of the week matching + } + + // Interrupt setup register 1 + register IRQ_SETUP_1_t IRQ_SETUP_1 at 0x4005c014; + register uint32 IRQ_SETUP_1_raw at 0x4005c014; + + type RTC_1_t { + DAY = uint5(0); // Day of the month (1..31) + _res1 = uint3(0); // Reserved, 3 bits + MONTH = uint4(0); // Month (1..12) + YEAR = uint12(0); // Year + _res2 = uint8(0); // Reserved, 8 bits + } + + // RTC register 1. + register RTC_1_t RTC_1 at 0x4005c018; + register uint32 RTC_1_raw at 0x4005c018; + + type RTC_0_t { + SEC = uint6(0); // Seconds + _res1 = uint2(0); // Reserved, 2 bits + MIN = uint6(0); // Minutes + _res2 = uint2(0); // Reserved, 2 bits + HOUR = uint5(0); // Hours + _res3 = uint3(0); // Reserved, 3 bits + DOTW = uint3(0); // Day of the week + _res4 = uint5(0); // Reserved, 5 bits + } + + // RTC register 0 Read this before RTC 1! + register RTC_0_t RTC_0 at 0x4005c01c; + register uint32 RTC_0_raw at 0x4005c01c; + + type RTC_INTR_t { + RTC = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Raw Interrupts + register RTC_INTR_t RTC_INTR at 0x4005c020; + register uint32 RTC_INTR_raw at 0x4005c020; + + type RTC_INTE_t { + RTC = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Interrupt Enable + register RTC_INTE_t RTC_INTE at 0x4005c024; + register uint32 RTC_INTE_raw at 0x4005c024; + + type RTC_INTF_t { + RTC = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Interrupt Force + register RTC_INTF_t RTC_INTF at 0x4005c028; + register uint32 RTC_INTF_raw at 0x4005c028; + + type RTC_INTS_t { + RTC = false; // + _res1 = uint31(0); // Reserved, 31 bits + } + + // Interrupt status after masking & forcing + register RTC_INTS_t RTC_INTS at 0x4005c02c; + register uint32 RTC_INTS_raw at 0x4005c02c; + diff --git a/lib/arch/rp/rp2040/rp2040.ld b/lib/arch/rp/rp2040/rp2040.ld new file mode 100644 index 0000000..9a30194 --- /dev/null +++ b/lib/arch/rp/rp2040/rp2040.ld @@ -0,0 +1,72 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 2M + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 264K +} + +__reset_stack_pointer = ORIGIN(RAM) + LENGTH(RAM); + +SECTIONS +{ + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + .isr_vector : { + __isr_start = .; + LONG(__reset_stack_pointer); + LONG(__isr_reset | 1); + LONG(__error_handler | 1); /*isr nmi */ + LONG(__error_handler | 1); /*HardFault_Handler*/ + LONG(0); + LONG(0); + LONG(0); + LONG(0); + LONG(0); + LONG(__error_handler | 1); /*SVCall_Handler*/ + LONG(0); + LONG(0); + LONG(__error_handler | 1); /*PendSV_Handler*/ + LONG(__error_handler | 1); /*SysTick_Handler*/ + + /* The interrupt table is 192 bytes long. Advance to that position. */ + . = __isr_start + 192; + } > FLASH + + + .text : { + . = ALIGN(4); + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + . = ALIGN(4); + } > FLASH + + __data_init = LOADADDR(.data); + + .data : { + __data_start = .; + *(.data) + *(.data.*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH + + .bss : + { + __bss_start = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/lib/arch/rp/rp2040/rp2040.svd b/lib/arch/rp/rp2040/rp2040.svd new file mode 100644 index 0000000..b372675 --- /dev/null +++ b/lib/arch/rp/rp2040/rp2040.svd @@ -0,0 +1,51245 @@ + + + + Raspberry Pi + RP2040 + RP + 0.1 + + Dual-core Arm Cortex-M0+ processor, flexible clock running up to 133 MHz + 264KB on-chip SRAM + 2 x UART, 2 x SPI controllers, 2 x I2C controllers, 16 x PWM channels + 1 x USB 1.1 controller and PHY, with host and device support + 8 x Programmable I/O (PIO) state machines for custom peripheral support + Supported input power 1.8-5.5V DC + Operating temperature -20C to +85C + Drag-and-drop programming using mass storage over USB + Low-power sleep and dormant modes + Accurate on-chip clock + Temperature sensor + Accelerated integer and floating-point libraries on-chip + + 32 + 32 + 0xffffffff + 0x00000000 + read-write + + Copyright (c) 2024 Raspberry Pi Ltd. + + SPDX-License-Identifier: BSD-3-Clause + + + CM0PLUS + r0p1 + little + true + false + 1 + 2 + false + 26 + + 8 + + + RESETS + 0x4000c000 + + 0 + 12 + registers + + + + RESET + 0x00000000 + Reset control. If a bit is set it means the peripheral is in reset. 0 means the peripheral's reset is deasserted. + 0x01ffffff + + + USBCTRL + [24:24] + read-write + + + UART1 + [23:23] + read-write + + + UART0 + [22:22] + read-write + + + TIMER + [21:21] + read-write + + + TBMAN + [20:20] + read-write + + + SYSINFO + [19:19] + read-write + + + SYSCFG + [18:18] + read-write + + + SPI1 + [17:17] + read-write + + + SPI0 + [16:16] + read-write + + + RTC + [15:15] + read-write + + + PWM + [14:14] + read-write + + + PLL_USB + [13:13] + read-write + + + PLL_SYS + [12:12] + read-write + + + PIO1 + [11:11] + read-write + + + PIO0 + [10:10] + read-write + + + PADS_QSPI + [9:9] + read-write + + + PADS_BANK0 + [8:8] + read-write + + + JTAG + [7:7] + read-write + + + IO_QSPI + [6:6] + read-write + + + IO_BANK0 + [5:5] + read-write + + + I2C1 + [4:4] + read-write + + + I2C0 + [3:3] + read-write + + + DMA + [2:2] + read-write + + + BUSCTRL + [1:1] + read-write + + + ADC + [0:0] + read-write + + + + + WDSEL + 0x00000004 + Watchdog select. If a bit is set then the watchdog will reset this peripheral when the watchdog fires. + 0x00000000 + + + USBCTRL + [24:24] + read-write + + + UART1 + [23:23] + read-write + + + UART0 + [22:22] + read-write + + + TIMER + [21:21] + read-write + + + TBMAN + [20:20] + read-write + + + SYSINFO + [19:19] + read-write + + + SYSCFG + [18:18] + read-write + + + SPI1 + [17:17] + read-write + + + SPI0 + [16:16] + read-write + + + RTC + [15:15] + read-write + + + PWM + [14:14] + read-write + + + PLL_USB + [13:13] + read-write + + + PLL_SYS + [12:12] + read-write + + + PIO1 + [11:11] + read-write + + + PIO0 + [10:10] + read-write + + + PADS_QSPI + [9:9] + read-write + + + PADS_BANK0 + [8:8] + read-write + + + JTAG + [7:7] + read-write + + + IO_QSPI + [6:6] + read-write + + + IO_BANK0 + [5:5] + read-write + + + I2C1 + [4:4] + read-write + + + I2C0 + [3:3] + read-write + + + DMA + [2:2] + read-write + + + BUSCTRL + [1:1] + read-write + + + ADC + [0:0] + read-write + + + + + RESET_DONE + 0x00000008 + Reset done. If a bit is set then a reset done signal has been returned by the peripheral. This indicates that the peripheral's registers are ready to be accessed. + 0x00000000 + + + USBCTRL + [24:24] + read-only + + + UART1 + [23:23] + read-only + + + UART0 + [22:22] + read-only + + + TIMER + [21:21] + read-only + + + TBMAN + [20:20] + read-only + + + SYSINFO + [19:19] + read-only + + + SYSCFG + [18:18] + read-only + + + SPI1 + [17:17] + read-only + + + SPI0 + [16:16] + read-only + + + RTC + [15:15] + read-only + + + PWM + [14:14] + read-only + + + PLL_USB + [13:13] + read-only + + + PLL_SYS + [12:12] + read-only + + + PIO1 + [11:11] + read-only + + + PIO0 + [10:10] + read-only + + + PADS_QSPI + [9:9] + read-only + + + PADS_BANK0 + [8:8] + read-only + + + JTAG + [7:7] + read-only + + + IO_QSPI + [6:6] + read-only + + + IO_BANK0 + [5:5] + read-only + + + I2C1 + [4:4] + read-only + + + I2C0 + [3:3] + read-only + + + DMA + [2:2] + read-only + + + BUSCTRL + [1:1] + read-only + + + ADC + [0:0] + read-only + + + + + + + PSM + 0x40010000 + + 0 + 16 + registers + + + + FRCE_ON + 0x00000000 + Force block out of reset (i.e. power it on) + 0x00000000 + + + PROC1 + [16:16] + read-write + + + PROC0 + [15:15] + read-write + + + SIO + [14:14] + read-write + + + VREG_AND_CHIP_RESET + [13:13] + read-write + + + XIP + [12:12] + read-write + + + SRAM5 + [11:11] + read-write + + + SRAM4 + [10:10] + read-write + + + SRAM3 + [9:9] + read-write + + + SRAM2 + [8:8] + read-write + + + SRAM1 + [7:7] + read-write + + + SRAM0 + [6:6] + read-write + + + ROM + [5:5] + read-write + + + BUSFABRIC + [4:4] + read-write + + + RESETS + [3:3] + read-write + + + CLOCKS + [2:2] + read-write + + + XOSC + [1:1] + read-write + + + ROSC + [0:0] + read-write + + + + + FRCE_OFF + 0x00000004 + Force into reset (i.e. power it off) + 0x00000000 + + + PROC1 + [16:16] + read-write + + + PROC0 + [15:15] + read-write + + + SIO + [14:14] + read-write + + + VREG_AND_CHIP_RESET + [13:13] + read-write + + + XIP + [12:12] + read-write + + + SRAM5 + [11:11] + read-write + + + SRAM4 + [10:10] + read-write + + + SRAM3 + [9:9] + read-write + + + SRAM2 + [8:8] + read-write + + + SRAM1 + [7:7] + read-write + + + SRAM0 + [6:6] + read-write + + + ROM + [5:5] + read-write + + + BUSFABRIC + [4:4] + read-write + + + RESETS + [3:3] + read-write + + + CLOCKS + [2:2] + read-write + + + XOSC + [1:1] + read-write + + + ROSC + [0:0] + read-write + + + + + WDSEL + 0x00000008 + Set to 1 if this peripheral should be reset when the watchdog fires. + 0x00000000 + + + PROC1 + [16:16] + read-write + + + PROC0 + [15:15] + read-write + + + SIO + [14:14] + read-write + + + VREG_AND_CHIP_RESET + [13:13] + read-write + + + XIP + [12:12] + read-write + + + SRAM5 + [11:11] + read-write + + + SRAM4 + [10:10] + read-write + + + SRAM3 + [9:9] + read-write + + + SRAM2 + [8:8] + read-write + + + SRAM1 + [7:7] + read-write + + + SRAM0 + [6:6] + read-write + + + ROM + [5:5] + read-write + + + BUSFABRIC + [4:4] + read-write + + + RESETS + [3:3] + read-write + + + CLOCKS + [2:2] + read-write + + + XOSC + [1:1] + read-write + + + ROSC + [0:0] + read-write + + + + + DONE + 0x0000000c + Indicates the peripheral's registers are ready to access. + 0x00000000 + + + PROC1 + [16:16] + read-only + + + PROC0 + [15:15] + read-only + + + SIO + [14:14] + read-only + + + VREG_AND_CHIP_RESET + [13:13] + read-only + + + XIP + [12:12] + read-only + + + SRAM5 + [11:11] + read-only + + + SRAM4 + [10:10] + read-only + + + SRAM3 + [9:9] + read-only + + + SRAM2 + [8:8] + read-only + + + SRAM1 + [7:7] + read-only + + + SRAM0 + [6:6] + read-only + + + ROM + [5:5] + read-only + + + BUSFABRIC + [4:4] + read-only + + + RESETS + [3:3] + read-only + + + CLOCKS + [2:2] + read-only + + + XOSC + [1:1] + read-only + + + ROSC + [0:0] + read-only + + + + + + + CLOCKS + 0x40008000 + + 0 + 200 + registers + + + CLOCKS_IRQ + 17 + + + + CLK_GPOUT0_CTRL + 0x00000000 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + DC50 + Enables duty cycle correction for odd divisors + [12:12] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [8:5] + read-write + + + clksrc_pll_sys + 0 + + + clksrc_gpin0 + 1 + + + clksrc_gpin1 + 2 + + + clksrc_pll_usb + 3 + + + rosc_clksrc + 4 + + + xosc_clksrc + 5 + + + clk_sys + 6 + + + clk_usb + 7 + + + clk_adc + 8 + + + clk_rtc + 9 + + + clk_ref + 10 + + + + + + + CLK_GPOUT0_DIV + 0x00000004 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_GPOUT0_SELECTED + 0x00000008 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_GPOUT0_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_GPOUT1_CTRL + 0x0000000c + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + DC50 + Enables duty cycle correction for odd divisors + [12:12] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [8:5] + read-write + + + clksrc_pll_sys + 0 + + + clksrc_gpin0 + 1 + + + clksrc_gpin1 + 2 + + + clksrc_pll_usb + 3 + + + rosc_clksrc + 4 + + + xosc_clksrc + 5 + + + clk_sys + 6 + + + clk_usb + 7 + + + clk_adc + 8 + + + clk_rtc + 9 + + + clk_ref + 10 + + + + + + + CLK_GPOUT1_DIV + 0x00000010 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_GPOUT1_SELECTED + 0x00000014 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_GPOUT1_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_GPOUT2_CTRL + 0x00000018 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + DC50 + Enables duty cycle correction for odd divisors + [12:12] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [8:5] + read-write + + + clksrc_pll_sys + 0 + + + clksrc_gpin0 + 1 + + + clksrc_gpin1 + 2 + + + clksrc_pll_usb + 3 + + + rosc_clksrc_ph + 4 + + + xosc_clksrc + 5 + + + clk_sys + 6 + + + clk_usb + 7 + + + clk_adc + 8 + + + clk_rtc + 9 + + + clk_ref + 10 + + + + + + + CLK_GPOUT2_DIV + 0x0000001c + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_GPOUT2_SELECTED + 0x00000020 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_GPOUT2_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_GPOUT3_CTRL + 0x00000024 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + DC50 + Enables duty cycle correction for odd divisors + [12:12] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [8:5] + read-write + + + clksrc_pll_sys + 0 + + + clksrc_gpin0 + 1 + + + clksrc_gpin1 + 2 + + + clksrc_pll_usb + 3 + + + rosc_clksrc_ph + 4 + + + xosc_clksrc + 5 + + + clk_sys + 6 + + + clk_usb + 7 + + + clk_adc + 8 + + + clk_rtc + 9 + + + clk_ref + 10 + + + + + + + CLK_GPOUT3_DIV + 0x00000028 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_GPOUT3_SELECTED + 0x0000002c + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_GPOUT3_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_REF_CTRL + 0x00000030 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [6:5] + read-write + + + clksrc_pll_usb + 0 + + + clksrc_gpin0 + 1 + + + clksrc_gpin1 + 2 + + + + + SRC + Selects the clock source glitchlessly, can be changed on-the-fly + [1:0] + read-write + + + rosc_clksrc_ph + 0 + + + clksrc_clk_ref_aux + 1 + + + xosc_clksrc + 2 + + + + + + + CLK_REF_DIV + 0x00000034 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [9:8] + read-write + + + + + CLK_REF_SELECTED + 0x00000038 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_REF_SELECTED + The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. + [31:0] + read-only + + + + + CLK_SYS_CTRL + 0x0000003c + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [7:5] + read-write + + + clksrc_pll_sys + 0 + + + clksrc_pll_usb + 1 + + + rosc_clksrc + 2 + + + xosc_clksrc + 3 + + + clksrc_gpin0 + 4 + + + clksrc_gpin1 + 5 + + + + + SRC + Selects the clock source glitchlessly, can be changed on-the-fly + [0:0] + read-write + + + clk_ref + 0 + + + clksrc_clk_sys_aux + 1 + + + + + + + CLK_SYS_DIV + 0x00000040 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_SYS_SELECTED + 0x00000044 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_SYS_SELECTED + The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. + [31:0] + read-only + + + + + CLK_PERI_CTRL + 0x00000048 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [7:5] + read-write + + + clk_sys + 0 + + + clksrc_pll_sys + 1 + + + clksrc_pll_usb + 2 + + + rosc_clksrc_ph + 3 + + + xosc_clksrc + 4 + + + clksrc_gpin0 + 5 + + + clksrc_gpin1 + 6 + + + + + + + CLK_PERI_DIV + 0x0000004c + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_PERI_SELECTED + 0x00000050 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_PERI_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_USB_CTRL + 0x00000054 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [7:5] + read-write + + + clksrc_pll_usb + 0 + + + clksrc_pll_sys + 1 + + + rosc_clksrc_ph + 2 + + + xosc_clksrc + 3 + + + clksrc_gpin0 + 4 + + + clksrc_gpin1 + 5 + + + + + + + CLK_USB_DIV + 0x00000058 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [9:8] + read-write + + + + + CLK_USB_SELECTED + 0x0000005c + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_USB_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_ADC_CTRL + 0x00000060 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [7:5] + read-write + + + clksrc_pll_usb + 0 + + + clksrc_pll_sys + 1 + + + rosc_clksrc_ph + 2 + + + xosc_clksrc + 3 + + + clksrc_gpin0 + 4 + + + clksrc_gpin1 + 5 + + + + + + + CLK_ADC_DIV + 0x00000064 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [9:8] + read-write + + + + + CLK_ADC_SELECTED + 0x00000068 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_ADC_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_RTC_CTRL + 0x0000006c + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [7:5] + read-write + + + clksrc_pll_usb + 0 + + + clksrc_pll_sys + 1 + + + rosc_clksrc_ph + 2 + + + xosc_clksrc + 3 + + + clksrc_gpin0 + 4 + + + clksrc_gpin1 + 5 + + + + + + + CLK_RTC_DIV + 0x00000070 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_RTC_SELECTED + 0x00000074 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_RTC_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_SYS_RESUS_CTRL + 0x00000078 + 0x000000ff + + + CLEAR + For clearing the resus after the fault that triggered it has been corrected + [16:16] + read-write + + + FRCE + Force a resus, for test purposes only + [12:12] + read-write + + + ENABLE + Enable resus + [8:8] + read-write + + + TIMEOUT + This is expressed as a number of clk_ref cycles + and must be >= 2x clk_ref_freq/min_clk_tst_freq + [7:0] + read-write + + + + + CLK_SYS_RESUS_STATUS + 0x0000007c + 0x00000000 + + + RESUSSED + Clock has been resuscitated, correct the error then send ctrl_clear=1 + [0:0] + read-only + + + + + FC0_REF_KHZ + 0x00000080 + Reference clock frequency in kHz + 0x00000000 + + + FC0_REF_KHZ + [19:0] + read-write + + + + + FC0_MIN_KHZ + 0x00000084 + Minimum pass frequency in kHz. This is optional. Set to 0 if you are not using the pass/fail flags + 0x00000000 + + + FC0_MIN_KHZ + [24:0] + read-write + + + + + FC0_MAX_KHZ + 0x00000088 + Maximum pass frequency in kHz. This is optional. Set to 0x1ffffff if you are not using the pass/fail flags + 0x01ffffff + + + FC0_MAX_KHZ + [24:0] + read-write + + + + + FC0_DELAY + 0x0000008c + Delays the start of frequency counting to allow the mux to settle + Delay is measured in multiples of the reference clock period + 0x00000001 + + + FC0_DELAY + [2:0] + read-write + + + + + FC0_INTERVAL + 0x00000090 + The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval + The default gives a test interval of 250us + 0x00000008 + + + FC0_INTERVAL + [3:0] + read-write + + + + + FC0_SRC + 0x00000094 + Clock sent to frequency counter, set to 0 when not required + Writing to this register initiates the frequency count + 0x00000000 + + + FC0_SRC + [7:0] + read-write + + + NULL + 0 + + + pll_sys_clksrc_primary + 1 + + + pll_usb_clksrc_primary + 2 + + + rosc_clksrc + 3 + + + rosc_clksrc_ph + 4 + + + xosc_clksrc + 5 + + + clksrc_gpin0 + 6 + + + clksrc_gpin1 + 7 + + + clk_ref + 8 + + + clk_sys + 9 + + + clk_peri + 10 + + + clk_usb + 11 + + + clk_adc + 12 + + + clk_rtc + 13 + + + + + + + FC0_STATUS + 0x00000098 + Frequency counter status + 0x00000000 + + + DIED + Test clock stopped during test + [28:28] + read-only + + + FAST + Test clock faster than expected, only valid when status_done=1 + [24:24] + read-only + + + SLOW + Test clock slower than expected, only valid when status_done=1 + [20:20] + read-only + + + FAIL + Test failed + [16:16] + read-only + + + WAITING + Waiting for test clock to start + [12:12] + read-only + + + RUNNING + Test running + [8:8] + read-only + + + DONE + Test complete + [4:4] + read-only + + + PASS + Test passed + [0:0] + read-only + + + + + FC0_RESULT + 0x0000009c + Result of frequency measurement, only valid when status_done=1 + 0x00000000 + + + KHZ + [29:5] + read-only + + + FRAC + [4:0] + read-only + + + + + WAKE_EN0 + 0x000000a0 + enable clock in wake mode + 0xffffffff + + + CLK_SYS_SRAM3 + [31:31] + read-write + + + CLK_SYS_SRAM2 + [30:30] + read-write + + + CLK_SYS_SRAM1 + [29:29] + read-write + + + CLK_SYS_SRAM0 + [28:28] + read-write + + + CLK_SYS_SPI1 + [27:27] + read-write + + + CLK_PERI_SPI1 + [26:26] + read-write + + + CLK_SYS_SPI0 + [25:25] + read-write + + + CLK_PERI_SPI0 + [24:24] + read-write + + + CLK_SYS_SIO + [23:23] + read-write + + + CLK_SYS_RTC + [22:22] + read-write + + + CLK_RTC_RTC + [21:21] + read-write + + + CLK_SYS_ROSC + [20:20] + read-write + + + CLK_SYS_ROM + [19:19] + read-write + + + CLK_SYS_RESETS + [18:18] + read-write + + + CLK_SYS_PWM + [17:17] + read-write + + + CLK_SYS_PSM + [16:16] + read-write + + + CLK_SYS_PLL_USB + [15:15] + read-write + + + CLK_SYS_PLL_SYS + [14:14] + read-write + + + CLK_SYS_PIO1 + [13:13] + read-write + + + CLK_SYS_PIO0 + [12:12] + read-write + + + CLK_SYS_PADS + [11:11] + read-write + + + CLK_SYS_VREG_AND_CHIP_RESET + [10:10] + read-write + + + CLK_SYS_JTAG + [9:9] + read-write + + + CLK_SYS_IO + [8:8] + read-write + + + CLK_SYS_I2C1 + [7:7] + read-write + + + CLK_SYS_I2C0 + [6:6] + read-write + + + CLK_SYS_DMA + [5:5] + read-write + + + CLK_SYS_BUSFABRIC + [4:4] + read-write + + + CLK_SYS_BUSCTRL + [3:3] + read-write + + + CLK_SYS_ADC + [2:2] + read-write + + + CLK_ADC_ADC + [1:1] + read-write + + + CLK_SYS_CLOCKS + [0:0] + read-write + + + + + WAKE_EN1 + 0x000000a4 + enable clock in wake mode + 0x00007fff + + + CLK_SYS_XOSC + [14:14] + read-write + + + CLK_SYS_XIP + [13:13] + read-write + + + CLK_SYS_WATCHDOG + [12:12] + read-write + + + CLK_USB_USBCTRL + [11:11] + read-write + + + CLK_SYS_USBCTRL + [10:10] + read-write + + + CLK_SYS_UART1 + [9:9] + read-write + + + CLK_PERI_UART1 + [8:8] + read-write + + + CLK_SYS_UART0 + [7:7] + read-write + + + CLK_PERI_UART0 + [6:6] + read-write + + + CLK_SYS_TIMER + [5:5] + read-write + + + CLK_SYS_TBMAN + [4:4] + read-write + + + CLK_SYS_SYSINFO + [3:3] + read-write + + + CLK_SYS_SYSCFG + [2:2] + read-write + + + CLK_SYS_SRAM5 + [1:1] + read-write + + + CLK_SYS_SRAM4 + [0:0] + read-write + + + + + SLEEP_EN0 + 0x000000a8 + enable clock in sleep mode + 0xffffffff + + + CLK_SYS_SRAM3 + [31:31] + read-write + + + CLK_SYS_SRAM2 + [30:30] + read-write + + + CLK_SYS_SRAM1 + [29:29] + read-write + + + CLK_SYS_SRAM0 + [28:28] + read-write + + + CLK_SYS_SPI1 + [27:27] + read-write + + + CLK_PERI_SPI1 + [26:26] + read-write + + + CLK_SYS_SPI0 + [25:25] + read-write + + + CLK_PERI_SPI0 + [24:24] + read-write + + + CLK_SYS_SIO + [23:23] + read-write + + + CLK_SYS_RTC + [22:22] + read-write + + + CLK_RTC_RTC + [21:21] + read-write + + + CLK_SYS_ROSC + [20:20] + read-write + + + CLK_SYS_ROM + [19:19] + read-write + + + CLK_SYS_RESETS + [18:18] + read-write + + + CLK_SYS_PWM + [17:17] + read-write + + + CLK_SYS_PSM + [16:16] + read-write + + + CLK_SYS_PLL_USB + [15:15] + read-write + + + CLK_SYS_PLL_SYS + [14:14] + read-write + + + CLK_SYS_PIO1 + [13:13] + read-write + + + CLK_SYS_PIO0 + [12:12] + read-write + + + CLK_SYS_PADS + [11:11] + read-write + + + CLK_SYS_VREG_AND_CHIP_RESET + [10:10] + read-write + + + CLK_SYS_JTAG + [9:9] + read-write + + + CLK_SYS_IO + [8:8] + read-write + + + CLK_SYS_I2C1 + [7:7] + read-write + + + CLK_SYS_I2C0 + [6:6] + read-write + + + CLK_SYS_DMA + [5:5] + read-write + + + CLK_SYS_BUSFABRIC + [4:4] + read-write + + + CLK_SYS_BUSCTRL + [3:3] + read-write + + + CLK_SYS_ADC + [2:2] + read-write + + + CLK_ADC_ADC + [1:1] + read-write + + + CLK_SYS_CLOCKS + [0:0] + read-write + + + + + SLEEP_EN1 + 0x000000ac + enable clock in sleep mode + 0x00007fff + + + CLK_SYS_XOSC + [14:14] + read-write + + + CLK_SYS_XIP + [13:13] + read-write + + + CLK_SYS_WATCHDOG + [12:12] + read-write + + + CLK_USB_USBCTRL + [11:11] + read-write + + + CLK_SYS_USBCTRL + [10:10] + read-write + + + CLK_SYS_UART1 + [9:9] + read-write + + + CLK_PERI_UART1 + [8:8] + read-write + + + CLK_SYS_UART0 + [7:7] + read-write + + + CLK_PERI_UART0 + [6:6] + read-write + + + CLK_SYS_TIMER + [5:5] + read-write + + + CLK_SYS_TBMAN + [4:4] + read-write + + + CLK_SYS_SYSINFO + [3:3] + read-write + + + CLK_SYS_SYSCFG + [2:2] + read-write + + + CLK_SYS_SRAM5 + [1:1] + read-write + + + CLK_SYS_SRAM4 + [0:0] + read-write + + + + + ENABLED0 + 0x000000b0 + indicates the state of the clock enable + 0x00000000 + + + CLK_SYS_SRAM3 + [31:31] + read-only + + + CLK_SYS_SRAM2 + [30:30] + read-only + + + CLK_SYS_SRAM1 + [29:29] + read-only + + + CLK_SYS_SRAM0 + [28:28] + read-only + + + CLK_SYS_SPI1 + [27:27] + read-only + + + CLK_PERI_SPI1 + [26:26] + read-only + + + CLK_SYS_SPI0 + [25:25] + read-only + + + CLK_PERI_SPI0 + [24:24] + read-only + + + CLK_SYS_SIO + [23:23] + read-only + + + CLK_SYS_RTC + [22:22] + read-only + + + CLK_RTC_RTC + [21:21] + read-only + + + CLK_SYS_ROSC + [20:20] + read-only + + + CLK_SYS_ROM + [19:19] + read-only + + + CLK_SYS_RESETS + [18:18] + read-only + + + CLK_SYS_PWM + [17:17] + read-only + + + CLK_SYS_PSM + [16:16] + read-only + + + CLK_SYS_PLL_USB + [15:15] + read-only + + + CLK_SYS_PLL_SYS + [14:14] + read-only + + + CLK_SYS_PIO1 + [13:13] + read-only + + + CLK_SYS_PIO0 + [12:12] + read-only + + + CLK_SYS_PADS + [11:11] + read-only + + + CLK_SYS_VREG_AND_CHIP_RESET + [10:10] + read-only + + + CLK_SYS_JTAG + [9:9] + read-only + + + CLK_SYS_IO + [8:8] + read-only + + + CLK_SYS_I2C1 + [7:7] + read-only + + + CLK_SYS_I2C0 + [6:6] + read-only + + + CLK_SYS_DMA + [5:5] + read-only + + + CLK_SYS_BUSFABRIC + [4:4] + read-only + + + CLK_SYS_BUSCTRL + [3:3] + read-only + + + CLK_SYS_ADC + [2:2] + read-only + + + CLK_ADC_ADC + [1:1] + read-only + + + CLK_SYS_CLOCKS + [0:0] + read-only + + + + + ENABLED1 + 0x000000b4 + indicates the state of the clock enable + 0x00000000 + + + CLK_SYS_XOSC + [14:14] + read-only + + + CLK_SYS_XIP + [13:13] + read-only + + + CLK_SYS_WATCHDOG + [12:12] + read-only + + + CLK_USB_USBCTRL + [11:11] + read-only + + + CLK_SYS_USBCTRL + [10:10] + read-only + + + CLK_SYS_UART1 + [9:9] + read-only + + + CLK_PERI_UART1 + [8:8] + read-only + + + CLK_SYS_UART0 + [7:7] + read-only + + + CLK_PERI_UART0 + [6:6] + read-only + + + CLK_SYS_TIMER + [5:5] + read-only + + + CLK_SYS_TBMAN + [4:4] + read-only + + + CLK_SYS_SYSINFO + [3:3] + read-only + + + CLK_SYS_SYSCFG + [2:2] + read-only + + + CLK_SYS_SRAM5 + [1:1] + read-only + + + CLK_SYS_SRAM4 + [0:0] + read-only + + + + + INTR + 0x000000b8 + Raw Interrupts + 0x00000000 + + + CLK_SYS_RESUS + [0:0] + read-only + + + + + INTE + 0x000000bc + Interrupt Enable + 0x00000000 + + + CLK_SYS_RESUS + [0:0] + read-write + + + + + INTF + 0x000000c0 + Interrupt Force + 0x00000000 + + + CLK_SYS_RESUS + [0:0] + read-write + + + + + INTS + 0x000000c4 + Interrupt status after masking & forcing + 0x00000000 + + + CLK_SYS_RESUS + [0:0] + read-only + + + + + + + PADS_BANK0 + 0x4001c000 + + 0 + 132 + registers + + + + VOLTAGE_SELECT + 0x00000000 + Voltage select. Per bank control + 0x00000000 + + + VOLTAGE_SELECT + [0:0] + read-write + + + 3v3 + 0 + Set voltage to 3.3V (DVDD >= 2V5) + + + 1v8 + 1 + Set voltage to 1.8V (DVDD <= 1V8) + + + + + + + GPIO0 + 0x00000004 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO1 + 0x00000008 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO2 + 0x0000000c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO3 + 0x00000010 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO4 + 0x00000014 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO5 + 0x00000018 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO6 + 0x0000001c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO7 + 0x00000020 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO8 + 0x00000024 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO9 + 0x00000028 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO10 + 0x0000002c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO11 + 0x00000030 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO12 + 0x00000034 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO13 + 0x00000038 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO14 + 0x0000003c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO15 + 0x00000040 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO16 + 0x00000044 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO17 + 0x00000048 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO18 + 0x0000004c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO19 + 0x00000050 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO20 + 0x00000054 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO21 + 0x00000058 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO22 + 0x0000005c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO23 + 0x00000060 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO24 + 0x00000064 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO25 + 0x00000068 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO26 + 0x0000006c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO27 + 0x00000070 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO28 + 0x00000074 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO29 + 0x00000078 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + SWCLK + 0x0000007c + Pad control register + 0x000000da + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + SWD + 0x00000080 + Pad control register + 0x0000005a + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + + + PADS_QSPI + 0x40020000 + + 0 + 28 + registers + + + + VOLTAGE_SELECT + 0x00000000 + Voltage select. Per bank control + 0x00000000 + + + VOLTAGE_SELECT + [0:0] + read-write + + + 3v3 + 0 + Set voltage to 3.3V (DVDD >= 2V5) + + + 1v8 + 1 + Set voltage to 1.8V (DVDD <= 1V8) + + + + + + + GPIO_QSPI_SCLK + 0x00000004 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO_QSPI_SD0 + 0x00000008 + Pad control register + 0x00000052 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO_QSPI_SD1 + 0x0000000c + Pad control register + 0x00000052 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO_QSPI_SD2 + 0x00000010 + Pad control register + 0x00000052 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO_QSPI_SD3 + 0x00000014 + Pad control register + 0x00000052 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO_QSPI_SS + 0x00000018 + Pad control register + 0x0000005a + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + + + IO_QSPI + 0x40018000 + + 0 + 88 + registers + + + IO_IRQ_QSPI + 14 + + + + GPIO_QSPI_SCLK_STATUS + 0x00000000 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SCLK_CTRL + 0x00000004 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_sclk + 0 + + + sio_30 + 5 + + + null + 31 + + + + + + + GPIO_QSPI_SS_STATUS + 0x00000008 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SS_CTRL + 0x0000000c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_ss_n + 0 + + + sio_31 + 5 + + + null + 31 + + + + + + + GPIO_QSPI_SD0_STATUS + 0x00000010 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SD0_CTRL + 0x00000014 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_sd0 + 0 + + + sio_32 + 5 + + + null + 31 + + + + + + + GPIO_QSPI_SD1_STATUS + 0x00000018 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SD1_CTRL + 0x0000001c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_sd1 + 0 + + + sio_33 + 5 + + + null + 31 + + + + + + + GPIO_QSPI_SD2_STATUS + 0x00000020 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SD2_CTRL + 0x00000024 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_sd2 + 0 + + + sio_34 + 5 + + + null + 31 + + + + + + + GPIO_QSPI_SD3_STATUS + 0x00000028 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SD3_CTRL + 0x0000002c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_sd3 + 0 + + + sio_35 + 5 + + + null + 31 + + + + + + + INTR + 0x00000030 + Raw Interrupts + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + oneToClear + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + oneToClear + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-only + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-only + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + oneToClear + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + oneToClear + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-only + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-only + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + oneToClear + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + oneToClear + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-only + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-only + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + oneToClear + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + oneToClear + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-only + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-only + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + oneToClear + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + oneToClear + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-only + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-only + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + oneToClear + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + oneToClear + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-only + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-only + + + + + PROC0_INTE + 0x00000034 + Interrupt Enable for proc0 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTF + 0x00000038 + Interrupt Force for proc0 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTS + 0x0000003c + Interrupt status after masking & forcing for proc0 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-only + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-only + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-only + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-only + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-only + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-only + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-only + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-only + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-only + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-only + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-only + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-only + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-only + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-only + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-only + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-only + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-only + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-only + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-only + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-only + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-only + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-only + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-only + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-only + + + + + PROC1_INTE + 0x00000040 + Interrupt Enable for proc1 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTF + 0x00000044 + Interrupt Force for proc1 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTS + 0x00000048 + Interrupt status after masking & forcing for proc1 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-only + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-only + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-only + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-only + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-only + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-only + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-only + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-only + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-only + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-only + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-only + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-only + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-only + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-only + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-only + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-only + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-only + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-only + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-only + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-only + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-only + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-only + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-only + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-only + + + + + DORMANT_WAKE_INTE + 0x0000004c + Interrupt Enable for dormant_wake + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTF + 0x00000050 + Interrupt Force for dormant_wake + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTS + 0x00000054 + Interrupt status after masking & forcing for dormant_wake + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-only + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-only + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-only + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-only + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-only + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-only + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-only + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-only + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-only + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-only + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-only + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-only + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-only + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-only + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-only + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-only + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-only + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-only + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-only + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-only + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-only + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-only + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-only + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-only + + + + + + + IO_BANK0 + 0x40014000 + + 0 + 400 + registers + + + IO_IRQ_BANK0 + 13 + + + + GPIO0_STATUS + 0x00000000 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO0_CTRL + 0x00000004 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + jtag_tck + 0 + + + spi0_rx + 1 + + + uart0_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_0 + 4 + + + sio_0 + 5 + + + pio0_0 + 6 + + + pio1_0 + 7 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO1_STATUS + 0x00000008 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO1_CTRL + 0x0000000c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + jtag_tms + 0 + + + spi0_ss_n + 1 + + + uart0_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_0 + 4 + + + sio_1 + 5 + + + pio0_1 + 6 + + + pio1_1 + 7 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO2_STATUS + 0x00000010 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO2_CTRL + 0x00000014 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + jtag_tdi + 0 + + + spi0_sclk + 1 + + + uart0_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_1 + 4 + + + sio_2 + 5 + + + pio0_2 + 6 + + + pio1_2 + 7 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO3_STATUS + 0x00000018 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO3_CTRL + 0x0000001c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + jtag_tdo + 0 + + + spi0_tx + 1 + + + uart0_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_1 + 4 + + + sio_3 + 5 + + + pio0_3 + 6 + + + pio1_3 + 7 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO4_STATUS + 0x00000020 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO4_CTRL + 0x00000024 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_rx + 1 + + + uart1_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_2 + 4 + + + sio_4 + 5 + + + pio0_4 + 6 + + + pio1_4 + 7 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO5_STATUS + 0x00000028 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO5_CTRL + 0x0000002c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_ss_n + 1 + + + uart1_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_2 + 4 + + + sio_5 + 5 + + + pio0_5 + 6 + + + pio1_5 + 7 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO6_STATUS + 0x00000030 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO6_CTRL + 0x00000034 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_sclk + 1 + + + uart1_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_3 + 4 + + + sio_6 + 5 + + + pio0_6 + 6 + + + pio1_6 + 7 + + + usb_muxing_extphy_softcon + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO7_STATUS + 0x00000038 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO7_CTRL + 0x0000003c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_tx + 1 + + + uart1_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_3 + 4 + + + sio_7 + 5 + + + pio0_7 + 6 + + + pio1_7 + 7 + + + usb_muxing_extphy_oe_n + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO8_STATUS + 0x00000040 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO8_CTRL + 0x00000044 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_rx + 1 + + + uart1_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_4 + 4 + + + sio_8 + 5 + + + pio0_8 + 6 + + + pio1_8 + 7 + + + usb_muxing_extphy_rcv + 8 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO9_STATUS + 0x00000048 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO9_CTRL + 0x0000004c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_ss_n + 1 + + + uart1_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_4 + 4 + + + sio_9 + 5 + + + pio0_9 + 6 + + + pio1_9 + 7 + + + usb_muxing_extphy_vp + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO10_STATUS + 0x00000050 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO10_CTRL + 0x00000054 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_sclk + 1 + + + uart1_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_5 + 4 + + + sio_10 + 5 + + + pio0_10 + 6 + + + pio1_10 + 7 + + + usb_muxing_extphy_vm + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO11_STATUS + 0x00000058 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO11_CTRL + 0x0000005c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_tx + 1 + + + uart1_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_5 + 4 + + + sio_11 + 5 + + + pio0_11 + 6 + + + pio1_11 + 7 + + + usb_muxing_extphy_suspnd + 8 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO12_STATUS + 0x00000060 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO12_CTRL + 0x00000064 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_rx + 1 + + + uart0_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_6 + 4 + + + sio_12 + 5 + + + pio0_12 + 6 + + + pio1_12 + 7 + + + usb_muxing_extphy_speed + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO13_STATUS + 0x00000068 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO13_CTRL + 0x0000006c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_ss_n + 1 + + + uart0_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_6 + 4 + + + sio_13 + 5 + + + pio0_13 + 6 + + + pio1_13 + 7 + + + usb_muxing_extphy_vpo + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO14_STATUS + 0x00000070 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO14_CTRL + 0x00000074 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_sclk + 1 + + + uart0_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_7 + 4 + + + sio_14 + 5 + + + pio0_14 + 6 + + + pio1_14 + 7 + + + usb_muxing_extphy_vmo + 8 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO15_STATUS + 0x00000078 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO15_CTRL + 0x0000007c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_tx + 1 + + + uart0_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_7 + 4 + + + sio_15 + 5 + + + pio0_15 + 6 + + + pio1_15 + 7 + + + usb_muxing_digital_dp + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO16_STATUS + 0x00000080 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO16_CTRL + 0x00000084 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_rx + 1 + + + uart0_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_0 + 4 + + + sio_16 + 5 + + + pio0_16 + 6 + + + pio1_16 + 7 + + + usb_muxing_digital_dm + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO17_STATUS + 0x00000088 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO17_CTRL + 0x0000008c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_ss_n + 1 + + + uart0_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_0 + 4 + + + sio_17 + 5 + + + pio0_17 + 6 + + + pio1_17 + 7 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO18_STATUS + 0x00000090 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO18_CTRL + 0x00000094 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_sclk + 1 + + + uart0_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_1 + 4 + + + sio_18 + 5 + + + pio0_18 + 6 + + + pio1_18 + 7 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO19_STATUS + 0x00000098 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO19_CTRL + 0x0000009c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_tx + 1 + + + uart0_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_1 + 4 + + + sio_19 + 5 + + + pio0_19 + 6 + + + pio1_19 + 7 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO20_STATUS + 0x000000a0 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO20_CTRL + 0x000000a4 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_rx + 1 + + + uart1_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_2 + 4 + + + sio_20 + 5 + + + pio0_20 + 6 + + + pio1_20 + 7 + + + clocks_gpin_0 + 8 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO21_STATUS + 0x000000a8 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO21_CTRL + 0x000000ac + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_ss_n + 1 + + + uart1_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_2 + 4 + + + sio_21 + 5 + + + pio0_21 + 6 + + + pio1_21 + 7 + + + clocks_gpout_0 + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO22_STATUS + 0x000000b0 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO22_CTRL + 0x000000b4 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_sclk + 1 + + + uart1_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_3 + 4 + + + sio_22 + 5 + + + pio0_22 + 6 + + + pio1_22 + 7 + + + clocks_gpin_1 + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO23_STATUS + 0x000000b8 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO23_CTRL + 0x000000bc + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_tx + 1 + + + uart1_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_3 + 4 + + + sio_23 + 5 + + + pio0_23 + 6 + + + pio1_23 + 7 + + + clocks_gpout_1 + 8 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO24_STATUS + 0x000000c0 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO24_CTRL + 0x000000c4 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_rx + 1 + + + uart1_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_4 + 4 + + + sio_24 + 5 + + + pio0_24 + 6 + + + pio1_24 + 7 + + + clocks_gpout_2 + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO25_STATUS + 0x000000c8 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO25_CTRL + 0x000000cc + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_ss_n + 1 + + + uart1_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_4 + 4 + + + sio_25 + 5 + + + pio0_25 + 6 + + + pio1_25 + 7 + + + clocks_gpout_3 + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO26_STATUS + 0x000000d0 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO26_CTRL + 0x000000d4 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_sclk + 1 + + + uart1_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_5 + 4 + + + sio_26 + 5 + + + pio0_26 + 6 + + + pio1_26 + 7 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO27_STATUS + 0x000000d8 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO27_CTRL + 0x000000dc + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_tx + 1 + + + uart1_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_5 + 4 + + + sio_27 + 5 + + + pio0_27 + 6 + + + pio1_27 + 7 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO28_STATUS + 0x000000e0 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO28_CTRL + 0x000000e4 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_rx + 1 + + + uart0_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_6 + 4 + + + sio_28 + 5 + + + pio0_28 + 6 + + + pio1_28 + 7 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO29_STATUS + 0x000000e8 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO29_CTRL + 0x000000ec + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_ss_n + 1 + + + uart0_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_6 + 4 + + + sio_29 + 5 + + + pio0_29 + 6 + + + pio1_29 + 7 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + INTR0 + 0x000000f0 + Raw Interrupts + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + oneToClear + + + GPIO7_EDGE_LOW + [30:30] + read-write + oneToClear + + + GPIO7_LEVEL_HIGH + [29:29] + read-only + + + GPIO7_LEVEL_LOW + [28:28] + read-only + + + GPIO6_EDGE_HIGH + [27:27] + read-write + oneToClear + + + GPIO6_EDGE_LOW + [26:26] + read-write + oneToClear + + + GPIO6_LEVEL_HIGH + [25:25] + read-only + + + GPIO6_LEVEL_LOW + [24:24] + read-only + + + GPIO5_EDGE_HIGH + [23:23] + read-write + oneToClear + + + GPIO5_EDGE_LOW + [22:22] + read-write + oneToClear + + + GPIO5_LEVEL_HIGH + [21:21] + read-only + + + GPIO5_LEVEL_LOW + [20:20] + read-only + + + GPIO4_EDGE_HIGH + [19:19] + read-write + oneToClear + + + GPIO4_EDGE_LOW + [18:18] + read-write + oneToClear + + + GPIO4_LEVEL_HIGH + [17:17] + read-only + + + GPIO4_LEVEL_LOW + [16:16] + read-only + + + GPIO3_EDGE_HIGH + [15:15] + read-write + oneToClear + + + GPIO3_EDGE_LOW + [14:14] + read-write + oneToClear + + + GPIO3_LEVEL_HIGH + [13:13] + read-only + + + GPIO3_LEVEL_LOW + [12:12] + read-only + + + GPIO2_EDGE_HIGH + [11:11] + read-write + oneToClear + + + GPIO2_EDGE_LOW + [10:10] + read-write + oneToClear + + + GPIO2_LEVEL_HIGH + [9:9] + read-only + + + GPIO2_LEVEL_LOW + [8:8] + read-only + + + GPIO1_EDGE_HIGH + [7:7] + read-write + oneToClear + + + GPIO1_EDGE_LOW + [6:6] + read-write + oneToClear + + + GPIO1_LEVEL_HIGH + [5:5] + read-only + + + GPIO1_LEVEL_LOW + [4:4] + read-only + + + GPIO0_EDGE_HIGH + [3:3] + read-write + oneToClear + + + GPIO0_EDGE_LOW + [2:2] + read-write + oneToClear + + + GPIO0_LEVEL_HIGH + [1:1] + read-only + + + GPIO0_LEVEL_LOW + [0:0] + read-only + + + + + INTR1 + 0x000000f4 + Raw Interrupts + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + oneToClear + + + GPIO15_EDGE_LOW + [30:30] + read-write + oneToClear + + + GPIO15_LEVEL_HIGH + [29:29] + read-only + + + GPIO15_LEVEL_LOW + [28:28] + read-only + + + GPIO14_EDGE_HIGH + [27:27] + read-write + oneToClear + + + GPIO14_EDGE_LOW + [26:26] + read-write + oneToClear + + + GPIO14_LEVEL_HIGH + [25:25] + read-only + + + GPIO14_LEVEL_LOW + [24:24] + read-only + + + GPIO13_EDGE_HIGH + [23:23] + read-write + oneToClear + + + GPIO13_EDGE_LOW + [22:22] + read-write + oneToClear + + + GPIO13_LEVEL_HIGH + [21:21] + read-only + + + GPIO13_LEVEL_LOW + [20:20] + read-only + + + GPIO12_EDGE_HIGH + [19:19] + read-write + oneToClear + + + GPIO12_EDGE_LOW + [18:18] + read-write + oneToClear + + + GPIO12_LEVEL_HIGH + [17:17] + read-only + + + GPIO12_LEVEL_LOW + [16:16] + read-only + + + GPIO11_EDGE_HIGH + [15:15] + read-write + oneToClear + + + GPIO11_EDGE_LOW + [14:14] + read-write + oneToClear + + + GPIO11_LEVEL_HIGH + [13:13] + read-only + + + GPIO11_LEVEL_LOW + [12:12] + read-only + + + GPIO10_EDGE_HIGH + [11:11] + read-write + oneToClear + + + GPIO10_EDGE_LOW + [10:10] + read-write + oneToClear + + + GPIO10_LEVEL_HIGH + [9:9] + read-only + + + GPIO10_LEVEL_LOW + [8:8] + read-only + + + GPIO9_EDGE_HIGH + [7:7] + read-write + oneToClear + + + GPIO9_EDGE_LOW + [6:6] + read-write + oneToClear + + + GPIO9_LEVEL_HIGH + [5:5] + read-only + + + GPIO9_LEVEL_LOW + [4:4] + read-only + + + GPIO8_EDGE_HIGH + [3:3] + read-write + oneToClear + + + GPIO8_EDGE_LOW + [2:2] + read-write + oneToClear + + + GPIO8_LEVEL_HIGH + [1:1] + read-only + + + GPIO8_LEVEL_LOW + [0:0] + read-only + + + + + INTR2 + 0x000000f8 + Raw Interrupts + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + oneToClear + + + GPIO23_EDGE_LOW + [30:30] + read-write + oneToClear + + + GPIO23_LEVEL_HIGH + [29:29] + read-only + + + GPIO23_LEVEL_LOW + [28:28] + read-only + + + GPIO22_EDGE_HIGH + [27:27] + read-write + oneToClear + + + GPIO22_EDGE_LOW + [26:26] + read-write + oneToClear + + + GPIO22_LEVEL_HIGH + [25:25] + read-only + + + GPIO22_LEVEL_LOW + [24:24] + read-only + + + GPIO21_EDGE_HIGH + [23:23] + read-write + oneToClear + + + GPIO21_EDGE_LOW + [22:22] + read-write + oneToClear + + + GPIO21_LEVEL_HIGH + [21:21] + read-only + + + GPIO21_LEVEL_LOW + [20:20] + read-only + + + GPIO20_EDGE_HIGH + [19:19] + read-write + oneToClear + + + GPIO20_EDGE_LOW + [18:18] + read-write + oneToClear + + + GPIO20_LEVEL_HIGH + [17:17] + read-only + + + GPIO20_LEVEL_LOW + [16:16] + read-only + + + GPIO19_EDGE_HIGH + [15:15] + read-write + oneToClear + + + GPIO19_EDGE_LOW + [14:14] + read-write + oneToClear + + + GPIO19_LEVEL_HIGH + [13:13] + read-only + + + GPIO19_LEVEL_LOW + [12:12] + read-only + + + GPIO18_EDGE_HIGH + [11:11] + read-write + oneToClear + + + GPIO18_EDGE_LOW + [10:10] + read-write + oneToClear + + + GPIO18_LEVEL_HIGH + [9:9] + read-only + + + GPIO18_LEVEL_LOW + [8:8] + read-only + + + GPIO17_EDGE_HIGH + [7:7] + read-write + oneToClear + + + GPIO17_EDGE_LOW + [6:6] + read-write + oneToClear + + + GPIO17_LEVEL_HIGH + [5:5] + read-only + + + GPIO17_LEVEL_LOW + [4:4] + read-only + + + GPIO16_EDGE_HIGH + [3:3] + read-write + oneToClear + + + GPIO16_EDGE_LOW + [2:2] + read-write + oneToClear + + + GPIO16_LEVEL_HIGH + [1:1] + read-only + + + GPIO16_LEVEL_LOW + [0:0] + read-only + + + + + INTR3 + 0x000000fc + Raw Interrupts + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + oneToClear + + + GPIO29_EDGE_LOW + [22:22] + read-write + oneToClear + + + GPIO29_LEVEL_HIGH + [21:21] + read-only + + + GPIO29_LEVEL_LOW + [20:20] + read-only + + + GPIO28_EDGE_HIGH + [19:19] + read-write + oneToClear + + + GPIO28_EDGE_LOW + [18:18] + read-write + oneToClear + + + GPIO28_LEVEL_HIGH + [17:17] + read-only + + + GPIO28_LEVEL_LOW + [16:16] + read-only + + + GPIO27_EDGE_HIGH + [15:15] + read-write + oneToClear + + + GPIO27_EDGE_LOW + [14:14] + read-write + oneToClear + + + GPIO27_LEVEL_HIGH + [13:13] + read-only + + + GPIO27_LEVEL_LOW + [12:12] + read-only + + + GPIO26_EDGE_HIGH + [11:11] + read-write + oneToClear + + + GPIO26_EDGE_LOW + [10:10] + read-write + oneToClear + + + GPIO26_LEVEL_HIGH + [9:9] + read-only + + + GPIO26_LEVEL_LOW + [8:8] + read-only + + + GPIO25_EDGE_HIGH + [7:7] + read-write + oneToClear + + + GPIO25_EDGE_LOW + [6:6] + read-write + oneToClear + + + GPIO25_LEVEL_HIGH + [5:5] + read-only + + + GPIO25_LEVEL_LOW + [4:4] + read-only + + + GPIO24_EDGE_HIGH + [3:3] + read-write + oneToClear + + + GPIO24_EDGE_LOW + [2:2] + read-write + oneToClear + + + GPIO24_LEVEL_HIGH + [1:1] + read-only + + + GPIO24_LEVEL_LOW + [0:0] + read-only + + + + + PROC0_INTE0 + 0x00000100 + Interrupt Enable for proc0 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTE1 + 0x00000104 + Interrupt Enable for proc0 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTE2 + 0x00000108 + Interrupt Enable for proc0 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTE3 + 0x0000010c + Interrupt Enable for proc0 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTF0 + 0x00000110 + Interrupt Force for proc0 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTF1 + 0x00000114 + Interrupt Force for proc0 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTF2 + 0x00000118 + Interrupt Force for proc0 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTF3 + 0x0000011c + Interrupt Force for proc0 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTS0 + 0x00000120 + Interrupt status after masking & forcing for proc0 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-only + + + GPIO7_EDGE_LOW + [30:30] + read-only + + + GPIO7_LEVEL_HIGH + [29:29] + read-only + + + GPIO7_LEVEL_LOW + [28:28] + read-only + + + GPIO6_EDGE_HIGH + [27:27] + read-only + + + GPIO6_EDGE_LOW + [26:26] + read-only + + + GPIO6_LEVEL_HIGH + [25:25] + read-only + + + GPIO6_LEVEL_LOW + [24:24] + read-only + + + GPIO5_EDGE_HIGH + [23:23] + read-only + + + GPIO5_EDGE_LOW + [22:22] + read-only + + + GPIO5_LEVEL_HIGH + [21:21] + read-only + + + GPIO5_LEVEL_LOW + [20:20] + read-only + + + GPIO4_EDGE_HIGH + [19:19] + read-only + + + GPIO4_EDGE_LOW + [18:18] + read-only + + + GPIO4_LEVEL_HIGH + [17:17] + read-only + + + GPIO4_LEVEL_LOW + [16:16] + read-only + + + GPIO3_EDGE_HIGH + [15:15] + read-only + + + GPIO3_EDGE_LOW + [14:14] + read-only + + + GPIO3_LEVEL_HIGH + [13:13] + read-only + + + GPIO3_LEVEL_LOW + [12:12] + read-only + + + GPIO2_EDGE_HIGH + [11:11] + read-only + + + GPIO2_EDGE_LOW + [10:10] + read-only + + + GPIO2_LEVEL_HIGH + [9:9] + read-only + + + GPIO2_LEVEL_LOW + [8:8] + read-only + + + GPIO1_EDGE_HIGH + [7:7] + read-only + + + GPIO1_EDGE_LOW + [6:6] + read-only + + + GPIO1_LEVEL_HIGH + [5:5] + read-only + + + GPIO1_LEVEL_LOW + [4:4] + read-only + + + GPIO0_EDGE_HIGH + [3:3] + read-only + + + GPIO0_EDGE_LOW + [2:2] + read-only + + + GPIO0_LEVEL_HIGH + [1:1] + read-only + + + GPIO0_LEVEL_LOW + [0:0] + read-only + + + + + PROC0_INTS1 + 0x00000124 + Interrupt status after masking & forcing for proc0 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-only + + + GPIO15_EDGE_LOW + [30:30] + read-only + + + GPIO15_LEVEL_HIGH + [29:29] + read-only + + + GPIO15_LEVEL_LOW + [28:28] + read-only + + + GPIO14_EDGE_HIGH + [27:27] + read-only + + + GPIO14_EDGE_LOW + [26:26] + read-only + + + GPIO14_LEVEL_HIGH + [25:25] + read-only + + + GPIO14_LEVEL_LOW + [24:24] + read-only + + + GPIO13_EDGE_HIGH + [23:23] + read-only + + + GPIO13_EDGE_LOW + [22:22] + read-only + + + GPIO13_LEVEL_HIGH + [21:21] + read-only + + + GPIO13_LEVEL_LOW + [20:20] + read-only + + + GPIO12_EDGE_HIGH + [19:19] + read-only + + + GPIO12_EDGE_LOW + [18:18] + read-only + + + GPIO12_LEVEL_HIGH + [17:17] + read-only + + + GPIO12_LEVEL_LOW + [16:16] + read-only + + + GPIO11_EDGE_HIGH + [15:15] + read-only + + + GPIO11_EDGE_LOW + [14:14] + read-only + + + GPIO11_LEVEL_HIGH + [13:13] + read-only + + + GPIO11_LEVEL_LOW + [12:12] + read-only + + + GPIO10_EDGE_HIGH + [11:11] + read-only + + + GPIO10_EDGE_LOW + [10:10] + read-only + + + GPIO10_LEVEL_HIGH + [9:9] + read-only + + + GPIO10_LEVEL_LOW + [8:8] + read-only + + + GPIO9_EDGE_HIGH + [7:7] + read-only + + + GPIO9_EDGE_LOW + [6:6] + read-only + + + GPIO9_LEVEL_HIGH + [5:5] + read-only + + + GPIO9_LEVEL_LOW + [4:4] + read-only + + + GPIO8_EDGE_HIGH + [3:3] + read-only + + + GPIO8_EDGE_LOW + [2:2] + read-only + + + GPIO8_LEVEL_HIGH + [1:1] + read-only + + + GPIO8_LEVEL_LOW + [0:0] + read-only + + + + + PROC0_INTS2 + 0x00000128 + Interrupt status after masking & forcing for proc0 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-only + + + GPIO23_EDGE_LOW + [30:30] + read-only + + + GPIO23_LEVEL_HIGH + [29:29] + read-only + + + GPIO23_LEVEL_LOW + [28:28] + read-only + + + GPIO22_EDGE_HIGH + [27:27] + read-only + + + GPIO22_EDGE_LOW + [26:26] + read-only + + + GPIO22_LEVEL_HIGH + [25:25] + read-only + + + GPIO22_LEVEL_LOW + [24:24] + read-only + + + GPIO21_EDGE_HIGH + [23:23] + read-only + + + GPIO21_EDGE_LOW + [22:22] + read-only + + + GPIO21_LEVEL_HIGH + [21:21] + read-only + + + GPIO21_LEVEL_LOW + [20:20] + read-only + + + GPIO20_EDGE_HIGH + [19:19] + read-only + + + GPIO20_EDGE_LOW + [18:18] + read-only + + + GPIO20_LEVEL_HIGH + [17:17] + read-only + + + GPIO20_LEVEL_LOW + [16:16] + read-only + + + GPIO19_EDGE_HIGH + [15:15] + read-only + + + GPIO19_EDGE_LOW + [14:14] + read-only + + + GPIO19_LEVEL_HIGH + [13:13] + read-only + + + GPIO19_LEVEL_LOW + [12:12] + read-only + + + GPIO18_EDGE_HIGH + [11:11] + read-only + + + GPIO18_EDGE_LOW + [10:10] + read-only + + + GPIO18_LEVEL_HIGH + [9:9] + read-only + + + GPIO18_LEVEL_LOW + [8:8] + read-only + + + GPIO17_EDGE_HIGH + [7:7] + read-only + + + GPIO17_EDGE_LOW + [6:6] + read-only + + + GPIO17_LEVEL_HIGH + [5:5] + read-only + + + GPIO17_LEVEL_LOW + [4:4] + read-only + + + GPIO16_EDGE_HIGH + [3:3] + read-only + + + GPIO16_EDGE_LOW + [2:2] + read-only + + + GPIO16_LEVEL_HIGH + [1:1] + read-only + + + GPIO16_LEVEL_LOW + [0:0] + read-only + + + + + PROC0_INTS3 + 0x0000012c + Interrupt status after masking & forcing for proc0 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-only + + + GPIO29_EDGE_LOW + [22:22] + read-only + + + GPIO29_LEVEL_HIGH + [21:21] + read-only + + + GPIO29_LEVEL_LOW + [20:20] + read-only + + + GPIO28_EDGE_HIGH + [19:19] + read-only + + + GPIO28_EDGE_LOW + [18:18] + read-only + + + GPIO28_LEVEL_HIGH + [17:17] + read-only + + + GPIO28_LEVEL_LOW + [16:16] + read-only + + + GPIO27_EDGE_HIGH + [15:15] + read-only + + + GPIO27_EDGE_LOW + [14:14] + read-only + + + GPIO27_LEVEL_HIGH + [13:13] + read-only + + + GPIO27_LEVEL_LOW + [12:12] + read-only + + + GPIO26_EDGE_HIGH + [11:11] + read-only + + + GPIO26_EDGE_LOW + [10:10] + read-only + + + GPIO26_LEVEL_HIGH + [9:9] + read-only + + + GPIO26_LEVEL_LOW + [8:8] + read-only + + + GPIO25_EDGE_HIGH + [7:7] + read-only + + + GPIO25_EDGE_LOW + [6:6] + read-only + + + GPIO25_LEVEL_HIGH + [5:5] + read-only + + + GPIO25_LEVEL_LOW + [4:4] + read-only + + + GPIO24_EDGE_HIGH + [3:3] + read-only + + + GPIO24_EDGE_LOW + [2:2] + read-only + + + GPIO24_LEVEL_HIGH + [1:1] + read-only + + + GPIO24_LEVEL_LOW + [0:0] + read-only + + + + + PROC1_INTE0 + 0x00000130 + Interrupt Enable for proc1 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTE1 + 0x00000134 + Interrupt Enable for proc1 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTE2 + 0x00000138 + Interrupt Enable for proc1 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTE3 + 0x0000013c + Interrupt Enable for proc1 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTF0 + 0x00000140 + Interrupt Force for proc1 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTF1 + 0x00000144 + Interrupt Force for proc1 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTF2 + 0x00000148 + Interrupt Force for proc1 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTF3 + 0x0000014c + Interrupt Force for proc1 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTS0 + 0x00000150 + Interrupt status after masking & forcing for proc1 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-only + + + GPIO7_EDGE_LOW + [30:30] + read-only + + + GPIO7_LEVEL_HIGH + [29:29] + read-only + + + GPIO7_LEVEL_LOW + [28:28] + read-only + + + GPIO6_EDGE_HIGH + [27:27] + read-only + + + GPIO6_EDGE_LOW + [26:26] + read-only + + + GPIO6_LEVEL_HIGH + [25:25] + read-only + + + GPIO6_LEVEL_LOW + [24:24] + read-only + + + GPIO5_EDGE_HIGH + [23:23] + read-only + + + GPIO5_EDGE_LOW + [22:22] + read-only + + + GPIO5_LEVEL_HIGH + [21:21] + read-only + + + GPIO5_LEVEL_LOW + [20:20] + read-only + + + GPIO4_EDGE_HIGH + [19:19] + read-only + + + GPIO4_EDGE_LOW + [18:18] + read-only + + + GPIO4_LEVEL_HIGH + [17:17] + read-only + + + GPIO4_LEVEL_LOW + [16:16] + read-only + + + GPIO3_EDGE_HIGH + [15:15] + read-only + + + GPIO3_EDGE_LOW + [14:14] + read-only + + + GPIO3_LEVEL_HIGH + [13:13] + read-only + + + GPIO3_LEVEL_LOW + [12:12] + read-only + + + GPIO2_EDGE_HIGH + [11:11] + read-only + + + GPIO2_EDGE_LOW + [10:10] + read-only + + + GPIO2_LEVEL_HIGH + [9:9] + read-only + + + GPIO2_LEVEL_LOW + [8:8] + read-only + + + GPIO1_EDGE_HIGH + [7:7] + read-only + + + GPIO1_EDGE_LOW + [6:6] + read-only + + + GPIO1_LEVEL_HIGH + [5:5] + read-only + + + GPIO1_LEVEL_LOW + [4:4] + read-only + + + GPIO0_EDGE_HIGH + [3:3] + read-only + + + GPIO0_EDGE_LOW + [2:2] + read-only + + + GPIO0_LEVEL_HIGH + [1:1] + read-only + + + GPIO0_LEVEL_LOW + [0:0] + read-only + + + + + PROC1_INTS1 + 0x00000154 + Interrupt status after masking & forcing for proc1 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-only + + + GPIO15_EDGE_LOW + [30:30] + read-only + + + GPIO15_LEVEL_HIGH + [29:29] + read-only + + + GPIO15_LEVEL_LOW + [28:28] + read-only + + + GPIO14_EDGE_HIGH + [27:27] + read-only + + + GPIO14_EDGE_LOW + [26:26] + read-only + + + GPIO14_LEVEL_HIGH + [25:25] + read-only + + + GPIO14_LEVEL_LOW + [24:24] + read-only + + + GPIO13_EDGE_HIGH + [23:23] + read-only + + + GPIO13_EDGE_LOW + [22:22] + read-only + + + GPIO13_LEVEL_HIGH + [21:21] + read-only + + + GPIO13_LEVEL_LOW + [20:20] + read-only + + + GPIO12_EDGE_HIGH + [19:19] + read-only + + + GPIO12_EDGE_LOW + [18:18] + read-only + + + GPIO12_LEVEL_HIGH + [17:17] + read-only + + + GPIO12_LEVEL_LOW + [16:16] + read-only + + + GPIO11_EDGE_HIGH + [15:15] + read-only + + + GPIO11_EDGE_LOW + [14:14] + read-only + + + GPIO11_LEVEL_HIGH + [13:13] + read-only + + + GPIO11_LEVEL_LOW + [12:12] + read-only + + + GPIO10_EDGE_HIGH + [11:11] + read-only + + + GPIO10_EDGE_LOW + [10:10] + read-only + + + GPIO10_LEVEL_HIGH + [9:9] + read-only + + + GPIO10_LEVEL_LOW + [8:8] + read-only + + + GPIO9_EDGE_HIGH + [7:7] + read-only + + + GPIO9_EDGE_LOW + [6:6] + read-only + + + GPIO9_LEVEL_HIGH + [5:5] + read-only + + + GPIO9_LEVEL_LOW + [4:4] + read-only + + + GPIO8_EDGE_HIGH + [3:3] + read-only + + + GPIO8_EDGE_LOW + [2:2] + read-only + + + GPIO8_LEVEL_HIGH + [1:1] + read-only + + + GPIO8_LEVEL_LOW + [0:0] + read-only + + + + + PROC1_INTS2 + 0x00000158 + Interrupt status after masking & forcing for proc1 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-only + + + GPIO23_EDGE_LOW + [30:30] + read-only + + + GPIO23_LEVEL_HIGH + [29:29] + read-only + + + GPIO23_LEVEL_LOW + [28:28] + read-only + + + GPIO22_EDGE_HIGH + [27:27] + read-only + + + GPIO22_EDGE_LOW + [26:26] + read-only + + + GPIO22_LEVEL_HIGH + [25:25] + read-only + + + GPIO22_LEVEL_LOW + [24:24] + read-only + + + GPIO21_EDGE_HIGH + [23:23] + read-only + + + GPIO21_EDGE_LOW + [22:22] + read-only + + + GPIO21_LEVEL_HIGH + [21:21] + read-only + + + GPIO21_LEVEL_LOW + [20:20] + read-only + + + GPIO20_EDGE_HIGH + [19:19] + read-only + + + GPIO20_EDGE_LOW + [18:18] + read-only + + + GPIO20_LEVEL_HIGH + [17:17] + read-only + + + GPIO20_LEVEL_LOW + [16:16] + read-only + + + GPIO19_EDGE_HIGH + [15:15] + read-only + + + GPIO19_EDGE_LOW + [14:14] + read-only + + + GPIO19_LEVEL_HIGH + [13:13] + read-only + + + GPIO19_LEVEL_LOW + [12:12] + read-only + + + GPIO18_EDGE_HIGH + [11:11] + read-only + + + GPIO18_EDGE_LOW + [10:10] + read-only + + + GPIO18_LEVEL_HIGH + [9:9] + read-only + + + GPIO18_LEVEL_LOW + [8:8] + read-only + + + GPIO17_EDGE_HIGH + [7:7] + read-only + + + GPIO17_EDGE_LOW + [6:6] + read-only + + + GPIO17_LEVEL_HIGH + [5:5] + read-only + + + GPIO17_LEVEL_LOW + [4:4] + read-only + + + GPIO16_EDGE_HIGH + [3:3] + read-only + + + GPIO16_EDGE_LOW + [2:2] + read-only + + + GPIO16_LEVEL_HIGH + [1:1] + read-only + + + GPIO16_LEVEL_LOW + [0:0] + read-only + + + + + PROC1_INTS3 + 0x0000015c + Interrupt status after masking & forcing for proc1 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-only + + + GPIO29_EDGE_LOW + [22:22] + read-only + + + GPIO29_LEVEL_HIGH + [21:21] + read-only + + + GPIO29_LEVEL_LOW + [20:20] + read-only + + + GPIO28_EDGE_HIGH + [19:19] + read-only + + + GPIO28_EDGE_LOW + [18:18] + read-only + + + GPIO28_LEVEL_HIGH + [17:17] + read-only + + + GPIO28_LEVEL_LOW + [16:16] + read-only + + + GPIO27_EDGE_HIGH + [15:15] + read-only + + + GPIO27_EDGE_LOW + [14:14] + read-only + + + GPIO27_LEVEL_HIGH + [13:13] + read-only + + + GPIO27_LEVEL_LOW + [12:12] + read-only + + + GPIO26_EDGE_HIGH + [11:11] + read-only + + + GPIO26_EDGE_LOW + [10:10] + read-only + + + GPIO26_LEVEL_HIGH + [9:9] + read-only + + + GPIO26_LEVEL_LOW + [8:8] + read-only + + + GPIO25_EDGE_HIGH + [7:7] + read-only + + + GPIO25_EDGE_LOW + [6:6] + read-only + + + GPIO25_LEVEL_HIGH + [5:5] + read-only + + + GPIO25_LEVEL_LOW + [4:4] + read-only + + + GPIO24_EDGE_HIGH + [3:3] + read-only + + + GPIO24_EDGE_LOW + [2:2] + read-only + + + GPIO24_LEVEL_HIGH + [1:1] + read-only + + + GPIO24_LEVEL_LOW + [0:0] + read-only + + + + + DORMANT_WAKE_INTE0 + 0x00000160 + Interrupt Enable for dormant_wake + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTE1 + 0x00000164 + Interrupt Enable for dormant_wake + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTE2 + 0x00000168 + Interrupt Enable for dormant_wake + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTE3 + 0x0000016c + Interrupt Enable for dormant_wake + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTF0 + 0x00000170 + Interrupt Force for dormant_wake + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTF1 + 0x00000174 + Interrupt Force for dormant_wake + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTF2 + 0x00000178 + Interrupt Force for dormant_wake + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTF3 + 0x0000017c + Interrupt Force for dormant_wake + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTS0 + 0x00000180 + Interrupt status after masking & forcing for dormant_wake + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-only + + + GPIO7_EDGE_LOW + [30:30] + read-only + + + GPIO7_LEVEL_HIGH + [29:29] + read-only + + + GPIO7_LEVEL_LOW + [28:28] + read-only + + + GPIO6_EDGE_HIGH + [27:27] + read-only + + + GPIO6_EDGE_LOW + [26:26] + read-only + + + GPIO6_LEVEL_HIGH + [25:25] + read-only + + + GPIO6_LEVEL_LOW + [24:24] + read-only + + + GPIO5_EDGE_HIGH + [23:23] + read-only + + + GPIO5_EDGE_LOW + [22:22] + read-only + + + GPIO5_LEVEL_HIGH + [21:21] + read-only + + + GPIO5_LEVEL_LOW + [20:20] + read-only + + + GPIO4_EDGE_HIGH + [19:19] + read-only + + + GPIO4_EDGE_LOW + [18:18] + read-only + + + GPIO4_LEVEL_HIGH + [17:17] + read-only + + + GPIO4_LEVEL_LOW + [16:16] + read-only + + + GPIO3_EDGE_HIGH + [15:15] + read-only + + + GPIO3_EDGE_LOW + [14:14] + read-only + + + GPIO3_LEVEL_HIGH + [13:13] + read-only + + + GPIO3_LEVEL_LOW + [12:12] + read-only + + + GPIO2_EDGE_HIGH + [11:11] + read-only + + + GPIO2_EDGE_LOW + [10:10] + read-only + + + GPIO2_LEVEL_HIGH + [9:9] + read-only + + + GPIO2_LEVEL_LOW + [8:8] + read-only + + + GPIO1_EDGE_HIGH + [7:7] + read-only + + + GPIO1_EDGE_LOW + [6:6] + read-only + + + GPIO1_LEVEL_HIGH + [5:5] + read-only + + + GPIO1_LEVEL_LOW + [4:4] + read-only + + + GPIO0_EDGE_HIGH + [3:3] + read-only + + + GPIO0_EDGE_LOW + [2:2] + read-only + + + GPIO0_LEVEL_HIGH + [1:1] + read-only + + + GPIO0_LEVEL_LOW + [0:0] + read-only + + + + + DORMANT_WAKE_INTS1 + 0x00000184 + Interrupt status after masking & forcing for dormant_wake + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-only + + + GPIO15_EDGE_LOW + [30:30] + read-only + + + GPIO15_LEVEL_HIGH + [29:29] + read-only + + + GPIO15_LEVEL_LOW + [28:28] + read-only + + + GPIO14_EDGE_HIGH + [27:27] + read-only + + + GPIO14_EDGE_LOW + [26:26] + read-only + + + GPIO14_LEVEL_HIGH + [25:25] + read-only + + + GPIO14_LEVEL_LOW + [24:24] + read-only + + + GPIO13_EDGE_HIGH + [23:23] + read-only + + + GPIO13_EDGE_LOW + [22:22] + read-only + + + GPIO13_LEVEL_HIGH + [21:21] + read-only + + + GPIO13_LEVEL_LOW + [20:20] + read-only + + + GPIO12_EDGE_HIGH + [19:19] + read-only + + + GPIO12_EDGE_LOW + [18:18] + read-only + + + GPIO12_LEVEL_HIGH + [17:17] + read-only + + + GPIO12_LEVEL_LOW + [16:16] + read-only + + + GPIO11_EDGE_HIGH + [15:15] + read-only + + + GPIO11_EDGE_LOW + [14:14] + read-only + + + GPIO11_LEVEL_HIGH + [13:13] + read-only + + + GPIO11_LEVEL_LOW + [12:12] + read-only + + + GPIO10_EDGE_HIGH + [11:11] + read-only + + + GPIO10_EDGE_LOW + [10:10] + read-only + + + GPIO10_LEVEL_HIGH + [9:9] + read-only + + + GPIO10_LEVEL_LOW + [8:8] + read-only + + + GPIO9_EDGE_HIGH + [7:7] + read-only + + + GPIO9_EDGE_LOW + [6:6] + read-only + + + GPIO9_LEVEL_HIGH + [5:5] + read-only + + + GPIO9_LEVEL_LOW + [4:4] + read-only + + + GPIO8_EDGE_HIGH + [3:3] + read-only + + + GPIO8_EDGE_LOW + [2:2] + read-only + + + GPIO8_LEVEL_HIGH + [1:1] + read-only + + + GPIO8_LEVEL_LOW + [0:0] + read-only + + + + + DORMANT_WAKE_INTS2 + 0x00000188 + Interrupt status after masking & forcing for dormant_wake + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-only + + + GPIO23_EDGE_LOW + [30:30] + read-only + + + GPIO23_LEVEL_HIGH + [29:29] + read-only + + + GPIO23_LEVEL_LOW + [28:28] + read-only + + + GPIO22_EDGE_HIGH + [27:27] + read-only + + + GPIO22_EDGE_LOW + [26:26] + read-only + + + GPIO22_LEVEL_HIGH + [25:25] + read-only + + + GPIO22_LEVEL_LOW + [24:24] + read-only + + + GPIO21_EDGE_HIGH + [23:23] + read-only + + + GPIO21_EDGE_LOW + [22:22] + read-only + + + GPIO21_LEVEL_HIGH + [21:21] + read-only + + + GPIO21_LEVEL_LOW + [20:20] + read-only + + + GPIO20_EDGE_HIGH + [19:19] + read-only + + + GPIO20_EDGE_LOW + [18:18] + read-only + + + GPIO20_LEVEL_HIGH + [17:17] + read-only + + + GPIO20_LEVEL_LOW + [16:16] + read-only + + + GPIO19_EDGE_HIGH + [15:15] + read-only + + + GPIO19_EDGE_LOW + [14:14] + read-only + + + GPIO19_LEVEL_HIGH + [13:13] + read-only + + + GPIO19_LEVEL_LOW + [12:12] + read-only + + + GPIO18_EDGE_HIGH + [11:11] + read-only + + + GPIO18_EDGE_LOW + [10:10] + read-only + + + GPIO18_LEVEL_HIGH + [9:9] + read-only + + + GPIO18_LEVEL_LOW + [8:8] + read-only + + + GPIO17_EDGE_HIGH + [7:7] + read-only + + + GPIO17_EDGE_LOW + [6:6] + read-only + + + GPIO17_LEVEL_HIGH + [5:5] + read-only + + + GPIO17_LEVEL_LOW + [4:4] + read-only + + + GPIO16_EDGE_HIGH + [3:3] + read-only + + + GPIO16_EDGE_LOW + [2:2] + read-only + + + GPIO16_LEVEL_HIGH + [1:1] + read-only + + + GPIO16_LEVEL_LOW + [0:0] + read-only + + + + + DORMANT_WAKE_INTS3 + 0x0000018c + Interrupt status after masking & forcing for dormant_wake + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-only + + + GPIO29_EDGE_LOW + [22:22] + read-only + + + GPIO29_LEVEL_HIGH + [21:21] + read-only + + + GPIO29_LEVEL_LOW + [20:20] + read-only + + + GPIO28_EDGE_HIGH + [19:19] + read-only + + + GPIO28_EDGE_LOW + [18:18] + read-only + + + GPIO28_LEVEL_HIGH + [17:17] + read-only + + + GPIO28_LEVEL_LOW + [16:16] + read-only + + + GPIO27_EDGE_HIGH + [15:15] + read-only + + + GPIO27_EDGE_LOW + [14:14] + read-only + + + GPIO27_LEVEL_HIGH + [13:13] + read-only + + + GPIO27_LEVEL_LOW + [12:12] + read-only + + + GPIO26_EDGE_HIGH + [11:11] + read-only + + + GPIO26_EDGE_LOW + [10:10] + read-only + + + GPIO26_LEVEL_HIGH + [9:9] + read-only + + + GPIO26_LEVEL_LOW + [8:8] + read-only + + + GPIO25_EDGE_HIGH + [7:7] + read-only + + + GPIO25_EDGE_LOW + [6:6] + read-only + + + GPIO25_LEVEL_HIGH + [5:5] + read-only + + + GPIO25_LEVEL_LOW + [4:4] + read-only + + + GPIO24_EDGE_HIGH + [3:3] + read-only + + + GPIO24_EDGE_LOW + [2:2] + read-only + + + GPIO24_LEVEL_HIGH + [1:1] + read-only + + + GPIO24_LEVEL_LOW + [0:0] + read-only + + + + + + + SYSINFO + 0x40000000 + + 0 + 20 + registers + + + + CHIP_ID + 0x00000000 + JEDEC JEP-106 compliant chip identifier. + 0x00000000 + + + REVISION + [31:28] + read-only + + + PART + [27:12] + read-only + + + MANUFACTURER + [11:0] + read-only + + + + + PLATFORM + 0x00000004 + Platform register. Allows software to know what environment it is running in. + 0x00000000 + + + ASIC + [1:1] + read-only + + + FPGA + [0:0] + read-only + + + + + GITREF_RP2040 + 0x00000010 + Git hash of the chip source. Used to identify chip version. + 0x00000000 + + + GITREF_RP2040 + [31:0] + read-only + + + + + + + PPB + 0xe0000000 + + 0 + 60836 + registers + + + + SYST_CSR + 0x0000e010 + Use the SysTick Control and Status Register to enable the SysTick features. + 0x00000000 + + + COUNTFLAG + Returns 1 if timer counted to 0 since last time this was read. Clears on read by application or debugger. + [16:16] + read-only + + + CLKSOURCE + SysTick clock source. Always reads as one if SYST_CALIB reports NOREF. + Selects the SysTick timer clock source: + 0 = External reference clock. + 1 = Processor clock. + [2:2] + read-write + + + TICKINT + Enables SysTick exception request: + 0 = Counting down to zero does not assert the SysTick exception request. + 1 = Counting down to zero to asserts the SysTick exception request. + [1:1] + read-write + + + ENABLE + Enable SysTick counter: + 0 = Counter disabled. + 1 = Counter enabled. + [0:0] + read-write + + + + + SYST_RVR + 0x0000e014 + Use the SysTick Reload Value Register to specify the start value to load into the current value register when the counter reaches 0. It can be any value between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect because the SysTick interrupt and COUNTFLAG are activated when counting from 1 to 0. The reset value of this register is UNKNOWN. + To generate a multi-shot timer with a period of N processor clock cycles, use a RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 clock pulses, set RELOAD to 99. + 0x00000000 + + + RELOAD + Value to load into the SysTick Current Value Register when the counter reaches 0. + [23:0] + read-write + + + + + SYST_CVR + 0x0000e018 + Use the SysTick Current Value Register to find the current value in the register. The reset value of this register is UNKNOWN. + 0x00000000 + + + CURRENT + Reads return the current value of the SysTick counter. This register is write-clear. Writing to it with any value clears the register to 0. Clearing this register also clears the COUNTFLAG bit of the SysTick Control and Status Register. + [23:0] + read-write + + + + + SYST_CALIB + 0x0000e01c + Use the SysTick Calibration Value Register to enable software to scale to any required speed using divide and multiply. + 0x00000000 + + + NOREF + If reads as 1, the Reference clock is not provided - the CLKSOURCE bit of the SysTick Control and Status register will be forced to 1 and cannot be cleared to 0. + [31:31] + read-only + + + SKEW + If reads as 1, the calibration value for 10ms is inexact (due to clock frequency). + [30:30] + read-only + + + TENMS + An optional Reload value to be used for 10ms (100Hz) timing, subject to system clock skew errors. If the value reads as 0, the calibration value is not known. + [23:0] + read-only + + + + + NVIC_ISER + 0x0000e100 + Use the Interrupt Set-Enable Register to enable interrupts and determine which interrupts are currently enabled. + If a pending interrupt is enabled, the NVIC activates the interrupt based on its priority. If an interrupt is not enabled, asserting its interrupt signal changes the interrupt state to pending, but the NVIC never activates the interrupt, regardless of its priority. + 0x00000000 + + + SETENA + Interrupt set-enable bits. + Write: + 0 = No effect. + 1 = Enable interrupt. + Read: + 0 = Interrupt disabled. + 1 = Interrupt enabled. + [31:0] + read-write + + + + + NVIC_ICER + 0x0000e180 + Use the Interrupt Clear-Enable Registers to disable interrupts and determine which interrupts are currently enabled. + 0x00000000 + + + CLRENA + Interrupt clear-enable bits. + Write: + 0 = No effect. + 1 = Disable interrupt. + Read: + 0 = Interrupt disabled. + 1 = Interrupt enabled. + [31:0] + read-write + + + + + NVIC_ISPR + 0x0000e200 + The NVIC_ISPR forces interrupts into the pending state, and shows which interrupts are pending. + 0x00000000 + + + SETPEND + Interrupt set-pending bits. + Write: + 0 = No effect. + 1 = Changes interrupt state to pending. + Read: + 0 = Interrupt is not pending. + 1 = Interrupt is pending. + Note: Writing 1 to the NVIC_ISPR bit corresponding to: + An interrupt that is pending has no effect. + A disabled interrupt sets the state of that interrupt to pending. + [31:0] + read-write + + + + + NVIC_ICPR + 0x0000e280 + Use the Interrupt Clear-Pending Register to clear pending interrupts and determine which interrupts are currently pending. + 0x00000000 + + + CLRPEND + Interrupt clear-pending bits. + Write: + 0 = No effect. + 1 = Removes pending state and interrupt. + Read: + 0 = Interrupt is not pending. + 1 = Interrupt is pending. + [31:0] + read-write + + + + + NVIC_IPR0 + 0x0000e400 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + Note: Writing 1 to an NVIC_ICPR bit does not affect the active state of the corresponding interrupt. + These registers are only word-accessible + 0x00000000 + + + IP_3 + Priority of interrupt 3 + [31:30] + read-write + + + IP_2 + Priority of interrupt 2 + [23:22] + read-write + + + IP_1 + Priority of interrupt 1 + [15:14] + read-write + + + IP_0 + Priority of interrupt 0 + [7:6] + read-write + + + + + NVIC_IPR1 + 0x0000e404 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_7 + Priority of interrupt 7 + [31:30] + read-write + + + IP_6 + Priority of interrupt 6 + [23:22] + read-write + + + IP_5 + Priority of interrupt 5 + [15:14] + read-write + + + IP_4 + Priority of interrupt 4 + [7:6] + read-write + + + + + NVIC_IPR2 + 0x0000e408 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_11 + Priority of interrupt 11 + [31:30] + read-write + + + IP_10 + Priority of interrupt 10 + [23:22] + read-write + + + IP_9 + Priority of interrupt 9 + [15:14] + read-write + + + IP_8 + Priority of interrupt 8 + [7:6] + read-write + + + + + NVIC_IPR3 + 0x0000e40c + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_15 + Priority of interrupt 15 + [31:30] + read-write + + + IP_14 + Priority of interrupt 14 + [23:22] + read-write + + + IP_13 + Priority of interrupt 13 + [15:14] + read-write + + + IP_12 + Priority of interrupt 12 + [7:6] + read-write + + + + + NVIC_IPR4 + 0x0000e410 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_19 + Priority of interrupt 19 + [31:30] + read-write + + + IP_18 + Priority of interrupt 18 + [23:22] + read-write + + + IP_17 + Priority of interrupt 17 + [15:14] + read-write + + + IP_16 + Priority of interrupt 16 + [7:6] + read-write + + + + + NVIC_IPR5 + 0x0000e414 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_23 + Priority of interrupt 23 + [31:30] + read-write + + + IP_22 + Priority of interrupt 22 + [23:22] + read-write + + + IP_21 + Priority of interrupt 21 + [15:14] + read-write + + + IP_20 + Priority of interrupt 20 + [7:6] + read-write + + + + + NVIC_IPR6 + 0x0000e418 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_27 + Priority of interrupt 27 + [31:30] + read-write + + + IP_26 + Priority of interrupt 26 + [23:22] + read-write + + + IP_25 + Priority of interrupt 25 + [15:14] + read-write + + + IP_24 + Priority of interrupt 24 + [7:6] + read-write + + + + + NVIC_IPR7 + 0x0000e41c + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_31 + Priority of interrupt 31 + [31:30] + read-write + + + IP_30 + Priority of interrupt 30 + [23:22] + read-write + + + IP_29 + Priority of interrupt 29 + [15:14] + read-write + + + IP_28 + Priority of interrupt 28 + [7:6] + read-write + + + + + CPUID + 0x0000ed00 + Read the CPU ID Base Register to determine: the ID number of the processor core, the version number of the processor core, the implementation details of the processor core. + 0x410cc601 + + + IMPLEMENTER + Implementor code: 0x41 = ARM + [31:24] + read-only + + + VARIANT + Major revision number n in the rnpm revision status: + 0x0 = Revision 0. + [23:20] + read-only + + + ARCHITECTURE + Constant that defines the architecture of the processor: + 0xC = ARMv6-M architecture. + [19:16] + read-only + + + PARTNO + Number of processor within family: 0xC60 = Cortex-M0+ + [15:4] + read-only + + + REVISION + Minor revision number m in the rnpm revision status: + 0x1 = Patch 1. + [3:0] + read-only + + + + + ICSR + 0x0000ed04 + Use the Interrupt Control State Register to set a pending Non-Maskable Interrupt (NMI), set or clear a pending PendSV, set or clear a pending SysTick, check for pending exceptions, check the vector number of the highest priority pended exception, check the vector number of the active exception. + 0x00000000 + + + NMIPENDSET + Setting this bit will activate an NMI. Since NMI is the highest priority exception, it will activate as soon as it is registered. + NMI set-pending bit. + Write: + 0 = No effect. + 1 = Changes NMI exception state to pending. + Read: + 0 = NMI exception is not pending. + 1 = NMI exception is pending. + Because NMI is the highest-priority exception, normally the processor enters the NMI + exception handler as soon as it detects a write of 1 to this bit. Entering the handler then clears + this bit to 0. This means a read of this bit by the NMI exception handler returns 1 only if the + NMI signal is reasserted while the processor is executing that handler. + [31:31] + read-write + + + PENDSVSET + PendSV set-pending bit. + Write: + 0 = No effect. + 1 = Changes PendSV exception state to pending. + Read: + 0 = PendSV exception is not pending. + 1 = PendSV exception is pending. + Writing 1 to this bit is the only way to set the PendSV exception state to pending. + [28:28] + read-write + + + PENDSVCLR + PendSV clear-pending bit. + Write: + 0 = No effect. + 1 = Removes the pending state from the PendSV exception. + [27:27] + read-write + + + PENDSTSET + SysTick exception set-pending bit. + Write: + 0 = No effect. + 1 = Changes SysTick exception state to pending. + Read: + 0 = SysTick exception is not pending. + 1 = SysTick exception is pending. + [26:26] + read-write + + + PENDSTCLR + SysTick exception clear-pending bit. + Write: + 0 = No effect. + 1 = Removes the pending state from the SysTick exception. + This bit is WO. On a register read its value is Unknown. + [25:25] + read-write + + + ISRPREEMPT + The system can only access this bit when the core is halted. It indicates that a pending interrupt is to be taken in the next running cycle. If C_MASKINTS is clear in the Debug Halting Control and Status Register, the interrupt is serviced. + [23:23] + read-only + + + ISRPENDING + External interrupt pending flag + [22:22] + read-only + + + VECTPENDING + Indicates the exception number for the highest priority pending exception: 0 = no pending exceptions. Non zero = The pending state includes the effect of memory-mapped enable and mask registers. It does not include the PRIMASK special-purpose register qualifier. + [20:12] + read-only + + + VECTACTIVE + Active exception number field. Reset clears the VECTACTIVE field. + [8:0] + read-only + + + + + VTOR + 0x0000ed08 + The VTOR holds the vector table offset address. + 0x00000000 + + + TBLOFF + Bits [31:8] of the indicate the vector table offset address. + [31:8] + read-write + + + + + AIRCR + 0x0000ed0c + Use the Application Interrupt and Reset Control Register to: determine data endianness, clear all active state information from debug halt mode, request a system reset. + 0x00000000 + + + VECTKEY + Register key: + Reads as Unknown + On writes, write 0x05FA to VECTKEY, otherwise the write is ignored. + [31:16] + read-write + + + ENDIANESS + Data endianness implemented: + 0 = Little-endian. + [15:15] + read-only + + + SYSRESETREQ + Writing 1 to this bit causes the SYSRESETREQ signal to the outer system to be asserted to request a reset. The intention is to force a large system reset of all major components except for debug. The C_HALT bit in the DHCSR is cleared as a result of the system reset requested. The debugger does not lose contact with the device. + [2:2] + read-write + + + VECTCLRACTIVE + Clears all active state information for fixed and configurable exceptions. This bit: is self-clearing, can only be set by the DAP when the core is halted. When set: clears all active exception status of the processor, forces a return to Thread mode, forces an IPSR of 0. A debugger must re-initialize the stack. + [1:1] + read-write + + + + + SCR + 0x0000ed10 + System Control Register. Use the System Control Register for power-management functions: signal to the system when the processor can enter a low power state, control how the processor enters and exits low power states. + 0x00000000 + + + SEVONPEND + Send Event on Pending bit: + 0 = Only enabled interrupts or events can wakeup the processor, disabled interrupts are excluded. + 1 = Enabled events and all interrupts, including disabled interrupts, can wakeup the processor. + When an event or interrupt becomes pending, the event signal wakes up the processor from WFE. If the + processor is not waiting for an event, the event is registered and affects the next WFE. + The processor also wakes up on execution of an SEV instruction or an external event. + [4:4] + read-write + + + SLEEPDEEP + Controls whether the processor uses sleep or deep sleep as its low power mode: + 0 = Sleep. + 1 = Deep sleep. + [2:2] + read-write + + + SLEEPONEXIT + Indicates sleep-on-exit when returning from Handler mode to Thread mode: + 0 = Do not sleep when returning to Thread mode. + 1 = Enter sleep, or deep sleep, on return from an ISR to Thread mode. + Setting this bit to 1 enables an interrupt driven application to avoid returning to an empty main application. + [1:1] + read-write + + + + + CCR + 0x0000ed14 + The Configuration and Control Register permanently enables stack alignment and causes unaligned accesses to result in a Hard Fault. + 0x00000000 + + + STKALIGN + Always reads as one, indicates 8-byte stack alignment on exception entry. On exception entry, the processor uses bit[9] of the stacked PSR to indicate the stack alignment. On return from the exception it uses this stacked bit to restore the correct stack alignment. + [9:9] + read-only + + + UNALIGN_TRP + Always reads as one, indicates that all unaligned accesses generate a HardFault. + [3:3] + read-only + + + + + SHPR2 + 0x0000ed1c + System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 2 to set the priority of SVCall. + 0x00000000 + + + PRI_11 + Priority of system handler 11, SVCall + [31:30] + read-write + + + + + SHPR3 + 0x0000ed20 + System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 3 to set the priority of PendSV and SysTick. + 0x00000000 + + + PRI_15 + Priority of system handler 15, SysTick + [31:30] + read-write + + + PRI_14 + Priority of system handler 14, PendSV + [23:22] + read-write + + + + + SHCSR + 0x0000ed24 + Use the System Handler Control and State Register to determine or clear the pending status of SVCall. + 0x00000000 + + + SVCALLPENDED + Reads as 1 if SVCall is Pending. Write 1 to set pending SVCall, write 0 to clear pending SVCall. + [15:15] + read-write + + + + + MPU_TYPE + 0x0000ed90 + Read the MPU Type Register to determine if the processor implements an MPU, and how many regions the MPU supports. + 0x00000800 + + + IREGION + Instruction region. Reads as zero as ARMv6-M only supports a unified MPU. + [23:16] + read-only + + + DREGION + Number of regions supported by the MPU. + [15:8] + read-only + + + SEPARATE + Indicates support for separate instruction and data address maps. Reads as 0 as ARMv6-M only supports a unified MPU. + [0:0] + read-only + + + + + MPU_CTRL + 0x0000ed94 + Use the MPU Control Register to enable and disable the MPU, and to control whether the default memory map is enabled as a background region for privileged accesses, and whether the MPU is enabled for HardFaults and NMIs. + 0x00000000 + + + PRIVDEFENA + Controls whether the default memory map is enabled as a background region for privileged accesses. This bit is ignored when ENABLE is clear. + 0 = If the MPU is enabled, disables use of the default memory map. Any memory access to a location not + covered by any enabled region causes a fault. + 1 = If the MPU is enabled, enables use of the default memory map as a background region for privileged software accesses. + When enabled, the background region acts as if it is region number -1. Any region that is defined and enabled has priority over this default map. + [2:2] + read-write + + + HFNMIENA + Controls the use of the MPU for HardFaults and NMIs. Setting this bit when ENABLE is clear results in UNPREDICTABLE behaviour. + When the MPU is enabled: + 0 = MPU is disabled during HardFault and NMI handlers, regardless of the value of the ENABLE bit. + 1 = the MPU is enabled during HardFault and NMI handlers. + [1:1] + read-write + + + ENABLE + Enables the MPU. If the MPU is disabled, privileged and unprivileged accesses use the default memory map. + 0 = MPU disabled. + 1 = MPU enabled. + [0:0] + read-write + + + + + MPU_RNR + 0x0000ed98 + Use the MPU Region Number Register to select the region currently accessed by MPU_RBAR and MPU_RASR. + 0x00000000 + + + REGION + Indicates the MPU region referenced by the MPU_RBAR and MPU_RASR registers. + The MPU supports 8 memory regions, so the permitted values of this field are 0-7. + [3:0] + read-write + + + + + MPU_RBAR + 0x0000ed9c + Read the MPU Region Base Address Register to determine the base address of the region identified by MPU_RNR. Write to update the base address of said region or that of a specified region, with whose number MPU_RNR will also be updated. + 0x00000000 + + + ADDR + Base address of the region. + [31:8] + read-write + + + VALID + On writes, indicates whether the write must update the base address of the region identified by the REGION field, updating the MPU_RNR to indicate this new region. + Write: + 0 = MPU_RNR not changed, and the processor: + Updates the base address for the region specified in the MPU_RNR. + Ignores the value of the REGION field. + 1 = The processor: + Updates the value of the MPU_RNR to the value of the REGION field. + Updates the base address for the region specified in the REGION field. + Always reads as zero. + [4:4] + read-write + + + REGION + On writes, specifies the number of the region whose base address to update provided VALID is set written as 1. On reads, returns bits [3:0] of MPU_RNR. + [3:0] + read-write + + + + + MPU_RASR + 0x0000eda0 + Use the MPU Region Attribute and Size Register to define the size, access behaviour and memory type of the region identified by MPU_RNR, and enable that region. + 0x00000000 + + + ATTRS + The MPU Region Attribute field. Use to define the region attribute control. + 28 = XN: Instruction access disable bit: + 0 = Instruction fetches enabled. + 1 = Instruction fetches disabled. + 26:24 = AP: Access permission field + 18 = S: Shareable bit + 17 = C: Cacheable bit + 16 = B: Bufferable bit + [31:16] + read-write + + + SRD + Subregion Disable. For regions of 256 bytes or larger, each bit of this field controls whether one of the eight equal subregions is enabled. + [15:8] + read-write + + + SIZE + Indicates the region size. Region size in bytes = 2^(SIZE+1). The minimum permitted value is 7 (b00111) = 256Bytes + [5:1] + read-write + + + ENABLE + Enables the region. + [0:0] + read-write + + + + + + + SSI + DW_apb_ssi has the following features: + * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. + * APB3 and APB4 protocol support. + * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits. + * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices. + * Programmable Dual/Quad/Octal SPI support in Master Mode. + * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation. + * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes. + * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes. + * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests. + * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently. + * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus. + * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains. + * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates. + * Programmable features: + - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire. + - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation. + - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer. + * Configured features: + - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits. + - 1 slave select output. + - Hardware slave-select – Dedicated hardware slave-select line. + - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller. + - Interrupt polarity – active high interrupt lines. + - Serial clock polarity – low serial-clock polarity directly after reset. + - Serial clock phase – capture on first edge of serial-clock directly after reset. + 0x18000000 + + 0 + 252 + registers + + + + CTRLR0 + 0x00000000 + Control register 0 + 0x00000000 + + + SSTE + Slave select toggle enable + [24:24] + read-write + + + SPI_FRF + SPI frame format + [22:21] + read-write + + + STD + 0 + Standard 1-bit SPI frame format; 1 bit per SCK, full-duplex + + + DUAL + 1 + Dual-SPI frame format; two bits per SCK, half-duplex + + + QUAD + 2 + Quad-SPI frame format; four bits per SCK, half-duplex + + + + + DFS_32 + Data frame size in 32b transfer mode + Value of n -> n+1 clocks per frame. + [20:16] + read-write + + + CFS + Control frame size + Value of n -> n+1 clocks per frame. + [15:12] + read-write + + + SRL + Shift register loop (test mode) + [11:11] + read-write + + + SLV_OE + Slave output enable + [10:10] + read-write + + + TMOD + Transfer mode + [9:8] + read-write + + + TX_AND_RX + 0 + Both transmit and receive + + + TX_ONLY + 1 + Transmit only (not for FRF == 0, standard SPI mode) + + + RX_ONLY + 2 + Receive only (not for FRF == 0, standard SPI mode) + + + EEPROM_READ + 3 + EEPROM read mode (TX then RX; RX starts after control data TX'd) + + + + + SCPOL + Serial clock polarity + [7:7] + read-write + + + SCPH + Serial clock phase + [6:6] + read-write + + + FRF + Frame format + [5:4] + read-write + + + DFS + Data frame size + [3:0] + read-write + + + + + CTRLR1 + 0x00000004 + Master Control register 1 + 0x00000000 + + + NDF + Number of data frames + [15:0] + read-write + + + + + SSIENR + 0x00000008 + SSI Enable + 0x00000000 + + + SSI_EN + SSI enable + [0:0] + read-write + + + + + MWCR + 0x0000000c + Microwire Control + 0x00000000 + + + MHS + Microwire handshaking + [2:2] + read-write + + + MDD + Microwire control + [1:1] + read-write + + + MWMOD + Microwire transfer mode + [0:0] + read-write + + + + + SER + 0x00000010 + Slave enable + 0x00000000 + + + SER + For each bit: + 0 -> slave not selected + 1 -> slave selected + [0:0] + read-write + + + + + BAUDR + 0x00000014 + Baud rate + 0x00000000 + + + SCKDV + SSI clock divider + [15:0] + read-write + + + + + TXFTLR + 0x00000018 + TX FIFO threshold level + 0x00000000 + + + TFT + Transmit FIFO threshold + [7:0] + read-write + + + + + RXFTLR + 0x0000001c + RX FIFO threshold level + 0x00000000 + + + RFT + Receive FIFO threshold + [7:0] + read-write + + + + + TXFLR + 0x00000020 + TX FIFO level + 0x00000000 + + + TFTFL + Transmit FIFO level + [7:0] + read-only + + + + + RXFLR + 0x00000024 + RX FIFO level + 0x00000000 + + + RXTFL + Receive FIFO level + [7:0] + read-only + + + + + SR + 0x00000028 + Status register + 0x00000000 + + + DCOL + Data collision error + [6:6] + read-only + + + TXE + Transmission error + [5:5] + read-only + + + RFF + Receive FIFO full + [4:4] + read-only + + + RFNE + Receive FIFO not empty + [3:3] + read-only + + + TFE + Transmit FIFO empty + [2:2] + read-only + + + TFNF + Transmit FIFO not full + [1:1] + read-only + + + BUSY + SSI busy flag + [0:0] + read-only + + + + + IMR + 0x0000002c + Interrupt mask + 0x00000000 + + + MSTIM + Multi-master contention interrupt mask + [5:5] + read-write + + + RXFIM + Receive FIFO full interrupt mask + [4:4] + read-write + + + RXOIM + Receive FIFO overflow interrupt mask + [3:3] + read-write + + + RXUIM + Receive FIFO underflow interrupt mask + [2:2] + read-write + + + TXOIM + Transmit FIFO overflow interrupt mask + [1:1] + read-write + + + TXEIM + Transmit FIFO empty interrupt mask + [0:0] + read-write + + + + + ISR + 0x00000030 + Interrupt status + 0x00000000 + + + MSTIS + Multi-master contention interrupt status + [5:5] + read-only + + + RXFIS + Receive FIFO full interrupt status + [4:4] + read-only + + + RXOIS + Receive FIFO overflow interrupt status + [3:3] + read-only + + + RXUIS + Receive FIFO underflow interrupt status + [2:2] + read-only + + + TXOIS + Transmit FIFO overflow interrupt status + [1:1] + read-only + + + TXEIS + Transmit FIFO empty interrupt status + [0:0] + read-only + + + + + RISR + 0x00000034 + Raw interrupt status + 0x00000000 + + + MSTIR + Multi-master contention raw interrupt status + [5:5] + read-only + + + RXFIR + Receive FIFO full raw interrupt status + [4:4] + read-only + + + RXOIR + Receive FIFO overflow raw interrupt status + [3:3] + read-only + + + RXUIR + Receive FIFO underflow raw interrupt status + [2:2] + read-only + + + TXOIR + Transmit FIFO overflow raw interrupt status + [1:1] + read-only + + + TXEIR + Transmit FIFO empty raw interrupt status + [0:0] + read-only + + + + + TXOICR + 0x00000038 + TX FIFO overflow interrupt clear + 0x00000000 + + + TXOICR + Clear-on-read transmit FIFO overflow interrupt + [0:0] + read-only + + + + + RXOICR + 0x0000003c + RX FIFO overflow interrupt clear + 0x00000000 + + + RXOICR + Clear-on-read receive FIFO overflow interrupt + [0:0] + read-only + + + + + RXUICR + 0x00000040 + RX FIFO underflow interrupt clear + 0x00000000 + + + RXUICR + Clear-on-read receive FIFO underflow interrupt + [0:0] + read-only + + + + + MSTICR + 0x00000044 + Multi-master interrupt clear + 0x00000000 + + + MSTICR + Clear-on-read multi-master contention interrupt + [0:0] + read-only + + + + + ICR + 0x00000048 + Interrupt clear + 0x00000000 + + + ICR + Clear-on-read all active interrupts + [0:0] + read-only + + + + + DMACR + 0x0000004c + DMA control + 0x00000000 + + + TDMAE + Transmit DMA enable + [1:1] + read-write + + + RDMAE + Receive DMA enable + [0:0] + read-write + + + + + DMATDLR + 0x00000050 + DMA TX data level + 0x00000000 + + + DMATDL + Transmit data watermark level + [7:0] + read-write + + + + + DMARDLR + 0x00000054 + DMA RX data level + 0x00000000 + + + DMARDL + Receive data watermark level (DMARDLR+1) + [7:0] + read-write + + + + + IDR + 0x00000058 + Identification register + 0x51535049 + + + IDCODE + Peripheral dentification code + [31:0] + read-only + + + + + SSI_VERSION_ID + 0x0000005c + Version ID + 0x3430312a + + + SSI_COMP_VERSION + SNPS component version (format X.YY) + [31:0] + read-only + + + + + DR0 + 0x00000060 + Data Register 0 (of 36) + 0x00000000 + + + DR + First data register of 36 + [31:0] + read-write + + + + + RX_SAMPLE_DLY + 0x000000f0 + RX sample delay + 0x00000000 + + + RSD + RXD sample delay (in SCLK cycles) + [7:0] + read-write + + + + + SPI_CTRLR0 + 0x000000f4 + SPI control + 0x03000000 + + + XIP_CMD + SPI Command to send in XIP mode (INST_L = 8-bit) or to append to Address (INST_L = 0-bit) + [31:24] + read-write + + + SPI_RXDS_EN + Read data strobe enable + [18:18] + read-write + + + INST_DDR_EN + Instruction DDR transfer enable + [17:17] + read-write + + + SPI_DDR_EN + SPI DDR transfer enable + [16:16] + read-write + + + WAIT_CYCLES + Wait cycles between control frame transmit and data reception (in SCLK cycles) + [15:11] + read-write + + + INST_L + Instruction length (0/4/8/16b) + [9:8] + read-write + + + NONE + 0 + No instruction + + + 4B + 1 + 4-bit instruction + + + 8B + 2 + 8-bit instruction + + + 16B + 3 + 16-bit instruction + + + + + ADDR_L + Address length (0b-60b in 4b increments) + [5:2] + read-write + + + TRANS_TYPE + Address and instruction transfer format + [1:0] + read-write + + + 1C1A + 0 + Command and address both in standard SPI frame format + + + 1C2A + 1 + Command in standard SPI format, address in format specified by FRF + + + 2C2A + 2 + Command and address both in format specified by FRF (e.g. Dual-SPI) + + + + + + + TXD_DRIVE_EDGE + 0x000000f8 + TX drive edge + 0x00000000 + + + TDE + TXD drive edge + [7:0] + read-write + + + + + + + XIP_CTRL + QSPI flash execute-in-place block + 0x14000000 + + 0 + 32 + registers + + + XIP_IRQ + 6 + + + + CTRL + 0x00000000 + Cache control + 0x00000003 + + + POWER_DOWN + When 1, the cache memories are powered down. They retain state, + but can not be accessed. This reduces static power dissipation. + Writing 1 to this bit forces CTRL_EN to 0, i.e. the cache cannot + be enabled when powered down. + Cache-as-SRAM accesses will produce a bus error response when + the cache is powered down. + [3:3] + read-write + + + ERR_BADWRITE + When 1, writes to any alias other than 0x0 (caching, allocating) + will produce a bus fault. When 0, these writes are silently ignored. + In either case, writes to the 0x0 alias will deallocate on tag match, + as usual. + [1:1] + read-write + + + EN + When 1, enable the cache. When the cache is disabled, all XIP accesses + will go straight to the flash, without querying the cache. When enabled, + cacheable XIP accesses will query the cache, and the flash will + not be accessed if the tag matches and the valid bit is set. + + If the cache is enabled, cache-as-SRAM accesses have no effect on the + cache data RAM, and will produce a bus error response. + [0:0] + read-write + + + + + FLUSH + 0x00000004 + Cache Flush control + 0x00000000 + + + FLUSH + Write 1 to flush the cache. This clears the tag memory, but + the data memory retains its contents. (This means cache-as-SRAM + contents is not affected by flush or reset.) + Reading will hold the bus (stall the processor) until the flush + completes. Alternatively STAT can be polled until completion. + [0:0] + write-only + + + + + STAT + 0x00000008 + Cache Status + 0x00000002 + + + FIFO_FULL + When 1, indicates the XIP streaming FIFO is completely full. + The streaming FIFO is 2 entries deep, so the full and empty + flag allow its level to be ascertained. + [2:2] + read-only + + + FIFO_EMPTY + When 1, indicates the XIP streaming FIFO is completely empty. + [1:1] + read-only + + + FLUSH_READY + Reads as 0 while a cache flush is in progress, and 1 otherwise. + The cache is flushed whenever the XIP block is reset, and also + when requested via the FLUSH register. + [0:0] + read-only + + + + + CTR_HIT + 0x0000000c + Cache Hit counter + 0x00000000 + + + CTR_HIT + A 32 bit saturating counter that increments upon each cache hit, + i.e. when an XIP access is serviced directly from cached data. + Write any value to clear. + [31:0] + read-write + oneToClear + + + + + CTR_ACC + 0x00000010 + Cache Access counter + 0x00000000 + + + CTR_ACC + A 32 bit saturating counter that increments upon each XIP access, + whether the cache is hit or not. This includes noncacheable accesses. + Write any value to clear. + [31:0] + read-write + oneToClear + + + + + STREAM_ADDR + 0x00000014 + FIFO stream address + 0x00000000 + + + STREAM_ADDR + The address of the next word to be streamed from flash to the streaming FIFO. + Increments automatically after each flash access. + Write the initial access address here before starting a streaming read. + [31:2] + read-write + + + + + STREAM_CTR + 0x00000018 + FIFO stream control + 0x00000000 + + + STREAM_CTR + Write a nonzero value to start a streaming read. This will then + progress in the background, using flash idle cycles to transfer + a linear data block from flash to the streaming FIFO. + Decrements automatically (1 at a time) as the stream + progresses, and halts on reaching 0. + Write 0 to halt an in-progress stream, and discard any in-flight + read, so that a new stream can immediately be started (after + draining the FIFO and reinitialising STREAM_ADDR) + [21:0] + read-write + + + + + STREAM_FIFO + 0x0000001c + FIFO stream data + 0x00000000 + + + STREAM_FIFO + Streamed data is buffered here, for retrieval by the system DMA. + This FIFO can also be accessed via the XIP_AUX slave, to avoid exposing + the DMA to bus stalls caused by other XIP traffic. + [31:0] + read-only + modify + + + + + + + SYSCFG + Register block for various chip control signals + 0x40004000 + + 0 + 28 + registers + + + + PROC0_NMI_MASK + 0x00000000 + Processor core 0 NMI source mask + 0x00000000 + + + PROC0_NMI_MASK + Set a bit high to enable NMI from that IRQ + [31:0] + read-write + + + + + PROC1_NMI_MASK + 0x00000004 + Processor core 1 NMI source mask + 0x00000000 + + + PROC1_NMI_MASK + Set a bit high to enable NMI from that IRQ + [31:0] + read-write + + + + + PROC_CONFIG + 0x00000008 + Configuration for processors + 0x10000000 + + + PROC1_DAP_INSTID + Configure proc1 DAP instance ID. + Recommend that this is NOT changed until you require debug access in multi-chip environment + WARNING: do not set to 15 as this is reserved for RescueDP + [31:28] + read-write + + + PROC0_DAP_INSTID + Configure proc0 DAP instance ID. + Recommend that this is NOT changed until you require debug access in multi-chip environment + WARNING: do not set to 15 as this is reserved for RescueDP + [27:24] + read-write + + + PROC1_HALTED + Indication that proc1 has halted + [1:1] + read-only + + + PROC0_HALTED + Indication that proc0 has halted + [0:0] + read-only + + + + + PROC_IN_SYNC_BYPASS + 0x0000000c + For each bit, if 1, bypass the input synchronizer between that GPIO + and the GPIO input register in the SIO. The input synchronizers should + generally be unbypassed, to avoid injecting metastabilities into processors. + If you're feeling brave, you can bypass to save two cycles of input + latency. This register applies to GPIO 0...29. + 0x00000000 + + + PROC_IN_SYNC_BYPASS + [29:0] + read-write + + + + + PROC_IN_SYNC_BYPASS_HI + 0x00000010 + For each bit, if 1, bypass the input synchronizer between that GPIO + and the GPIO input register in the SIO. The input synchronizers should + generally be unbypassed, to avoid injecting metastabilities into processors. + If you're feeling brave, you can bypass to save two cycles of input + latency. This register applies to GPIO 30...35 (the QSPI IOs). + 0x00000000 + + + PROC_IN_SYNC_BYPASS_HI + [5:0] + read-write + + + + + DBGFORCE + 0x00000014 + Directly control the SWD debug port of either processor + 0x00000066 + + + PROC1_ATTACH + Attach processor 1 debug port to syscfg controls, and disconnect it from external SWD pads. + [7:7] + read-write + + + PROC1_SWCLK + Directly drive processor 1 SWCLK, if PROC1_ATTACH is set + [6:6] + read-write + + + PROC1_SWDI + Directly drive processor 1 SWDIO input, if PROC1_ATTACH is set + [5:5] + read-write + + + PROC1_SWDO + Observe the value of processor 1 SWDIO output. + [4:4] + read-only + + + PROC0_ATTACH + Attach processor 0 debug port to syscfg controls, and disconnect it from external SWD pads. + [3:3] + read-write + + + PROC0_SWCLK + Directly drive processor 0 SWCLK, if PROC0_ATTACH is set + [2:2] + read-write + + + PROC0_SWDI + Directly drive processor 0 SWDIO input, if PROC0_ATTACH is set + [1:1] + read-write + + + PROC0_SWDO + Observe the value of processor 0 SWDIO output. + [0:0] + read-only + + + + + MEMPOWERDOWN + 0x00000018 + Control power downs to memories. Set high to power down memories. + Use with extreme caution + 0x00000000 + + + ROM + [7:7] + read-write + + + USB + [6:6] + read-write + + + SRAM5 + [5:5] + read-write + + + SRAM4 + [4:4] + read-write + + + SRAM3 + [3:3] + read-write + + + SRAM2 + [2:2] + read-write + + + SRAM1 + [1:1] + read-write + + + SRAM0 + [0:0] + read-write + + + + + + + XOSC + Controls the crystal oscillator + 0x40024000 + + 0 + 32 + registers + + + + CTRL + 0x00000000 + Crystal Oscillator Control + 0x00000000 + + + ENABLE + On power-up this field is initialised to DISABLE and the chip runs from the ROSC. + If the chip has subsequently been programmed to run from the XOSC then DISABLE may lock-up the chip. If this is a concern then run the clk_ref from the ROSC and enable the clk_sys RESUS feature. + The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + [23:12] + read-write + + + DISABLE + 3358 + + + ENABLE + 4011 + + + + + FREQ_RANGE + Frequency range. An invalid setting will retain the previous value. The actual value being used can be read from STATUS_FREQ_RANGE. This resets to 0xAA0 and cannot be changed. + [11:0] + read-write + + + 1_15MHZ + 2720 + + + RESERVED_1 + 2721 + + + RESERVED_2 + 2722 + + + RESERVED_3 + 2723 + + + + + + + STATUS + 0x00000004 + Crystal Oscillator Status + 0x00000000 + + + STABLE + Oscillator is running and stable + [31:31] + read-only + + + BADWRITE + An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or DORMANT + [24:24] + read-write + oneToClear + + + ENABLED + Oscillator is enabled but not necessarily running and stable, resets to 0 + [12:12] + read-only + + + FREQ_RANGE + The current frequency range setting, always reads 0 + [1:0] + read-only + + + 1_15MHZ + 0 + + + RESERVED_1 + 1 + + + RESERVED_2 + 2 + + + RESERVED_3 + 3 + + + + + + + DORMANT + 0x00000008 + Crystal Oscillator pause control + 0x00000000 + + + DORMANT + This is used to save power by pausing the XOSC + On power-up this field is initialised to WAKE + An invalid write will also select WAKE + Warning: stop the PLLs before selecting dormant mode + Warning: setup the irq before selecting dormant mode + [31:0] + read-write + + + dormant + 1668246881 + + + WAKE + 2002873189 + + + + + + + STARTUP + 0x0000000c + Controls the startup delay + 0x00000000 + + + X4 + Multiplies the startup_delay by 4. This is of little value to the user given that the delay can be programmed directly. + [20:20] + read-write + + + DELAY + in multiples of 256*xtal_period. The reset value of 0xc4 corresponds to approx 50 000 cycles. + [13:0] + read-write + + + + + COUNT + 0x0000001c + A down counter running at the xosc frequency which counts to zero and stops. + To start the counter write a non-zero value. + Can be used for short software pauses when setting up time sensitive hardware. + 0x00000000 + + + COUNT + [7:0] + read-write + + + + + + + PLL_SYS + 0x40028000 + + 0 + 16 + registers + + + + CS + 0x00000000 + Control and Status + GENERAL CONSTRAINTS: + Reference clock frequency min=5MHz, max=800MHz + Feedback divider min=16, max=320 + VCO frequency min=750MHz, max=1600MHz + 0x00000001 + + + LOCK + PLL is locked + [31:31] + read-only + + + BYPASS + Passes the reference clock to the output instead of the divided VCO. The VCO continues to run so the user can switch between the reference clock and the divided VCO but the output will glitch when doing so. + [8:8] + read-write + + + REFDIV + Divides the PLL input reference clock. + Behaviour is undefined for div=0. + PLL output will be unpredictable during refdiv changes, wait for lock=1 before using it. + [5:0] + read-write + + + + + PWR + 0x00000004 + Controls the PLL power modes. + 0x0000002d + + + VCOPD + PLL VCO powerdown + To save power set high when PLL output not required or bypass=1. + [5:5] + read-write + + + POSTDIVPD + PLL post divider powerdown + To save power set high when PLL output not required or bypass=1. + [3:3] + read-write + + + DSMPD + PLL DSM powerdown + Nothing is achieved by setting this low. + [2:2] + read-write + + + PD + PLL powerdown + To save power set high when PLL output not required. + [0:0] + read-write + + + + + FBDIV_INT + 0x00000008 + Feedback divisor + (note: this PLL does not support fractional division) + 0x00000000 + + + FBDIV_INT + see ctrl reg description for constraints + [11:0] + read-write + + + + + PRIM + 0x0000000c + Controls the PLL post dividers for the primary output + (note: this PLL does not have a secondary output) + the primary output is driven from VCO divided by postdiv1*postdiv2 + 0x00077000 + + + POSTDIV1 + divide by 1-7 + [18:16] + read-write + + + POSTDIV2 + divide by 1-7 + [14:12] + read-write + + + + + + + PLL_USB + 0x4002c000 + + + UART0 + 0x40034000 + + 0 + 4096 + registers + + + UART0_IRQ + 20 + + + + UARTDR + 0x00000000 + Data Register, UARTDR + 0x00000000 + + + OE + Overrun error. This bit is set to 1 if data is received and the receive FIFO is already full. This is cleared to 0 once there is an empty space in the FIFO and a new character can be written to it. + [11:11] + read-only + + + BE + Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity and stop bits). In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state), and the next valid start bit is received. + [10:10] + read-only + + + PE + Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. In FIFO mode, this error is associated with the character at the top of the FIFO. + [9:9] + read-only + + + FE + Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is associated with the character at the top of the FIFO. + [8:8] + read-only + + + DATA + Receive (read) data character. Transmit (write) data character. + [7:0] + read-write + modify + + + + + UARTRSR + 0x00000004 + Receive Status Register/Error Clear Register, UARTRSR/UARTECR + 0x00000000 + + + OE + Overrun error. This bit is set to 1 if data is received and the FIFO is already full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain valid because no more data is written when the FIFO is full, only the contents of the shift register are overwritten. The CPU must now read the data, to empty the FIFO. + [3:3] + read-write + oneToClear + + + BE + Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity, and stop bits). This bit is cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state) and the next valid start bit is received. + [2:2] + read-write + oneToClear + + + PE + Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + [1:1] + read-write + oneToClear + + + FE + Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + [0:0] + read-write + oneToClear + + + + + UARTFR + 0x00000018 + Flag Register, UARTFR + 0x00000090 + + + RI + Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW. + [8:8] + read-only + + + TXFE + Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is set when the transmit holding register is empty. If the FIFO is enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if there is data in the transmit shift register. + [7:7] + read-only + + + RXFF + Receive FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is full. If the FIFO is enabled, the RXFF bit is set when the receive FIFO is full. + [6:6] + read-only + + + TXFF + Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set when the transmit FIFO is full. + [5:5] + read-only + + + RXFE + Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set when the receive FIFO is empty. + [4:4] + read-only + + + BUSY + UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit remains set until the complete byte, including all the stop bits, has been sent from the shift register. This bit is set as soon as the transmit FIFO becomes non-empty, regardless of whether the UART is enabled or not. + [3:3] + read-only + + + DCD + Data carrier detect. This bit is the complement of the UART data carrier detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. + [2:2] + read-only + + + DSR + Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW. + [1:1] + read-only + + + CTS + Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW. + [0:0] + read-only + + + + + UARTILPR + 0x00000020 + IrDA Low-Power Counter Register, UARTILPR + 0x00000000 + + + ILPDVSR + 8-bit low-power divisor value. These bits are cleared to 0 at reset. + [7:0] + read-write + + + + + UARTIBRD + 0x00000024 + Integer Baud Rate Register, UARTIBRD + 0x00000000 + + + BAUD_DIVINT + The integer baud rate divisor. These bits are cleared to 0 on reset. + [15:0] + read-write + + + + + UARTFBRD + 0x00000028 + Fractional Baud Rate Register, UARTFBRD + 0x00000000 + + + BAUD_DIVFRAC + The fractional baud rate divisor. These bits are cleared to 0 on reset. + [5:0] + read-write + + + + + UARTLCR_H + 0x0000002c + Line Control Register, UARTLCR_H + 0x00000000 + + + SPS + Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then the parity bit is transmitted and checked as a 0. This bit has no effect when the PEN bit disables parity checking and generation. + [7:7] + read-write + + + WLEN + Word length. These bits indicate the number of data bits transmitted or received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. + [6:5] + read-write + + + FEN + Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled (FIFO mode). + [4:4] + read-write + + + STP2 + Two stop bits select. If this bit is set to 1, two stop bits are transmitted at the end of the frame. The receive logic does not check for two stop bits being received. + [3:3] + read-write + + + EPS + Even parity select. Controls the type of parity the UART uses during transmission and reception: 0 = odd parity. The UART generates or checks for an odd number of 1s in the data and parity bits. 1 = even parity. The UART generates or checks for an even number of 1s in the data and parity bits. This bit has no effect when the PEN bit disables parity checking and generation. + [2:2] + read-write + + + PEN + Parity enable: 0 = parity is disabled and no parity bit added to the data frame 1 = parity checking and generation is enabled. + [1:1] + read-write + + + BRK + Send break. If this bit is set to 1, a low-level is continually output on the UARTTXD output, after completing transmission of the current character. For the proper execution of the break command, the software must set this bit for at least two complete frames. For normal use, this bit must be cleared to 0. + [0:0] + read-write + + + + + UARTCR + 0x00000030 + Control Register, UARTCR + 0x00000300 + + + CTSEN + CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow control is enabled. Data is only transmitted when the nUARTCTS signal is asserted. + [15:15] + read-write + + + RTSEN + RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow control is enabled. Data is only requested when there is space in the receive FIFO for it to be received. + [14:14] + read-write + + + OUT2 + This bit is the complement of the UART Out2 (nUARTOut2) modem status output. That is, when the bit is programmed to a 1, the output is 0. For DTE this can be used as Ring Indicator (RI). + [13:13] + read-write + + + OUT1 + This bit is the complement of the UART Out1 (nUARTOut1) modem status output. That is, when the bit is programmed to a 1 the output is 0. For DTE this can be used as Data Carrier Detect (DCD). + [12:12] + read-write + + + RTS + Request to send. This bit is the complement of the UART request to send, nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then nUARTRTS is LOW. + [11:11] + read-write + + + DTR + Data transmit ready. This bit is the complement of the UART data transmit ready, nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then nUARTDTR is LOW. + [10:10] + read-write + + + RXE + Receive enable. If this bit is set to 1, the receive section of the UART is enabled. Data reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of reception, it completes the current character before stopping. + [9:9] + read-write + + + TXE + Transmit enable. If this bit is set to 1, the transmit section of the UART is enabled. Data transmission occurs for either UART signals, or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of transmission, it completes the current character before stopping. + [8:8] + read-write + + + LBE + Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test register must be set to 1 to override the normal half-duplex SIR operation. This must be the requirement for accessing the test registers during normal operation, and SIRTEST must be cleared to 0 when loopback testing is finished. This feature reduces the amount of external coupling required during system test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path is fed through to the UARTRXD path. In either SIR mode or UART mode, when this bit is set, the modem outputs are also fed through to the modem inputs. This bit is cleared to 0 on reset, to disable loopback. + [7:7] + read-write + + + SIRLP + SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is cleared to 0, low-level bits are transmitted as an active high pulse with a width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are transmitted with a pulse width that is 3 times the period of the IrLPBaud16 input signal, regardless of the selected bit rate. Setting this bit uses less power, but might reduce transmission distances. + [2:2] + read-write + + + SIREN + SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD remains HIGH, in the marking state. Signal transitions on UARTRXD or modem status inputs have no effect. This bit has no effect if the UARTEN bit disables the UART. + [1:1] + read-write + + + UARTEN + UART enable: 0 = UART is disabled. If the UART is disabled in the middle of transmission or reception, it completes the current character before stopping. 1 = the UART is enabled. Data transmission and reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. + [0:0] + read-write + + + + + UARTIFLS + 0x00000034 + Interrupt FIFO Level Select Register, UARTIFLS + 0x00000012 + + + RXIFLSEL + Receive interrupt FIFO level select. The trigger points for the receive interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 full b101-b111 = reserved. + [5:3] + read-write + + + TXIFLSEL + Transmit interrupt FIFO level select. The trigger points for the transmit interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 full b101-b111 = reserved. + [2:0] + read-write + + + + + UARTIMSC + 0x00000038 + Interrupt Mask Set/Clear Register, UARTIMSC + 0x00000000 + + + OEIM + Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write of 0 clears the mask. + [10:10] + read-write + + + BEIM + Break error interrupt mask. A read returns the current mask for the UARTBEINTR interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write of 0 clears the mask. + [9:9] + read-write + + + PEIM + Parity error interrupt mask. A read returns the current mask for the UARTPEINTR interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write of 0 clears the mask. + [8:8] + read-write + + + FEIM + Framing error interrupt mask. A read returns the current mask for the UARTFEINTR interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write of 0 clears the mask. + [7:7] + read-write + + + RTIM + Receive timeout interrupt mask. A read returns the current mask for the UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is set. A write of 0 clears the mask. + [6:6] + read-write + + + TXIM + Transmit interrupt mask. A read returns the current mask for the UARTTXINTR interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write of 0 clears the mask. + [5:5] + read-write + + + RXIM + Receive interrupt mask. A read returns the current mask for the UARTRXINTR interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write of 0 clears the mask. + [4:4] + read-write + + + DSRMIM + nUARTDSR modem interrupt mask. A read returns the current mask for the UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is set. A write of 0 clears the mask. + [3:3] + read-write + + + DCDMIM + nUARTDCD modem interrupt mask. A read returns the current mask for the UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is set. A write of 0 clears the mask. + [2:2] + read-write + + + CTSMIM + nUARTCTS modem interrupt mask. A read returns the current mask for the UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is set. A write of 0 clears the mask. + [1:1] + read-write + + + RIMIM + nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write of 0 clears the mask. + [0:0] + read-write + + + + + UARTRIS + 0x0000003c + Raw Interrupt Status Register, UARTRIS + 0x00000000 + + + OERIS + Overrun error interrupt status. Returns the raw interrupt state of the UARTOEINTR interrupt. + [10:10] + read-only + + + BERIS + Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR interrupt. + [9:9] + read-only + + + PERIS + Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR interrupt. + [8:8] + read-only + + + FERIS + Framing error interrupt status. Returns the raw interrupt state of the UARTFEINTR interrupt. + [7:7] + read-only + + + RTRIS + Receive timeout interrupt status. Returns the raw interrupt state of the UARTRTINTR interrupt. a + [6:6] + read-only + + + TXRIS + Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR interrupt. + [5:5] + read-only + + + RXRIS + Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR interrupt. + [4:4] + read-only + + + DSRRMIS + nUARTDSR modem interrupt status. Returns the raw interrupt state of the UARTDSRINTR interrupt. + [3:3] + read-only + + + DCDRMIS + nUARTDCD modem interrupt status. Returns the raw interrupt state of the UARTDCDINTR interrupt. + [2:2] + read-only + + + CTSRMIS + nUARTCTS modem interrupt status. Returns the raw interrupt state of the UARTCTSINTR interrupt. + [1:1] + read-only + + + RIRMIS + nUARTRI modem interrupt status. Returns the raw interrupt state of the UARTRIINTR interrupt. + [0:0] + read-only + + + + + UARTMIS + 0x00000040 + Masked Interrupt Status Register, UARTMIS + 0x00000000 + + + OEMIS + Overrun error masked interrupt status. Returns the masked interrupt state of the UARTOEINTR interrupt. + [10:10] + read-only + + + BEMIS + Break error masked interrupt status. Returns the masked interrupt state of the UARTBEINTR interrupt. + [9:9] + read-only + + + PEMIS + Parity error masked interrupt status. Returns the masked interrupt state of the UARTPEINTR interrupt. + [8:8] + read-only + + + FEMIS + Framing error masked interrupt status. Returns the masked interrupt state of the UARTFEINTR interrupt. + [7:7] + read-only + + + RTMIS + Receive timeout masked interrupt status. Returns the masked interrupt state of the UARTRTINTR interrupt. + [6:6] + read-only + + + TXMIS + Transmit masked interrupt status. Returns the masked interrupt state of the UARTTXINTR interrupt. + [5:5] + read-only + + + RXMIS + Receive masked interrupt status. Returns the masked interrupt state of the UARTRXINTR interrupt. + [4:4] + read-only + + + DSRMMIS + nUARTDSR modem masked interrupt status. Returns the masked interrupt state of the UARTDSRINTR interrupt. + [3:3] + read-only + + + DCDMMIS + nUARTDCD modem masked interrupt status. Returns the masked interrupt state of the UARTDCDINTR interrupt. + [2:2] + read-only + + + CTSMMIS + nUARTCTS modem masked interrupt status. Returns the masked interrupt state of the UARTCTSINTR interrupt. + [1:1] + read-only + + + RIMMIS + nUARTRI modem masked interrupt status. Returns the masked interrupt state of the UARTRIINTR interrupt. + [0:0] + read-only + + + + + UARTICR + 0x00000044 + Interrupt Clear Register, UARTICR + 0x00000000 + + + OEIC + Overrun error interrupt clear. Clears the UARTOEINTR interrupt. + [10:10] + read-write + oneToClear + + + BEIC + Break error interrupt clear. Clears the UARTBEINTR interrupt. + [9:9] + read-write + oneToClear + + + PEIC + Parity error interrupt clear. Clears the UARTPEINTR interrupt. + [8:8] + read-write + oneToClear + + + FEIC + Framing error interrupt clear. Clears the UARTFEINTR interrupt. + [7:7] + read-write + oneToClear + + + RTIC + Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. + [6:6] + read-write + oneToClear + + + TXIC + Transmit interrupt clear. Clears the UARTTXINTR interrupt. + [5:5] + read-write + oneToClear + + + RXIC + Receive interrupt clear. Clears the UARTRXINTR interrupt. + [4:4] + read-write + oneToClear + + + DSRMIC + nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt. + [3:3] + read-write + oneToClear + + + DCDMIC + nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt. + [2:2] + read-write + oneToClear + + + CTSMIC + nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt. + [1:1] + read-write + oneToClear + + + RIMIC + nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. + [0:0] + read-write + oneToClear + + + + + UARTDMACR + 0x00000048 + DMA Control Register, UARTDMACR + 0x00000000 + + + DMAONERR + DMA on error. If this bit is set to 1, the DMA receive request outputs, UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is asserted. + [2:2] + read-write + + + TXDMAE + Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + [1:1] + read-write + + + RXDMAE + Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is enabled. + [0:0] + read-write + + + + + UARTPERIPHID0 + 0x00000fe0 + UARTPeriphID0 Register + 0x00000011 + + + PARTNUMBER0 + These bits read back as 0x11 + [7:0] + read-only + + + + + UARTPERIPHID1 + 0x00000fe4 + UARTPeriphID1 Register + 0x00000010 + + + DESIGNER0 + These bits read back as 0x1 + [7:4] + read-only + + + PARTNUMBER1 + These bits read back as 0x0 + [3:0] + read-only + + + + + UARTPERIPHID2 + 0x00000fe8 + UARTPeriphID2 Register + 0x00000034 + + + REVISION + This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 0x2 r1p5 0x3 + [7:4] + read-only + + + DESIGNER1 + These bits read back as 0x4 + [3:0] + read-only + + + + + UARTPERIPHID3 + 0x00000fec + UARTPeriphID3 Register + 0x00000000 + + + CONFIGURATION + These bits read back as 0x00 + [7:0] + read-only + + + + + UARTPCELLID0 + 0x00000ff0 + UARTPCellID0 Register + 0x0000000d + + + UARTPCELLID0 + These bits read back as 0x0D + [7:0] + read-only + + + + + UARTPCELLID1 + 0x00000ff4 + UARTPCellID1 Register + 0x000000f0 + + + UARTPCELLID1 + These bits read back as 0xF0 + [7:0] + read-only + + + + + UARTPCELLID2 + 0x00000ff8 + UARTPCellID2 Register + 0x00000005 + + + UARTPCELLID2 + These bits read back as 0x05 + [7:0] + read-only + + + + + UARTPCELLID3 + 0x00000ffc + UARTPCellID3 Register + 0x000000b1 + + + UARTPCELLID3 + These bits read back as 0xB1 + [7:0] + read-only + + + + + + + UART1 + 0x40038000 + + UART1_IRQ + 21 + + + + ROSC + 0x40060000 + + 0 + 36 + registers + + + + CTRL + 0x00000000 + Ring Oscillator control + 0x00000aa0 + + + ENABLE + On power-up this field is initialised to ENABLE + The system clock must be switched to another source before setting this field to DISABLE otherwise the chip will lock up + The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + [23:12] + read-write + + + DISABLE + 3358 + + + ENABLE + 4011 + + + + + FREQ_RANGE + Controls the number of delay stages in the ROSC ring + LOW uses stages 0 to 7 + MEDIUM uses stages 2 to 7 + HIGH uses stages 4 to 7 + TOOHIGH uses stages 6 to 7 and should not be used because its frequency exceeds design specifications + The clock output will not glitch when changing the range up one step at a time + The clock output will glitch when changing the range down + Note: the values here are gray coded which is why HIGH comes before TOOHIGH + [11:0] + read-write + + + LOW + 4004 + + + MEDIUM + 4005 + + + HIGH + 4007 + + + TOOHIGH + 4006 + + + + + + + FREQA + 0x00000004 + The FREQA & FREQB registers control the frequency by controlling the drive strength of each stage + The drive strength has 4 levels determined by the number of bits set + Increasing the number of bits set increases the drive strength and increases the oscillation frequency + 0 bits set is the default drive strength + 1 bit set doubles the drive strength + 2 bits set triples drive strength + 3 bits set quadruples drive strength + 0x00000000 + + + PASSWD + Set to 0x9696 to apply the settings + Any other value in this field will set all drive strengths to 0 + [31:16] + read-write + + + PASS + 38550 + + + + + DS3 + Stage 3 drive strength + [14:12] + read-write + + + DS2 + Stage 2 drive strength + [10:8] + read-write + + + DS1 + Stage 1 drive strength + [6:4] + read-write + + + DS0 + Stage 0 drive strength + [2:0] + read-write + + + + + FREQB + 0x00000008 + For a detailed description see freqa register + 0x00000000 + + + PASSWD + Set to 0x9696 to apply the settings + Any other value in this field will set all drive strengths to 0 + [31:16] + read-write + + + PASS + 38550 + + + + + DS7 + Stage 7 drive strength + [14:12] + read-write + + + DS6 + Stage 6 drive strength + [10:8] + read-write + + + DS5 + Stage 5 drive strength + [6:4] + read-write + + + DS4 + Stage 4 drive strength + [2:0] + read-write + + + + + DORMANT + 0x0000000c + Ring Oscillator pause control + 0x00000000 + + + DORMANT + This is used to save power by pausing the ROSC + On power-up this field is initialised to WAKE + An invalid write will also select WAKE + Warning: setup the irq before selecting dormant mode + [31:0] + read-write + + + dormant + 1668246881 + + + WAKE + 2002873189 + + + + + + + DIV + 0x00000010 + Controls the output divider + 0x00000000 + + + DIV + set to 0xaa0 + div where + div = 0 divides by 32 + div = 1-31 divides by div + any other value sets div=31 + this register resets to div=16 + [11:0] + read-write + + + PASS + 2720 + + + + + + + PHASE + 0x00000014 + Controls the phase shifted output + 0x00000008 + + + PASSWD + set to 0xaa + any other value enables the output with shift=0 + [11:4] + read-write + + + ENABLE + enable the phase-shifted output + this can be changed on-the-fly + [3:3] + read-write + + + FLIP + invert the phase-shifted output + this is ignored when div=1 + [2:2] + read-write + + + SHIFT + phase shift the phase-shifted output by SHIFT input clocks + this can be changed on-the-fly + must be set to 0 before setting div=1 + [1:0] + read-write + + + + + STATUS + 0x00000018 + Ring Oscillator Status + 0x00000000 + + + STABLE + Oscillator is running and stable + [31:31] + read-only + + + BADWRITE + An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or FREQA or FREQB or DIV or PHASE or DORMANT + [24:24] + read-write + oneToClear + + + DIV_RUNNING + post-divider is running + this resets to 0 but transitions to 1 during chip startup + [16:16] + read-only + + + ENABLED + Oscillator is enabled but not necessarily running and stable + this resets to 0 but transitions to 1 during chip startup + [12:12] + read-only + + + + + RANDOMBIT + 0x0000001c + This just reads the state of the oscillator output so randomness is compromised if the ring oscillator is stopped or run at a harmonic of the bus frequency + 0x00000001 + + + RANDOMBIT + [0:0] + read-only + + + + + COUNT + 0x00000020 + A down counter running at the ROSC frequency which counts to zero and stops. + To start the counter write a non-zero value. + Can be used for short software pauses when setting up time sensitive hardware. + 0x00000000 + + + COUNT + [7:0] + read-write + + + + + + + WATCHDOG + 0x40058000 + + 0 + 48 + registers + + + + CTRL + 0x00000000 + Watchdog control + The rst_wdsel register determines which subsystems are reset when the watchdog is triggered. + The watchdog can be triggered in software. + 0x07000000 + + + TRIGGER + Trigger a watchdog reset + [31:31] + write-only + + + ENABLE + When not enabled the watchdog timer is paused + [30:30] + read-write + + + PAUSE_DBG1 + Pause the watchdog timer when processor 1 is in debug mode + [26:26] + read-write + + + PAUSE_DBG0 + Pause the watchdog timer when processor 0 is in debug mode + [25:25] + read-write + + + PAUSE_JTAG + Pause the watchdog timer when JTAG is accessing the bus fabric + [24:24] + read-write + + + TIME + Indicates the number of ticks / 2 (see errata RP2040-E1) before a watchdog reset will be triggered + [23:0] + read-only + + + + + LOAD + 0x00000004 + Load the watchdog timer. The maximum setting is 0xffffff which corresponds to 0xffffff / 2 ticks before triggering a watchdog reset (see errata RP2040-E1). + 0x00000000 + + + LOAD + [23:0] + write-only + + + + + REASON + 0x00000008 + Logs the reason for the last reset. Both bits are zero for the case of a hardware reset. + 0x00000000 + + + FORCE + [1:1] + read-only + + + TIMER + [0:0] + read-only + + + + + SCRATCH0 + 0x0000000c + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH0 + [31:0] + read-write + + + + + SCRATCH1 + 0x00000010 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH1 + [31:0] + read-write + + + + + SCRATCH2 + 0x00000014 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH2 + [31:0] + read-write + + + + + SCRATCH3 + 0x00000018 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH3 + [31:0] + read-write + + + + + SCRATCH4 + 0x0000001c + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH4 + [31:0] + read-write + + + + + SCRATCH5 + 0x00000020 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH5 + [31:0] + read-write + + + + + SCRATCH6 + 0x00000024 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH6 + [31:0] + read-write + + + + + SCRATCH7 + 0x00000028 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH7 + [31:0] + read-write + + + + + TICK + 0x0000002c + Controls the tick generator + 0x00000200 + + + COUNT + Count down timer: the remaining number clk_tick cycles before the next tick is generated. + [19:11] + read-only + + + RUNNING + Is the tick generator running? + [10:10] + read-only + + + ENABLE + start / stop tick generation + [9:9] + read-write + + + CYCLES + Total number of clk_tick cycles before the next tick. + [8:0] + read-write + + + + + + + DMA + DMA with separate read and write masters + 0x50000000 + + 0 + 2760 + registers + + + DMA_IRQ_0 + 11 + + + DMA_IRQ_1 + 12 + + + + CH0_READ_ADDR + 0x00000000 + DMA Channel 0 Read Address pointer + 0x00000000 + + + CH0_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH0_WRITE_ADDR + 0x00000004 + DMA Channel 0 Write Address pointer + 0x00000000 + + + CH0_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH0_TRANS_COUNT + 0x00000008 + DMA Channel 0 Transfer Count + 0x00000000 + + + CH0_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH0_CTRL_TRIG + 0x0000000c + DMA Channel 0 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH0_AL1_CTRL + 0x00000010 + Alias for channel 0 CTRL register + 0x00000000 + + + CH0_AL1_CTRL + [31:0] + read-write + + + + + CH0_AL1_READ_ADDR + 0x00000014 + Alias for channel 0 READ_ADDR register + 0x00000000 + + + CH0_AL1_READ_ADDR + [31:0] + read-write + + + + + CH0_AL1_WRITE_ADDR + 0x00000018 + Alias for channel 0 WRITE_ADDR register + 0x00000000 + + + CH0_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH0_AL1_TRANS_COUNT_TRIG + 0x0000001c + Alias for channel 0 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH0_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH0_AL2_CTRL + 0x00000020 + Alias for channel 0 CTRL register + 0x00000000 + + + CH0_AL2_CTRL + [31:0] + read-write + + + + + CH0_AL2_TRANS_COUNT + 0x00000024 + Alias for channel 0 TRANS_COUNT register + 0x00000000 + + + CH0_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH0_AL2_READ_ADDR + 0x00000028 + Alias for channel 0 READ_ADDR register + 0x00000000 + + + CH0_AL2_READ_ADDR + [31:0] + read-write + + + + + CH0_AL2_WRITE_ADDR_TRIG + 0x0000002c + Alias for channel 0 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH0_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH0_AL3_CTRL + 0x00000030 + Alias for channel 0 CTRL register + 0x00000000 + + + CH0_AL3_CTRL + [31:0] + read-write + + + + + CH0_AL3_WRITE_ADDR + 0x00000034 + Alias for channel 0 WRITE_ADDR register + 0x00000000 + + + CH0_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH0_AL3_TRANS_COUNT + 0x00000038 + Alias for channel 0 TRANS_COUNT register + 0x00000000 + + + CH0_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH0_AL3_READ_ADDR_TRIG + 0x0000003c + Alias for channel 0 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH0_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH1_READ_ADDR + 0x00000040 + DMA Channel 1 Read Address pointer + 0x00000000 + + + CH1_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH1_WRITE_ADDR + 0x00000044 + DMA Channel 1 Write Address pointer + 0x00000000 + + + CH1_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH1_TRANS_COUNT + 0x00000048 + DMA Channel 1 Transfer Count + 0x00000000 + + + CH1_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH1_CTRL_TRIG + 0x0000004c + DMA Channel 1 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH1_AL1_CTRL + 0x00000050 + Alias for channel 1 CTRL register + 0x00000000 + + + CH1_AL1_CTRL + [31:0] + read-write + + + + + CH1_AL1_READ_ADDR + 0x00000054 + Alias for channel 1 READ_ADDR register + 0x00000000 + + + CH1_AL1_READ_ADDR + [31:0] + read-write + + + + + CH1_AL1_WRITE_ADDR + 0x00000058 + Alias for channel 1 WRITE_ADDR register + 0x00000000 + + + CH1_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH1_AL1_TRANS_COUNT_TRIG + 0x0000005c + Alias for channel 1 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH1_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH1_AL2_CTRL + 0x00000060 + Alias for channel 1 CTRL register + 0x00000000 + + + CH1_AL2_CTRL + [31:0] + read-write + + + + + CH1_AL2_TRANS_COUNT + 0x00000064 + Alias for channel 1 TRANS_COUNT register + 0x00000000 + + + CH1_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH1_AL2_READ_ADDR + 0x00000068 + Alias for channel 1 READ_ADDR register + 0x00000000 + + + CH1_AL2_READ_ADDR + [31:0] + read-write + + + + + CH1_AL2_WRITE_ADDR_TRIG + 0x0000006c + Alias for channel 1 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH1_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH1_AL3_CTRL + 0x00000070 + Alias for channel 1 CTRL register + 0x00000000 + + + CH1_AL3_CTRL + [31:0] + read-write + + + + + CH1_AL3_WRITE_ADDR + 0x00000074 + Alias for channel 1 WRITE_ADDR register + 0x00000000 + + + CH1_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH1_AL3_TRANS_COUNT + 0x00000078 + Alias for channel 1 TRANS_COUNT register + 0x00000000 + + + CH1_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH1_AL3_READ_ADDR_TRIG + 0x0000007c + Alias for channel 1 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH1_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH2_READ_ADDR + 0x00000080 + DMA Channel 2 Read Address pointer + 0x00000000 + + + CH2_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH2_WRITE_ADDR + 0x00000084 + DMA Channel 2 Write Address pointer + 0x00000000 + + + CH2_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH2_TRANS_COUNT + 0x00000088 + DMA Channel 2 Transfer Count + 0x00000000 + + + CH2_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH2_CTRL_TRIG + 0x0000008c + DMA Channel 2 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH2_AL1_CTRL + 0x00000090 + Alias for channel 2 CTRL register + 0x00000000 + + + CH2_AL1_CTRL + [31:0] + read-write + + + + + CH2_AL1_READ_ADDR + 0x00000094 + Alias for channel 2 READ_ADDR register + 0x00000000 + + + CH2_AL1_READ_ADDR + [31:0] + read-write + + + + + CH2_AL1_WRITE_ADDR + 0x00000098 + Alias for channel 2 WRITE_ADDR register + 0x00000000 + + + CH2_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH2_AL1_TRANS_COUNT_TRIG + 0x0000009c + Alias for channel 2 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH2_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH2_AL2_CTRL + 0x000000a0 + Alias for channel 2 CTRL register + 0x00000000 + + + CH2_AL2_CTRL + [31:0] + read-write + + + + + CH2_AL2_TRANS_COUNT + 0x000000a4 + Alias for channel 2 TRANS_COUNT register + 0x00000000 + + + CH2_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH2_AL2_READ_ADDR + 0x000000a8 + Alias for channel 2 READ_ADDR register + 0x00000000 + + + CH2_AL2_READ_ADDR + [31:0] + read-write + + + + + CH2_AL2_WRITE_ADDR_TRIG + 0x000000ac + Alias for channel 2 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH2_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH2_AL3_CTRL + 0x000000b0 + Alias for channel 2 CTRL register + 0x00000000 + + + CH2_AL3_CTRL + [31:0] + read-write + + + + + CH2_AL3_WRITE_ADDR + 0x000000b4 + Alias for channel 2 WRITE_ADDR register + 0x00000000 + + + CH2_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH2_AL3_TRANS_COUNT + 0x000000b8 + Alias for channel 2 TRANS_COUNT register + 0x00000000 + + + CH2_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH2_AL3_READ_ADDR_TRIG + 0x000000bc + Alias for channel 2 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH2_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH3_READ_ADDR + 0x000000c0 + DMA Channel 3 Read Address pointer + 0x00000000 + + + CH3_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH3_WRITE_ADDR + 0x000000c4 + DMA Channel 3 Write Address pointer + 0x00000000 + + + CH3_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH3_TRANS_COUNT + 0x000000c8 + DMA Channel 3 Transfer Count + 0x00000000 + + + CH3_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH3_CTRL_TRIG + 0x000000cc + DMA Channel 3 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH3_AL1_CTRL + 0x000000d0 + Alias for channel 3 CTRL register + 0x00000000 + + + CH3_AL1_CTRL + [31:0] + read-write + + + + + CH3_AL1_READ_ADDR + 0x000000d4 + Alias for channel 3 READ_ADDR register + 0x00000000 + + + CH3_AL1_READ_ADDR + [31:0] + read-write + + + + + CH3_AL1_WRITE_ADDR + 0x000000d8 + Alias for channel 3 WRITE_ADDR register + 0x00000000 + + + CH3_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH3_AL1_TRANS_COUNT_TRIG + 0x000000dc + Alias for channel 3 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH3_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH3_AL2_CTRL + 0x000000e0 + Alias for channel 3 CTRL register + 0x00000000 + + + CH3_AL2_CTRL + [31:0] + read-write + + + + + CH3_AL2_TRANS_COUNT + 0x000000e4 + Alias for channel 3 TRANS_COUNT register + 0x00000000 + + + CH3_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH3_AL2_READ_ADDR + 0x000000e8 + Alias for channel 3 READ_ADDR register + 0x00000000 + + + CH3_AL2_READ_ADDR + [31:0] + read-write + + + + + CH3_AL2_WRITE_ADDR_TRIG + 0x000000ec + Alias for channel 3 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH3_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH3_AL3_CTRL + 0x000000f0 + Alias for channel 3 CTRL register + 0x00000000 + + + CH3_AL3_CTRL + [31:0] + read-write + + + + + CH3_AL3_WRITE_ADDR + 0x000000f4 + Alias for channel 3 WRITE_ADDR register + 0x00000000 + + + CH3_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH3_AL3_TRANS_COUNT + 0x000000f8 + Alias for channel 3 TRANS_COUNT register + 0x00000000 + + + CH3_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH3_AL3_READ_ADDR_TRIG + 0x000000fc + Alias for channel 3 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH3_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH4_READ_ADDR + 0x00000100 + DMA Channel 4 Read Address pointer + 0x00000000 + + + CH4_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH4_WRITE_ADDR + 0x00000104 + DMA Channel 4 Write Address pointer + 0x00000000 + + + CH4_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH4_TRANS_COUNT + 0x00000108 + DMA Channel 4 Transfer Count + 0x00000000 + + + CH4_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH4_CTRL_TRIG + 0x0000010c + DMA Channel 4 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH4_AL1_CTRL + 0x00000110 + Alias for channel 4 CTRL register + 0x00000000 + + + CH4_AL1_CTRL + [31:0] + read-write + + + + + CH4_AL1_READ_ADDR + 0x00000114 + Alias for channel 4 READ_ADDR register + 0x00000000 + + + CH4_AL1_READ_ADDR + [31:0] + read-write + + + + + CH4_AL1_WRITE_ADDR + 0x00000118 + Alias for channel 4 WRITE_ADDR register + 0x00000000 + + + CH4_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH4_AL1_TRANS_COUNT_TRIG + 0x0000011c + Alias for channel 4 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH4_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH4_AL2_CTRL + 0x00000120 + Alias for channel 4 CTRL register + 0x00000000 + + + CH4_AL2_CTRL + [31:0] + read-write + + + + + CH4_AL2_TRANS_COUNT + 0x00000124 + Alias for channel 4 TRANS_COUNT register + 0x00000000 + + + CH4_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH4_AL2_READ_ADDR + 0x00000128 + Alias for channel 4 READ_ADDR register + 0x00000000 + + + CH4_AL2_READ_ADDR + [31:0] + read-write + + + + + CH4_AL2_WRITE_ADDR_TRIG + 0x0000012c + Alias for channel 4 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH4_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH4_AL3_CTRL + 0x00000130 + Alias for channel 4 CTRL register + 0x00000000 + + + CH4_AL3_CTRL + [31:0] + read-write + + + + + CH4_AL3_WRITE_ADDR + 0x00000134 + Alias for channel 4 WRITE_ADDR register + 0x00000000 + + + CH4_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH4_AL3_TRANS_COUNT + 0x00000138 + Alias for channel 4 TRANS_COUNT register + 0x00000000 + + + CH4_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH4_AL3_READ_ADDR_TRIG + 0x0000013c + Alias for channel 4 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH4_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH5_READ_ADDR + 0x00000140 + DMA Channel 5 Read Address pointer + 0x00000000 + + + CH5_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH5_WRITE_ADDR + 0x00000144 + DMA Channel 5 Write Address pointer + 0x00000000 + + + CH5_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH5_TRANS_COUNT + 0x00000148 + DMA Channel 5 Transfer Count + 0x00000000 + + + CH5_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH5_CTRL_TRIG + 0x0000014c + DMA Channel 5 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH5_AL1_CTRL + 0x00000150 + Alias for channel 5 CTRL register + 0x00000000 + + + CH5_AL1_CTRL + [31:0] + read-write + + + + + CH5_AL1_READ_ADDR + 0x00000154 + Alias for channel 5 READ_ADDR register + 0x00000000 + + + CH5_AL1_READ_ADDR + [31:0] + read-write + + + + + CH5_AL1_WRITE_ADDR + 0x00000158 + Alias for channel 5 WRITE_ADDR register + 0x00000000 + + + CH5_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH5_AL1_TRANS_COUNT_TRIG + 0x0000015c + Alias for channel 5 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH5_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH5_AL2_CTRL + 0x00000160 + Alias for channel 5 CTRL register + 0x00000000 + + + CH5_AL2_CTRL + [31:0] + read-write + + + + + CH5_AL2_TRANS_COUNT + 0x00000164 + Alias for channel 5 TRANS_COUNT register + 0x00000000 + + + CH5_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH5_AL2_READ_ADDR + 0x00000168 + Alias for channel 5 READ_ADDR register + 0x00000000 + + + CH5_AL2_READ_ADDR + [31:0] + read-write + + + + + CH5_AL2_WRITE_ADDR_TRIG + 0x0000016c + Alias for channel 5 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH5_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH5_AL3_CTRL + 0x00000170 + Alias for channel 5 CTRL register + 0x00000000 + + + CH5_AL3_CTRL + [31:0] + read-write + + + + + CH5_AL3_WRITE_ADDR + 0x00000174 + Alias for channel 5 WRITE_ADDR register + 0x00000000 + + + CH5_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH5_AL3_TRANS_COUNT + 0x00000178 + Alias for channel 5 TRANS_COUNT register + 0x00000000 + + + CH5_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH5_AL3_READ_ADDR_TRIG + 0x0000017c + Alias for channel 5 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH5_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH6_READ_ADDR + 0x00000180 + DMA Channel 6 Read Address pointer + 0x00000000 + + + CH6_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH6_WRITE_ADDR + 0x00000184 + DMA Channel 6 Write Address pointer + 0x00000000 + + + CH6_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH6_TRANS_COUNT + 0x00000188 + DMA Channel 6 Transfer Count + 0x00000000 + + + CH6_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH6_CTRL_TRIG + 0x0000018c + DMA Channel 6 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH6_AL1_CTRL + 0x00000190 + Alias for channel 6 CTRL register + 0x00000000 + + + CH6_AL1_CTRL + [31:0] + read-write + + + + + CH6_AL1_READ_ADDR + 0x00000194 + Alias for channel 6 READ_ADDR register + 0x00000000 + + + CH6_AL1_READ_ADDR + [31:0] + read-write + + + + + CH6_AL1_WRITE_ADDR + 0x00000198 + Alias for channel 6 WRITE_ADDR register + 0x00000000 + + + CH6_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH6_AL1_TRANS_COUNT_TRIG + 0x0000019c + Alias for channel 6 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH6_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH6_AL2_CTRL + 0x000001a0 + Alias for channel 6 CTRL register + 0x00000000 + + + CH6_AL2_CTRL + [31:0] + read-write + + + + + CH6_AL2_TRANS_COUNT + 0x000001a4 + Alias for channel 6 TRANS_COUNT register + 0x00000000 + + + CH6_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH6_AL2_READ_ADDR + 0x000001a8 + Alias for channel 6 READ_ADDR register + 0x00000000 + + + CH6_AL2_READ_ADDR + [31:0] + read-write + + + + + CH6_AL2_WRITE_ADDR_TRIG + 0x000001ac + Alias for channel 6 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH6_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH6_AL3_CTRL + 0x000001b0 + Alias for channel 6 CTRL register + 0x00000000 + + + CH6_AL3_CTRL + [31:0] + read-write + + + + + CH6_AL3_WRITE_ADDR + 0x000001b4 + Alias for channel 6 WRITE_ADDR register + 0x00000000 + + + CH6_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH6_AL3_TRANS_COUNT + 0x000001b8 + Alias for channel 6 TRANS_COUNT register + 0x00000000 + + + CH6_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH6_AL3_READ_ADDR_TRIG + 0x000001bc + Alias for channel 6 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH6_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH7_READ_ADDR + 0x000001c0 + DMA Channel 7 Read Address pointer + 0x00000000 + + + CH7_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH7_WRITE_ADDR + 0x000001c4 + DMA Channel 7 Write Address pointer + 0x00000000 + + + CH7_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH7_TRANS_COUNT + 0x000001c8 + DMA Channel 7 Transfer Count + 0x00000000 + + + CH7_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH7_CTRL_TRIG + 0x000001cc + DMA Channel 7 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH7_AL1_CTRL + 0x000001d0 + Alias for channel 7 CTRL register + 0x00000000 + + + CH7_AL1_CTRL + [31:0] + read-write + + + + + CH7_AL1_READ_ADDR + 0x000001d4 + Alias for channel 7 READ_ADDR register + 0x00000000 + + + CH7_AL1_READ_ADDR + [31:0] + read-write + + + + + CH7_AL1_WRITE_ADDR + 0x000001d8 + Alias for channel 7 WRITE_ADDR register + 0x00000000 + + + CH7_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH7_AL1_TRANS_COUNT_TRIG + 0x000001dc + Alias for channel 7 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH7_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH7_AL2_CTRL + 0x000001e0 + Alias for channel 7 CTRL register + 0x00000000 + + + CH7_AL2_CTRL + [31:0] + read-write + + + + + CH7_AL2_TRANS_COUNT + 0x000001e4 + Alias for channel 7 TRANS_COUNT register + 0x00000000 + + + CH7_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH7_AL2_READ_ADDR + 0x000001e8 + Alias for channel 7 READ_ADDR register + 0x00000000 + + + CH7_AL2_READ_ADDR + [31:0] + read-write + + + + + CH7_AL2_WRITE_ADDR_TRIG + 0x000001ec + Alias for channel 7 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH7_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH7_AL3_CTRL + 0x000001f0 + Alias for channel 7 CTRL register + 0x00000000 + + + CH7_AL3_CTRL + [31:0] + read-write + + + + + CH7_AL3_WRITE_ADDR + 0x000001f4 + Alias for channel 7 WRITE_ADDR register + 0x00000000 + + + CH7_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH7_AL3_TRANS_COUNT + 0x000001f8 + Alias for channel 7 TRANS_COUNT register + 0x00000000 + + + CH7_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH7_AL3_READ_ADDR_TRIG + 0x000001fc + Alias for channel 7 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH7_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH8_READ_ADDR + 0x00000200 + DMA Channel 8 Read Address pointer + 0x00000000 + + + CH8_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH8_WRITE_ADDR + 0x00000204 + DMA Channel 8 Write Address pointer + 0x00000000 + + + CH8_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH8_TRANS_COUNT + 0x00000208 + DMA Channel 8 Transfer Count + 0x00000000 + + + CH8_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH8_CTRL_TRIG + 0x0000020c + DMA Channel 8 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH8_AL1_CTRL + 0x00000210 + Alias for channel 8 CTRL register + 0x00000000 + + + CH8_AL1_CTRL + [31:0] + read-write + + + + + CH8_AL1_READ_ADDR + 0x00000214 + Alias for channel 8 READ_ADDR register + 0x00000000 + + + CH8_AL1_READ_ADDR + [31:0] + read-write + + + + + CH8_AL1_WRITE_ADDR + 0x00000218 + Alias for channel 8 WRITE_ADDR register + 0x00000000 + + + CH8_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH8_AL1_TRANS_COUNT_TRIG + 0x0000021c + Alias for channel 8 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH8_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH8_AL2_CTRL + 0x00000220 + Alias for channel 8 CTRL register + 0x00000000 + + + CH8_AL2_CTRL + [31:0] + read-write + + + + + CH8_AL2_TRANS_COUNT + 0x00000224 + Alias for channel 8 TRANS_COUNT register + 0x00000000 + + + CH8_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH8_AL2_READ_ADDR + 0x00000228 + Alias for channel 8 READ_ADDR register + 0x00000000 + + + CH8_AL2_READ_ADDR + [31:0] + read-write + + + + + CH8_AL2_WRITE_ADDR_TRIG + 0x0000022c + Alias for channel 8 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH8_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH8_AL3_CTRL + 0x00000230 + Alias for channel 8 CTRL register + 0x00000000 + + + CH8_AL3_CTRL + [31:0] + read-write + + + + + CH8_AL3_WRITE_ADDR + 0x00000234 + Alias for channel 8 WRITE_ADDR register + 0x00000000 + + + CH8_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH8_AL3_TRANS_COUNT + 0x00000238 + Alias for channel 8 TRANS_COUNT register + 0x00000000 + + + CH8_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH8_AL3_READ_ADDR_TRIG + 0x0000023c + Alias for channel 8 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH8_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH9_READ_ADDR + 0x00000240 + DMA Channel 9 Read Address pointer + 0x00000000 + + + CH9_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH9_WRITE_ADDR + 0x00000244 + DMA Channel 9 Write Address pointer + 0x00000000 + + + CH9_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH9_TRANS_COUNT + 0x00000248 + DMA Channel 9 Transfer Count + 0x00000000 + + + CH9_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH9_CTRL_TRIG + 0x0000024c + DMA Channel 9 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH9_AL1_CTRL + 0x00000250 + Alias for channel 9 CTRL register + 0x00000000 + + + CH9_AL1_CTRL + [31:0] + read-write + + + + + CH9_AL1_READ_ADDR + 0x00000254 + Alias for channel 9 READ_ADDR register + 0x00000000 + + + CH9_AL1_READ_ADDR + [31:0] + read-write + + + + + CH9_AL1_WRITE_ADDR + 0x00000258 + Alias for channel 9 WRITE_ADDR register + 0x00000000 + + + CH9_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH9_AL1_TRANS_COUNT_TRIG + 0x0000025c + Alias for channel 9 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH9_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH9_AL2_CTRL + 0x00000260 + Alias for channel 9 CTRL register + 0x00000000 + + + CH9_AL2_CTRL + [31:0] + read-write + + + + + CH9_AL2_TRANS_COUNT + 0x00000264 + Alias for channel 9 TRANS_COUNT register + 0x00000000 + + + CH9_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH9_AL2_READ_ADDR + 0x00000268 + Alias for channel 9 READ_ADDR register + 0x00000000 + + + CH9_AL2_READ_ADDR + [31:0] + read-write + + + + + CH9_AL2_WRITE_ADDR_TRIG + 0x0000026c + Alias for channel 9 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH9_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH9_AL3_CTRL + 0x00000270 + Alias for channel 9 CTRL register + 0x00000000 + + + CH9_AL3_CTRL + [31:0] + read-write + + + + + CH9_AL3_WRITE_ADDR + 0x00000274 + Alias for channel 9 WRITE_ADDR register + 0x00000000 + + + CH9_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH9_AL3_TRANS_COUNT + 0x00000278 + Alias for channel 9 TRANS_COUNT register + 0x00000000 + + + CH9_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH9_AL3_READ_ADDR_TRIG + 0x0000027c + Alias for channel 9 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH9_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH10_READ_ADDR + 0x00000280 + DMA Channel 10 Read Address pointer + 0x00000000 + + + CH10_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH10_WRITE_ADDR + 0x00000284 + DMA Channel 10 Write Address pointer + 0x00000000 + + + CH10_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH10_TRANS_COUNT + 0x00000288 + DMA Channel 10 Transfer Count + 0x00000000 + + + CH10_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH10_CTRL_TRIG + 0x0000028c + DMA Channel 10 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH10_AL1_CTRL + 0x00000290 + Alias for channel 10 CTRL register + 0x00000000 + + + CH10_AL1_CTRL + [31:0] + read-write + + + + + CH10_AL1_READ_ADDR + 0x00000294 + Alias for channel 10 READ_ADDR register + 0x00000000 + + + CH10_AL1_READ_ADDR + [31:0] + read-write + + + + + CH10_AL1_WRITE_ADDR + 0x00000298 + Alias for channel 10 WRITE_ADDR register + 0x00000000 + + + CH10_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH10_AL1_TRANS_COUNT_TRIG + 0x0000029c + Alias for channel 10 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH10_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH10_AL2_CTRL + 0x000002a0 + Alias for channel 10 CTRL register + 0x00000000 + + + CH10_AL2_CTRL + [31:0] + read-write + + + + + CH10_AL2_TRANS_COUNT + 0x000002a4 + Alias for channel 10 TRANS_COUNT register + 0x00000000 + + + CH10_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH10_AL2_READ_ADDR + 0x000002a8 + Alias for channel 10 READ_ADDR register + 0x00000000 + + + CH10_AL2_READ_ADDR + [31:0] + read-write + + + + + CH10_AL2_WRITE_ADDR_TRIG + 0x000002ac + Alias for channel 10 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH10_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH10_AL3_CTRL + 0x000002b0 + Alias for channel 10 CTRL register + 0x00000000 + + + CH10_AL3_CTRL + [31:0] + read-write + + + + + CH10_AL3_WRITE_ADDR + 0x000002b4 + Alias for channel 10 WRITE_ADDR register + 0x00000000 + + + CH10_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH10_AL3_TRANS_COUNT + 0x000002b8 + Alias for channel 10 TRANS_COUNT register + 0x00000000 + + + CH10_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH10_AL3_READ_ADDR_TRIG + 0x000002bc + Alias for channel 10 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH10_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH11_READ_ADDR + 0x000002c0 + DMA Channel 11 Read Address pointer + 0x00000000 + + + CH11_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH11_WRITE_ADDR + 0x000002c4 + DMA Channel 11 Write Address pointer + 0x00000000 + + + CH11_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH11_TRANS_COUNT + 0x000002c8 + DMA Channel 11 Transfer Count + 0x00000000 + + + CH11_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH11_CTRL_TRIG + 0x000002cc + DMA Channel 11 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH11_AL1_CTRL + 0x000002d0 + Alias for channel 11 CTRL register + 0x00000000 + + + CH11_AL1_CTRL + [31:0] + read-write + + + + + CH11_AL1_READ_ADDR + 0x000002d4 + Alias for channel 11 READ_ADDR register + 0x00000000 + + + CH11_AL1_READ_ADDR + [31:0] + read-write + + + + + CH11_AL1_WRITE_ADDR + 0x000002d8 + Alias for channel 11 WRITE_ADDR register + 0x00000000 + + + CH11_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH11_AL1_TRANS_COUNT_TRIG + 0x000002dc + Alias for channel 11 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH11_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH11_AL2_CTRL + 0x000002e0 + Alias for channel 11 CTRL register + 0x00000000 + + + CH11_AL2_CTRL + [31:0] + read-write + + + + + CH11_AL2_TRANS_COUNT + 0x000002e4 + Alias for channel 11 TRANS_COUNT register + 0x00000000 + + + CH11_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH11_AL2_READ_ADDR + 0x000002e8 + Alias for channel 11 READ_ADDR register + 0x00000000 + + + CH11_AL2_READ_ADDR + [31:0] + read-write + + + + + CH11_AL2_WRITE_ADDR_TRIG + 0x000002ec + Alias for channel 11 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH11_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH11_AL3_CTRL + 0x000002f0 + Alias for channel 11 CTRL register + 0x00000000 + + + CH11_AL3_CTRL + [31:0] + read-write + + + + + CH11_AL3_WRITE_ADDR + 0x000002f4 + Alias for channel 11 WRITE_ADDR register + 0x00000000 + + + CH11_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH11_AL3_TRANS_COUNT + 0x000002f8 + Alias for channel 11 TRANS_COUNT register + 0x00000000 + + + CH11_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH11_AL3_READ_ADDR_TRIG + 0x000002fc + Alias for channel 11 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH11_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + INTR + 0x00000400 + Interrupt Status (raw) + 0x00000000 + + + INTR + Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. + + Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. + + This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. + + It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + [15:0] + read-write + oneToClear + + + + + INTE0 + 0x00000404 + Interrupt Enables for IRQ 0 + 0x00000000 + + + INTE0 + Set bit n to pass interrupts from channel n to DMA IRQ 0. + [15:0] + read-write + + + + + INTF0 + 0x00000408 + Force Interrupts + 0x00000000 + + + INTF0 + Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + [15:0] + read-write + + + + + INTS0 + 0x0000040c + Interrupt Status for IRQ 0 + 0x00000000 + + + INTS0 + Indicates active channel interrupt requests which are currently causing IRQ 0 to be asserted. + Channel interrupts can be cleared by writing a bit mask here. + [15:0] + read-write + oneToClear + + + + + INTR1 + 0x00000410 + Interrupt Status (raw) + 0x00000000 + + + INTR1 + Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. + + Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. + + This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. + + It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + [15:0] + read-write + oneToClear + + + + + INTE1 + 0x00000414 + Interrupt Enables for IRQ 1 + 0x00000000 + + + INTE1 + Set bit n to pass interrupts from channel n to DMA IRQ 1. + [15:0] + read-write + + + + + INTF1 + 0x00000418 + Force Interrupts for IRQ 1 + 0x00000000 + + + INTF1 + Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + [15:0] + read-write + + + + + INTS1 + 0x0000041c + Interrupt Status (masked) for IRQ 1 + 0x00000000 + + + INTS1 + Indicates active channel interrupt requests which are currently causing IRQ 1 to be asserted. + Channel interrupts can be cleared by writing a bit mask here. + [15:0] + read-write + oneToClear + + + + + TIMER0 + 0x00000420 + Pacing (X/Y) Fractional Timer + The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + 0x00000000 + + + X + Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + [31:16] + read-write + + + Y + Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + [15:0] + read-write + + + + + TIMER1 + 0x00000424 + Pacing (X/Y) Fractional Timer + The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + 0x00000000 + + + X + Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + [31:16] + read-write + + + Y + Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + [15:0] + read-write + + + + + TIMER2 + 0x00000428 + Pacing (X/Y) Fractional Timer + The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + 0x00000000 + + + X + Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + [31:16] + read-write + + + Y + Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + [15:0] + read-write + + + + + TIMER3 + 0x0000042c + Pacing (X/Y) Fractional Timer + The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + 0x00000000 + + + X + Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + [31:16] + read-write + + + Y + Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + [15:0] + read-write + + + + + MULTI_CHAN_TRIGGER + 0x00000430 + Trigger one or more channels simultaneously + 0x00000000 + + + MULTI_CHAN_TRIGGER + Each bit in this register corresponds to a DMA channel. Writing a 1 to the relevant bit is the same as writing to that channel's trigger register; the channel will start if it is currently enabled and not already busy. + [15:0] + write-only + + + + + SNIFF_CTRL + 0x00000434 + Sniffer Control + 0x00000000 + + + OUT_INV + If set, the result appears inverted (bitwise complement) when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + [11:11] + read-write + + + OUT_REV + If set, the result appears bit-reversed when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + [10:10] + read-write + + + BSWAP + Locally perform a byte reverse on the sniffed data, before feeding into checksum. + + Note that the sniff hardware is downstream of the DMA channel byteswap performed in the read master: if channel CTRL_BSWAP and SNIFF_CTRL_BSWAP are both enabled, their effects cancel from the sniffer's point of view. + [9:9] + read-write + + + CALC + [8:5] + read-write + + + CRC32 + 0 + Calculate a CRC-32 (IEEE802.3 polynomial) + + + CRC32R + 1 + Calculate a CRC-32 (IEEE802.3 polynomial) with bit reversed data + + + CRC16 + 2 + Calculate a CRC-16-CCITT + + + CRC16R + 3 + Calculate a CRC-16-CCITT with bit reversed data + + + EVEN + 14 + XOR reduction over all data. == 1 if the total 1 population count is odd. + + + SUM + 15 + Calculate a simple 32-bit checksum (addition with a 32 bit accumulator) + + + + + DMACH + DMA channel for Sniffer to observe + [4:1] + read-write + + + EN + Enable sniffer + [0:0] + read-write + + + + + SNIFF_DATA + 0x00000438 + Data accumulator for sniff hardware + 0x00000000 + + + SNIFF_DATA + Write an initial seed value here before starting a DMA transfer on the channel indicated by SNIFF_CTRL_DMACH. The hardware will update this register each time it observes a read from the indicated channel. Once the channel completes, the final result can be read from this register. + [31:0] + read-write + + + + + FIFO_LEVELS + 0x00000440 + Debug RAF, WAF, TDF levels + 0x00000000 + + + RAF_LVL + Current Read-Address-FIFO fill level + [23:16] + read-only + + + WAF_LVL + Current Write-Address-FIFO fill level + [15:8] + read-only + + + TDF_LVL + Current Transfer-Data-FIFO fill level + [7:0] + read-only + + + + + CHAN_ABORT + 0x00000444 + Abort an in-progress transfer sequence on one or more channels + 0x00000000 + + + CHAN_ABORT + Each bit corresponds to a channel. Writing a 1 aborts whatever transfer sequence is in progress on that channel. The bit will remain high until any in-flight transfers have been flushed through the address and data FIFOs. + + After writing, this register must be polled until it returns all-zero. Until this point, it is unsafe to restart the channel. + [15:0] + read-write + oneToClear + + + + + N_CHANNELS + 0x00000448 + The number of channels this DMA instance is equipped with. This DMA supports up to 16 hardware channels, but can be configured with as few as one, to minimise silicon area. + 0x00000000 + + + N_CHANNELS + [4:0] + read-only + + + + + CH0_DBG_CTDREQ + 0x00000800 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH0_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH0_DBG_TCR + 0x00000804 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH0_DBG_TCR + [31:0] + read-only + + + + + CH1_DBG_CTDREQ + 0x00000840 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH1_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH1_DBG_TCR + 0x00000844 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH1_DBG_TCR + [31:0] + read-only + + + + + CH2_DBG_CTDREQ + 0x00000880 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH2_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH2_DBG_TCR + 0x00000884 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH2_DBG_TCR + [31:0] + read-only + + + + + CH3_DBG_CTDREQ + 0x000008c0 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH3_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH3_DBG_TCR + 0x000008c4 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH3_DBG_TCR + [31:0] + read-only + + + + + CH4_DBG_CTDREQ + 0x00000900 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH4_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH4_DBG_TCR + 0x00000904 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH4_DBG_TCR + [31:0] + read-only + + + + + CH5_DBG_CTDREQ + 0x00000940 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH5_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH5_DBG_TCR + 0x00000944 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH5_DBG_TCR + [31:0] + read-only + + + + + CH6_DBG_CTDREQ + 0x00000980 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH6_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH6_DBG_TCR + 0x00000984 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH6_DBG_TCR + [31:0] + read-only + + + + + CH7_DBG_CTDREQ + 0x000009c0 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH7_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH7_DBG_TCR + 0x000009c4 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH7_DBG_TCR + [31:0] + read-only + + + + + CH8_DBG_CTDREQ + 0x00000a00 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH8_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH8_DBG_TCR + 0x00000a04 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH8_DBG_TCR + [31:0] + read-only + + + + + CH9_DBG_CTDREQ + 0x00000a40 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH9_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH9_DBG_TCR + 0x00000a44 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH9_DBG_TCR + [31:0] + read-only + + + + + CH10_DBG_CTDREQ + 0x00000a80 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH10_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH10_DBG_TCR + 0x00000a84 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH10_DBG_TCR + [31:0] + read-only + + + + + CH11_DBG_CTDREQ + 0x00000ac0 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH11_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH11_DBG_TCR + 0x00000ac4 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH11_DBG_TCR + [31:0] + read-only + + + + + + + TIMER + Controls time and alarms + time is a 64 bit value indicating the time in usec since power-on + timeh is the top 32 bits of time & timel is the bottom 32 bits + to change time write to timelw before timehw + to read time read from timelr before timehr + An alarm is set by setting alarm_enable and writing to the corresponding alarm register + When an alarm is pending, the corresponding alarm_running signal will be high + An alarm can be cancelled before it has finished by clearing the alarm_enable + When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared + To clear the interrupt write a 1 to the corresponding alarm_irq + 0x40054000 + + 0 + 68 + registers + + + TIMER_IRQ_0 + 0 + + + TIMER_IRQ_1 + 1 + + + TIMER_IRQ_2 + 2 + + + TIMER_IRQ_3 + 3 + + + + TIMEHW + 0x00000000 + Write to bits 63:32 of time + always write timelw before timehw + 0x00000000 + + + TIMEHW + [31:0] + write-only + + + + + TIMELW + 0x00000004 + Write to bits 31:0 of time + writes do not get copied to time until timehw is written + 0x00000000 + + + TIMELW + [31:0] + write-only + + + + + TIMEHR + 0x00000008 + Read from bits 63:32 of time + always read timelr before timehr + 0x00000000 + + + TIMEHR + [31:0] + read-only + + + + + TIMELR + 0x0000000c + Read from bits 31:0 of time + 0x00000000 + + + TIMELR + [31:0] + read-only + modify + + + + + ALARM0 + 0x00000010 + Arm alarm 0, and configure the time it will fire. + Once armed, the alarm fires when TIMER_ALARM0 == TIMELR. + The alarm will disarm itself once it fires, and can + be disarmed early using the ARMED status register. + 0x00000000 + + + ALARM0 + [31:0] + read-write + + + + + ALARM1 + 0x00000014 + Arm alarm 1, and configure the time it will fire. + Once armed, the alarm fires when TIMER_ALARM1 == TIMELR. + The alarm will disarm itself once it fires, and can + be disarmed early using the ARMED status register. + 0x00000000 + + + ALARM1 + [31:0] + read-write + + + + + ALARM2 + 0x00000018 + Arm alarm 2, and configure the time it will fire. + Once armed, the alarm fires when TIMER_ALARM2 == TIMELR. + The alarm will disarm itself once it fires, and can + be disarmed early using the ARMED status register. + 0x00000000 + + + ALARM2 + [31:0] + read-write + + + + + ALARM3 + 0x0000001c + Arm alarm 3, and configure the time it will fire. + Once armed, the alarm fires when TIMER_ALARM3 == TIMELR. + The alarm will disarm itself once it fires, and can + be disarmed early using the ARMED status register. + 0x00000000 + + + ALARM3 + [31:0] + read-write + + + + + ARMED + 0x00000020 + Indicates the armed/disarmed status of each alarm. + A write to the corresponding ALARMx register arms the alarm. + Alarms automatically disarm upon firing, but writing ones here + will disarm immediately without waiting to fire. + 0x00000000 + + + ARMED + [3:0] + read-write + oneToClear + + + + + TIMERAWH + 0x00000024 + Raw read from bits 63:32 of time (no side effects) + 0x00000000 + + + TIMERAWH + [31:0] + read-only + + + + + TIMERAWL + 0x00000028 + Raw read from bits 31:0 of time (no side effects) + 0x00000000 + + + TIMERAWL + [31:0] + read-only + + + + + DBGPAUSE + 0x0000002c + Set bits high to enable pause when the corresponding debug ports are active + 0x00000007 + + + DBG1 + Pause when processor 1 is in debug mode + [2:2] + read-write + + + DBG0 + Pause when processor 0 is in debug mode + [1:1] + read-write + + + + + PAUSE + 0x00000030 + Set high to pause the timer + 0x00000000 + + + PAUSE + [0:0] + read-write + + + + + INTR + 0x00000034 + Raw Interrupts + 0x00000000 + + + ALARM_3 + [3:3] + read-write + oneToClear + + + ALARM_2 + [2:2] + read-write + oneToClear + + + ALARM_1 + [1:1] + read-write + oneToClear + + + ALARM_0 + [0:0] + read-write + oneToClear + + + + + INTE + 0x00000038 + Interrupt Enable + 0x00000000 + + + ALARM_3 + [3:3] + read-write + + + ALARM_2 + [2:2] + read-write + + + ALARM_1 + [1:1] + read-write + + + ALARM_0 + [0:0] + read-write + + + + + INTF + 0x0000003c + Interrupt Force + 0x00000000 + + + ALARM_3 + [3:3] + read-write + + + ALARM_2 + [2:2] + read-write + + + ALARM_1 + [1:1] + read-write + + + ALARM_0 + [0:0] + read-write + + + + + INTS + 0x00000040 + Interrupt status after masking & forcing + 0x00000000 + + + ALARM_3 + [3:3] + read-only + + + ALARM_2 + [2:2] + read-only + + + ALARM_1 + [1:1] + read-only + + + ALARM_0 + [0:0] + read-only + + + + + + + PWM + Simple PWM + 0x40050000 + + 0 + 180 + registers + + + PWM_IRQ_WRAP + 4 + + + + CH0_CSR + 0x00000000 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH0_DIV + 0x00000004 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH0_CTR + 0x00000008 + Direct access to the PWM counter + 0x00000000 + + + CH0_CTR + [15:0] + read-write + + + + + CH0_CC + 0x0000000c + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH0_TOP + 0x00000010 + Counter wrap value + 0x0000ffff + + + CH0_TOP + [15:0] + read-write + + + + + CH1_CSR + 0x00000014 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH1_DIV + 0x00000018 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH1_CTR + 0x0000001c + Direct access to the PWM counter + 0x00000000 + + + CH1_CTR + [15:0] + read-write + + + + + CH1_CC + 0x00000020 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH1_TOP + 0x00000024 + Counter wrap value + 0x0000ffff + + + CH1_TOP + [15:0] + read-write + + + + + CH2_CSR + 0x00000028 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH2_DIV + 0x0000002c + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH2_CTR + 0x00000030 + Direct access to the PWM counter + 0x00000000 + + + CH2_CTR + [15:0] + read-write + + + + + CH2_CC + 0x00000034 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH2_TOP + 0x00000038 + Counter wrap value + 0x0000ffff + + + CH2_TOP + [15:0] + read-write + + + + + CH3_CSR + 0x0000003c + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH3_DIV + 0x00000040 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH3_CTR + 0x00000044 + Direct access to the PWM counter + 0x00000000 + + + CH3_CTR + [15:0] + read-write + + + + + CH3_CC + 0x00000048 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH3_TOP + 0x0000004c + Counter wrap value + 0x0000ffff + + + CH3_TOP + [15:0] + read-write + + + + + CH4_CSR + 0x00000050 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH4_DIV + 0x00000054 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH4_CTR + 0x00000058 + Direct access to the PWM counter + 0x00000000 + + + CH4_CTR + [15:0] + read-write + + + + + CH4_CC + 0x0000005c + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH4_TOP + 0x00000060 + Counter wrap value + 0x0000ffff + + + CH4_TOP + [15:0] + read-write + + + + + CH5_CSR + 0x00000064 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH5_DIV + 0x00000068 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH5_CTR + 0x0000006c + Direct access to the PWM counter + 0x00000000 + + + CH5_CTR + [15:0] + read-write + + + + + CH5_CC + 0x00000070 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH5_TOP + 0x00000074 + Counter wrap value + 0x0000ffff + + + CH5_TOP + [15:0] + read-write + + + + + CH6_CSR + 0x00000078 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH6_DIV + 0x0000007c + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH6_CTR + 0x00000080 + Direct access to the PWM counter + 0x00000000 + + + CH6_CTR + [15:0] + read-write + + + + + CH6_CC + 0x00000084 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH6_TOP + 0x00000088 + Counter wrap value + 0x0000ffff + + + CH6_TOP + [15:0] + read-write + + + + + CH7_CSR + 0x0000008c + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH7_DIV + 0x00000090 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH7_CTR + 0x00000094 + Direct access to the PWM counter + 0x00000000 + + + CH7_CTR + [15:0] + read-write + + + + + CH7_CC + 0x00000098 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH7_TOP + 0x0000009c + Counter wrap value + 0x0000ffff + + + CH7_TOP + [15:0] + read-write + + + + + EN + 0x000000a0 + This register aliases the CSR_EN bits for all channels. + Writing to this register allows multiple channels to be enabled + or disabled simultaneously, so they can run in perfect sync. + For each channel, there is only one physical EN register bit, + which can be accessed through here or CHx_CSR. + 0x00000000 + + + CH7 + [7:7] + read-write + + + CH6 + [6:6] + read-write + + + CH5 + [5:5] + read-write + + + CH4 + [4:4] + read-write + + + CH3 + [3:3] + read-write + + + CH2 + [2:2] + read-write + + + CH1 + [1:1] + read-write + + + CH0 + [0:0] + read-write + + + + + INTR + 0x000000a4 + Raw Interrupts + 0x00000000 + + + CH7 + [7:7] + read-write + oneToClear + + + CH6 + [6:6] + read-write + oneToClear + + + CH5 + [5:5] + read-write + oneToClear + + + CH4 + [4:4] + read-write + oneToClear + + + CH3 + [3:3] + read-write + oneToClear + + + CH2 + [2:2] + read-write + oneToClear + + + CH1 + [1:1] + read-write + oneToClear + + + CH0 + [0:0] + read-write + oneToClear + + + + + INTE + 0x000000a8 + Interrupt Enable + 0x00000000 + + + CH7 + [7:7] + read-write + + + CH6 + [6:6] + read-write + + + CH5 + [5:5] + read-write + + + CH4 + [4:4] + read-write + + + CH3 + [3:3] + read-write + + + CH2 + [2:2] + read-write + + + CH1 + [1:1] + read-write + + + CH0 + [0:0] + read-write + + + + + INTF + 0x000000ac + Interrupt Force + 0x00000000 + + + CH7 + [7:7] + read-write + + + CH6 + [6:6] + read-write + + + CH5 + [5:5] + read-write + + + CH4 + [4:4] + read-write + + + CH3 + [3:3] + read-write + + + CH2 + [2:2] + read-write + + + CH1 + [1:1] + read-write + + + CH0 + [0:0] + read-write + + + + + INTS + 0x000000b0 + Interrupt status after masking & forcing + 0x00000000 + + + CH7 + [7:7] + read-only + + + CH6 + [6:6] + read-only + + + CH5 + [5:5] + read-only + + + CH4 + [4:4] + read-only + + + CH3 + [3:3] + read-only + + + CH2 + [2:2] + read-only + + + CH1 + [1:1] + read-only + + + CH0 + [0:0] + read-only + + + + + + + ADC + Control and data interface to SAR ADC + 0x4004c000 + + 0 + 36 + registers + + + ADC_IRQ_FIFO + 22 + + + + CS + 0x00000000 + ADC Control and Status + 0x00000000 + + + RROBIN + Round-robin sampling. 1 bit per channel. Set all bits to 0 to disable. + Otherwise, the ADC will cycle through each enabled channel in a round-robin fashion. + The first channel to be sampled will be the one currently indicated by AINSEL. + AINSEL will be updated after each conversion with the newly-selected channel. + [20:16] + read-write + + + AINSEL + Select analog mux input. Updated automatically in round-robin mode. + [14:12] + read-write + + + ERR_STICKY + Some past ADC conversion encountered an error. Write 1 to clear. + [10:10] + read-write + oneToClear + + + ERR + The most recent ADC conversion encountered an error; result is undefined or noisy. + [9:9] + read-only + + + READY + 1 if the ADC is ready to start a new conversion. Implies any previous conversion has completed. + 0 whilst conversion in progress. + [8:8] + read-only + + + START_MANY + Continuously perform conversions whilst this bit is 1. A new conversion will start immediately after the previous finishes. + [3:3] + read-write + + + START_ONCE + Start a single conversion. Self-clearing. Ignored if start_many is asserted. + [2:2] + write-only + + + TS_EN + Power on temperature sensor. 1 - enabled. 0 - disabled. + [1:1] + read-write + + + EN + Power on ADC and enable its clock. + 1 - enabled. 0 - disabled. + [0:0] + read-write + + + + + RESULT + 0x00000004 + Result of most recent ADC conversion + 0x00000000 + + + RESULT + [11:0] + read-only + + + + + FCS + 0x00000008 + FIFO control and status + 0x00000000 + + + THRESH + DREQ/IRQ asserted when level >= threshold + [27:24] + read-write + + + LEVEL + The number of conversion results currently waiting in the FIFO + [19:16] + read-only + + + OVER + 1 if the FIFO has been overflowed. Write 1 to clear. + [11:11] + read-write + oneToClear + + + UNDER + 1 if the FIFO has been underflowed. Write 1 to clear. + [10:10] + read-write + oneToClear + + + FULL + [9:9] + read-only + + + EMPTY + [8:8] + read-only + + + DREQ_EN + If 1: assert DMA requests when FIFO contains data + [3:3] + read-write + + + ERR + If 1: conversion error bit appears in the FIFO alongside the result + [2:2] + read-write + + + SHIFT + If 1: FIFO results are right-shifted to be one byte in size. Enables DMA to byte buffers. + [1:1] + read-write + + + EN + If 1: write result to the FIFO after each conversion. + [0:0] + read-write + + + + + FIFO + 0x0000000c + Conversion result FIFO + 0x00000000 + + + ERR + 1 if this particular sample experienced a conversion error. Remains in the same location if the sample is shifted. + [15:15] + read-only + modify + + + VAL + [11:0] + read-only + modify + + + + + DIV + 0x00000010 + Clock divider. If non-zero, CS_START_MANY will start conversions + at regular intervals rather than back-to-back. + The divider is reset when either of these fields are written. + Total period is 1 + INT + FRAC / 256 + 0x00000000 + + + INT + Integer part of clock divisor. + [23:8] + read-write + + + FRAC + Fractional part of clock divisor. First-order delta-sigma. + [7:0] + read-write + + + + + INTR + 0x00000014 + Raw Interrupts + 0x00000000 + + + FIFO + Triggered when the sample FIFO reaches a certain level. + This level can be programmed via the FCS_THRESH field. + [0:0] + read-only + + + + + INTE + 0x00000018 + Interrupt Enable + 0x00000000 + + + FIFO + Triggered when the sample FIFO reaches a certain level. + This level can be programmed via the FCS_THRESH field. + [0:0] + read-write + + + + + INTF + 0x0000001c + Interrupt Force + 0x00000000 + + + FIFO + Triggered when the sample FIFO reaches a certain level. + This level can be programmed via the FCS_THRESH field. + [0:0] + read-write + + + + + INTS + 0x00000020 + Interrupt status after masking & forcing + 0x00000000 + + + FIFO + Triggered when the sample FIFO reaches a certain level. + This level can be programmed via the FCS_THRESH field. + [0:0] + read-only + + + + + + + I2C0 + DW_apb_i2c address block + + List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): + + IC_ULTRA_FAST_MODE ................ 0x0 + IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 + IC_UFM_SCL_LOW_COUNT .............. 0x0008 + IC_UFM_SCL_HIGH_COUNT ............. 0x0006 + IC_TX_TL .......................... 0x0 + IC_TX_CMD_BLOCK ................... 0x1 + IC_HAS_DMA ........................ 0x1 + IC_HAS_ASYNC_FIFO ................. 0x0 + IC_SMBUS_ARP ...................... 0x0 + IC_FIRST_DATA_BYTE_STATUS ......... 0x1 + IC_INTR_IO ........................ 0x1 + IC_MASTER_MODE .................... 0x1 + IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 + IC_INTR_POL ....................... 0x1 + IC_OPTIONAL_SAR ................... 0x0 + IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 + IC_DEFAULT_SLAVE_ADDR ............. 0x055 + IC_DEFAULT_HS_SPKLEN .............. 0x1 + IC_FS_SCL_HIGH_COUNT .............. 0x0006 + IC_HS_SCL_LOW_COUNT ............... 0x0008 + IC_DEVICE_ID_VALUE ................ 0x0 + IC_10BITADDR_MASTER ............... 0x0 + IC_CLK_FREQ_OPTIMIZATION .......... 0x0 + IC_DEFAULT_FS_SPKLEN .............. 0x7 + IC_ADD_ENCODED_PARAMS ............. 0x0 + IC_DEFAULT_SDA_HOLD ............... 0x000001 + IC_DEFAULT_SDA_SETUP .............. 0x64 + IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 + IC_CLOCK_PERIOD ................... 100 + IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 + IC_RESTART_EN ..................... 0x1 + IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 + IC_BUS_CLEAR_FEATURE .............. 0x0 + IC_CAP_LOADING .................... 100 + IC_FS_SCL_LOW_COUNT ............... 0x000d + APB_DATA_WIDTH .................... 32 + IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff + IC_SLV_DATA_NACK_ONLY ............. 0x1 + IC_10BITADDR_SLAVE ................ 0x0 + IC_CLK_TYPE ....................... 0x0 + IC_SMBUS_UDID_MSB ................. 0x0 + IC_SMBUS_SUSPEND_ALERT ............ 0x0 + IC_HS_SCL_HIGH_COUNT .............. 0x0006 + IC_SLV_RESTART_DET_EN ............. 0x1 + IC_SMBUS .......................... 0x0 + IC_OPTIONAL_SAR_DEFAULT ........... 0x0 + IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 + IC_USE_COUNTS ..................... 0x0 + IC_RX_BUFFER_DEPTH ................ 16 + IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff + IC_RX_FULL_HLD_BUS_EN ............. 0x1 + IC_SLAVE_DISABLE .................. 0x1 + IC_RX_TL .......................... 0x0 + IC_DEVICE_ID ...................... 0x0 + IC_HC_COUNT_VALUES ................ 0x0 + I2C_DYNAMIC_TAR_UPDATE ............ 0 + IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff + IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff + IC_HS_MASTER_CODE ................. 0x1 + IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff + IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff + IC_SS_SCL_HIGH_COUNT .............. 0x0028 + IC_SS_SCL_LOW_COUNT ............... 0x002f + IC_MAX_SPEED_MODE ................. 0x2 + IC_STAT_FOR_CLK_STRETCH ........... 0x0 + IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 + IC_DEFAULT_UFM_SPKLEN ............. 0x1 + IC_TX_BUFFER_DEPTH ................ 16 + 0x40044000 + + 0 + 256 + registers + + + I2C0_IRQ + 23 + + + + IC_CON + 0x00000000 + I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only. + 0x00000065 + + + STOP_DET_IF_MASTER_ACTIVE + Master issues the STOP_DET interrupt irrespective of whether master is active or not + [10:10] + read-only + + + RX_FIFO_FULL_HLD_CTRL + This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is physically full to its RX_BUFFER_DEPTH, as described in the IC_RX_FULL_HLD_BUS_EN parameter. + + Reset value: 0x0. + [9:9] + read-write + + + DISABLED + 0 + Overflow when RX_FIFO is full + + + ENABLED + 1 + Hold bus when RX_FIFO is full + + + + + TX_EMPTY_CTRL + This bit controls the generation of the TX_EMPTY interrupt, as described in the IC_RAW_INTR_STAT register. + + Reset value: 0x0. + [8:8] + read-write + + + DISABLED + 0 + Default behaviour of TX_EMPTY interrupt + + + ENABLED + 1 + Controlled generation of TX_EMPTY interrupt + + + + + STOP_DET_IFADDRESSED + In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset value: 0x0 + + NOTE: During a general call address, this slave does not issue the STOP_DET interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). + [7:7] + read-write + + + DISABLED + 0 + slave issues STOP_DET intr always + + + ENABLED + 1 + slave issues STOP_DET intr only if addressed + + + + + IC_SLAVE_DISABLE + This bit controls whether I2C has its slave disabled, which means once the presetn signal is applied, then this bit is set and the slave is disabled. + + If this bit is set (slave is disabled), DW_apb_i2c functions only as a master and does not perform any action that requires a slave. + + NOTE: Software should ensure that if this bit is written with 0, then bit 0 should also be written with a 0. + [6:6] + read-write + + + SLAVE_ENABLED + 0 + Slave mode is enabled + + + SLAVE_DISABLED + 1 + Slave mode is disabled + + + + + IC_RESTART_EN + Determines whether RESTART conditions may be sent when acting as a master. Some older slaves do not support handling RESTART conditions; however, RESTART conditions are used in several DW_apb_i2c operations. When RESTART is disabled, the master is prohibited from performing the following functions: - Sending a START BYTE - Performing any high-speed mode operation - High-speed mode operation - Performing direction changes in combined format mode - Performing a read operation with a 10-bit address By replacing RESTART condition followed by a STOP and a subsequent START condition, split operations are broken down into multiple DW_apb_i2c transfers. If the above operations are performed, it will result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. + + Reset value: ENABLED + [5:5] + read-write + + + DISABLED + 0 + Master restart disabled + + + ENABLED + 1 + Master restart enabled + + + + + IC_10BITADDR_MASTER + Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing + [4:4] + read-write + + + ADDR_7BITS + 0 + Master 7Bit addressing mode + + + ADDR_10BITS + 1 + Master 10Bit addressing mode + + + + + IC_10BITADDR_SLAVE + When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c responds to only 10-bit addressing transfers that match the full 10 bits of the IC_SAR register. + [3:3] + read-write + + + ADDR_7BITS + 0 + Slave 7Bit addressing + + + ADDR_10BITS + 1 + Slave 10Bit addressing + + + + + SPEED + These bits control at which speed the DW_apb_i2c operates; its setting is relevant only if one is operating the DW_apb_i2c in master mode. Hardware protects against illegal values being programmed by software. These bits must be programmed appropriately for slave mode also, as it is used to capture correct value of spike filter as per the speed mode. + + This register should be programmed only with a value in the range of 1 to IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of IC_MAX_SPEED_MODE. + + 1: standard mode (100 kbit/s) + + 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s) + + 3: high speed mode (3.4 Mbit/s) + + Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 + [2:1] + read-write + + + STANDARD + 1 + Standard Speed mode of operation + + + FAST + 2 + Fast or Fast Plus mode of operation + + + HIGH + 3 + High Speed mode of operation + + + + + MASTER_MODE + This bit controls whether the DW_apb_i2c master is enabled. + + NOTE: Software should ensure that if this bit is written with '1' then bit 6 should also be written with a '1'. + [0:0] + read-write + + + DISABLED + 0 + Master mode is disabled + + + ENABLED + 1 + Master mode is enabled + + + + + + + IC_TAR + 0x00000004 + I2C Target Address Register + + This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0. + + Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only. + 0x00000055 + + + SPECIAL + This bit indicates whether software performs a Device-ID or General Call or START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: perform special I2C command as specified in Device_ID or GC_OR_START bit Reset value: 0x0 + [11:11] + read-write + + + DISABLED + 0 + Disables programming of GENERAL_CALL or START_BYTE transmission + + + ENABLED + 1 + Enables programming of GENERAL_CALL or START_BYTE transmission + + + + + GC_OR_START + If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit indicates whether a General Call or START byte command is to be performed by the DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only writes may be performed. Attempting to issue a read command results in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START BYTE Reset value: 0x0 + [10:10] + read-write + + + GENERAL_CALL + 0 + GENERAL_CALL byte transmission + + + START_BYTE + 1 + START byte transmission + + + + + IC_TAR + This is the target address for any master transaction. When transmitting a General Call, these bits are ignored. To generate a START BYTE, the CPU needs to write only once into these bits. + + If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared between master and slave, so full loopback is not feasible. Only one direction loopback mode is supported (simplex), not duplex. A master cannot transmit to itself; it can transmit to only a slave. + [9:0] + read-write + + + + + IC_SAR + 0x00000008 + I2C Slave Address Register + 0x00000055 + + + IC_SAR + The IC_SAR holds the slave address when the I2C is operating as a slave. For 7-bit addressing, only IC_SAR[6:0] is used. + + This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + Note: The default values cannot be any of the reserved address locations: that is, 0x00 to 0x07, or 0x78 to 0x7f. The correct operation of the device is not guaranteed if you program the IC_SAR or IC_TAR to a reserved value. Refer to <<table_I2C_firstbyte_bit_defs>> for a complete list of these reserved values. + [9:0] + read-write + + + + + IC_DATA_CMD + 0x00000010 + I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO. + + The size of the register changes as follows: + + Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging. + 0x00000000 + + + FIRST_DATA_BYTE + Indicates the first data byte received after the address phase for receive transfer in Master receiver or Slave receiver mode. + + Reset value : 0x0 + + NOTE: In case of APB_DATA_WIDTH=8, + + 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status on 11 bit. + + 2. In order to read the 11 bit, the user has to perform the first data byte read [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in order to know the status of 11 bit (whether the data received in previous read is a first data byte or not). + + 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] (offset 0x11) if not interested in FIRST_DATA_BYTE status. + [11:11] + read-only + + + INACTIVE + 0 + Sequential data byte received + + + ACTIVE + 1 + Non sequential data byte received + + + + + RESTART + This bit controls whether a RESTART is issued before the byte is sent or received. + + 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received (according to the value of CMD), regardless of whether or not the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. + + 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. + + Reset value: 0x0 + [10:10] + write-only + + + DISABLE + 0 + Don't Issue RESTART before this command + + + ENABLE + 1 + Issue RESTART before this command + + + + + STOP + This bit controls whether a STOP is issued after the byte is sent or received. + + - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master immediately tries to start a new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master continues the current transfer by sending/receiving data bytes according to the value of the CMD bit. If the Tx FIFO is empty, the master holds the SCL line low and stalls the bus until a new command is available in the Tx FIFO. Reset value: 0x0 + [9:9] + write-only + + + DISABLE + 0 + Don't Issue STOP after this command + + + ENABLE + 1 + Issue STOP after this command + + + + + CMD + This bit controls whether a read or a write is performed. This bit does not control the direction when the DW_apb_i2con acts as a slave. It controls only the direction when it acts as a master. + + When a command is entered in the TX FIFO, this bit distinguishes the write and read commands. In slave-receiver mode, this bit is a 'don't care' because writes to this register are not required. In slave-transmitter mode, a '0' indicates that the data in IC_DATA_CMD is to be transmitted. + + When programming this bit, you should remember the following: attempting to perform a read operation after a General Call command has been sent results in a TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs. + + Reset value: 0x0 + [8:8] + write-only + + + WRITE + 0 + Master Write Command + + + READ + 1 + Master Read Command + + + + + DAT + This register contains the data to be transmitted or received on the I2C bus. If you are writing to this register and want to perform a read, bits 7:0 (DAT) are ignored by the DW_apb_i2c. However, when you read this register, these bits return the value of data received on the DW_apb_i2c interface. + + Reset value: 0x0 + [7:0] + read-write + + + + + IC_SS_SCL_HCNT + 0x00000014 + Standard Speed I2C Clock SCL High Count Register + 0x00000028 + + + IC_SS_SCL_HCNT + This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration'. + + This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. + + NOTE: This register must not be programmed to a value higher than 65525, because DW_apb_i2c uses a 16-bit counter to flag an I2C bus idle condition when this counter reaches a value of IC_SS_SCL_HCNT + 10. + [15:0] + read-write + + + + + IC_SS_SCL_LCNT + 0x00000018 + Standard Speed I2C Clock SCL Low Count Register + 0x0000002f + + + IC_SS_SCL_LCNT + This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration' + + This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + The minimum valid value is 8; hardware prevents values less than this being written, and if attempted, results in 8 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of DW_apb_i2c. The lower byte must be programmed first, and then the upper byte is programmed. + [15:0] + read-write + + + + + IC_FS_SCL_HCNT + 0x0000001c + Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register + 0x00000006 + + + IC_FS_SCL_HCNT + This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for fast mode or fast mode plus. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. + + This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH == 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. + [15:0] + read-write + + + + + IC_FS_SCL_LCNT + 0x00000020 + Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register + 0x0000000d + + + IC_FS_SCL_LCNT + This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for fast speed. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. + + This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. + + This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + The minimum valid value is 8; hardware prevents values less than this being written, and if attempted results in 8 being set. For designs with APB_DATA_WIDTH = 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. If the value is less than 8 then the count value gets changed to 8. + [15:0] + read-write + + + + + IC_INTR_STAT + 0x0000002c + I2C Interrupt Status Register + + Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. + 0x00000000 + + + R_RESTART_DET + See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit. + + Reset value: 0x0 + [12:12] + read-only + + + INACTIVE + 0 + R_RESTART_DET interrupt is inactive + + + ACTIVE + 1 + R_RESTART_DET interrupt is active + + + + + R_GEN_CALL + See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit. + + Reset value: 0x0 + [11:11] + read-only + + + INACTIVE + 0 + R_GEN_CALL interrupt is inactive + + + ACTIVE + 1 + R_GEN_CALL interrupt is active + + + + + R_START_DET + See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit. + + Reset value: 0x0 + [10:10] + read-only + + + INACTIVE + 0 + R_START_DET interrupt is inactive + + + ACTIVE + 1 + R_START_DET interrupt is active + + + + + R_STOP_DET + See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit. + + Reset value: 0x0 + [9:9] + read-only + + + INACTIVE + 0 + R_STOP_DET interrupt is inactive + + + ACTIVE + 1 + R_STOP_DET interrupt is active + + + + + R_ACTIVITY + See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit. + + Reset value: 0x0 + [8:8] + read-only + + + INACTIVE + 0 + R_ACTIVITY interrupt is inactive + + + ACTIVE + 1 + R_ACTIVITY interrupt is active + + + + + R_RX_DONE + See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit. + + Reset value: 0x0 + [7:7] + read-only + + + INACTIVE + 0 + R_RX_DONE interrupt is inactive + + + ACTIVE + 1 + R_RX_DONE interrupt is active + + + + + R_TX_ABRT + See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit. + + Reset value: 0x0 + [6:6] + read-only + + + INACTIVE + 0 + R_TX_ABRT interrupt is inactive + + + ACTIVE + 1 + R_TX_ABRT interrupt is active + + + + + R_RD_REQ + See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit. + + Reset value: 0x0 + [5:5] + read-only + + + INACTIVE + 0 + R_RD_REQ interrupt is inactive + + + ACTIVE + 1 + R_RD_REQ interrupt is active + + + + + R_TX_EMPTY + See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit. + + Reset value: 0x0 + [4:4] + read-only + + + INACTIVE + 0 + R_TX_EMPTY interrupt is inactive + + + ACTIVE + 1 + R_TX_EMPTY interrupt is active + + + + + R_TX_OVER + See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit. + + Reset value: 0x0 + [3:3] + read-only + + + INACTIVE + 0 + R_TX_OVER interrupt is inactive + + + ACTIVE + 1 + R_TX_OVER interrupt is active + + + + + R_RX_FULL + See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit. + + Reset value: 0x0 + [2:2] + read-only + + + INACTIVE + 0 + R_RX_FULL interrupt is inactive + + + ACTIVE + 1 + R_RX_FULL interrupt is active + + + + + R_RX_OVER + See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit. + + Reset value: 0x0 + [1:1] + read-only + + + INACTIVE + 0 + R_RX_OVER interrupt is inactive + + + ACTIVE + 1 + R_RX_OVER interrupt is active + + + + + R_RX_UNDER + See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit. + + Reset value: 0x0 + [0:0] + read-only + + + INACTIVE + 0 + RX_UNDER interrupt is inactive + + + ACTIVE + 1 + RX_UNDER interrupt is active + + + + + + + IC_INTR_MASK + 0x00000030 + I2C Interrupt Mask Register. + + These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. + 0x000008ff + + + M_RESTART_DET + This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register. + + Reset value: 0x0 + [12:12] + read-write + + + ENABLED + 0 + RESTART_DET interrupt is masked + + + DISABLED + 1 + RESTART_DET interrupt is unmasked + + + + + M_GEN_CALL + This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [11:11] + read-write + + + ENABLED + 0 + GEN_CALL interrupt is masked + + + DISABLED + 1 + GEN_CALL interrupt is unmasked + + + + + M_START_DET + This bit masks the R_START_DET interrupt in IC_INTR_STAT register. + + Reset value: 0x0 + [10:10] + read-write + + + ENABLED + 0 + START_DET interrupt is masked + + + DISABLED + 1 + START_DET interrupt is unmasked + + + + + M_STOP_DET + This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register. + + Reset value: 0x0 + [9:9] + read-write + + + ENABLED + 0 + STOP_DET interrupt is masked + + + DISABLED + 1 + STOP_DET interrupt is unmasked + + + + + M_ACTIVITY + This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register. + + Reset value: 0x0 + [8:8] + read-write + + + ENABLED + 0 + ACTIVITY interrupt is masked + + + DISABLED + 1 + ACTIVITY interrupt is unmasked + + + + + M_RX_DONE + This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [7:7] + read-write + + + ENABLED + 0 + RX_DONE interrupt is masked + + + DISABLED + 1 + RX_DONE interrupt is unmasked + + + + + M_TX_ABRT + This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [6:6] + read-write + + + ENABLED + 0 + TX_ABORT interrupt is masked + + + DISABLED + 1 + TX_ABORT interrupt is unmasked + + + + + M_RD_REQ + This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [5:5] + read-write + + + ENABLED + 0 + RD_REQ interrupt is masked + + + DISABLED + 1 + RD_REQ interrupt is unmasked + + + + + M_TX_EMPTY + This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [4:4] + read-write + + + ENABLED + 0 + TX_EMPTY interrupt is masked + + + DISABLED + 1 + TX_EMPTY interrupt is unmasked + + + + + M_TX_OVER + This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [3:3] + read-write + + + ENABLED + 0 + TX_OVER interrupt is masked + + + DISABLED + 1 + TX_OVER interrupt is unmasked + + + + + M_RX_FULL + This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [2:2] + read-write + + + ENABLED + 0 + RX_FULL interrupt is masked + + + DISABLED + 1 + RX_FULL interrupt is unmasked + + + + + M_RX_OVER + This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [1:1] + read-write + + + ENABLED + 0 + RX_OVER interrupt is masked + + + DISABLED + 1 + RX_OVER interrupt is unmasked + + + + + M_RX_UNDER + This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [0:0] + read-write + + + ENABLED + 0 + RX_UNDER interrupt is masked + + + DISABLED + 1 + RX_UNDER interrupt is unmasked + + + + + + + IC_RAW_INTR_STAT + 0x00000034 + I2C Raw Interrupt Status Register + + Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c. + 0x00000000 + + + RESTART_DET + Indicates whether a RESTART condition has occurred on the I2C interface when DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled only when IC_SLV_RESTART_DET_EN=1. + + Note: However, in high-speed mode or during a START BYTE transfer, the RESTART comes before the address field as per the I2C protocol. In this case, the slave is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does not generate the RESTART_DET interrupt. + + Reset value: 0x0 + [12:12] + read-only + + + INACTIVE + 0 + RESTART_DET interrupt is inactive + + + ACTIVE + 1 + RESTART_DET interrupt is active + + + + + GEN_CALL + Set only when a General Call address is received and it is acknowledged. It stays set until it is cleared either by disabling DW_apb_i2c or when the CPU reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data in the Rx buffer. + + Reset value: 0x0 + [11:11] + read-only + + + INACTIVE + 0 + GEN_CALL interrupt is inactive + + + ACTIVE + 1 + GEN_CALL interrupt is active + + + + + START_DET + Indicates whether a START or RESTART condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. + + Reset value: 0x0 + [10:10] + read-only + + + INACTIVE + 0 + START_DET interrupt is inactive + + + ACTIVE + 1 + START_DET interrupt is active + + + + + STOP_DET + Indicates whether a STOP condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. + + In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET interrupt will be issued only if slave is addressed. Note: During a general call address, this slave does not issue a STOP_DET interrupt if STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt will be issued irrespective of whether master is active or not. Reset value: 0x0 + [9:9] + read-only + + + INACTIVE + 0 + STOP_DET interrupt is inactive + + + ACTIVE + 1 + STOP_DET interrupt is active + + + + + ACTIVITY + This bit captures DW_apb_i2c activity and stays set until it is cleared. There are four ways to clear it: - Disabling the DW_apb_i2c - Reading the IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once this bit is set, it stays set unless one of the four methods is used to clear it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, indicating that there was activity on the bus. + + Reset value: 0x0 + [8:8] + read-only + + + INACTIVE + 0 + RAW_INTR_ACTIVITY interrupt is inactive + + + ACTIVE + 1 + RAW_INTR_ACTIVITY interrupt is active + + + + + RX_DONE + When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if the master does not acknowledge a transmitted byte. This occurs on the last byte of the transmission, indicating that the transmission is done. + + Reset value: 0x0 + [7:7] + read-only + + + INACTIVE + 0 + RX_DONE interrupt is inactive + + + ACTIVE + 1 + RX_DONE interrupt is active + + + + + TX_ABRT + This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete the intended actions on the contents of the transmit FIFO. This situation can occur both as an I2C master or an I2C slave, and is referred to as a 'transmit abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the reason why the transmit abort takes places. + + Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever there is a transmit abort caused by any of the events tracked by the IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is then ready to accept more data bytes from the APB interface. + + Reset value: 0x0 + [6:6] + read-only + + + INACTIVE + 0 + TX_ABRT interrupt is inactive + + + ACTIVE + 1 + TX_ABRT interrupt is active + + + + + RD_REQ + This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in a wait state (SCL=0) until this interrupt is serviced, which means that the slave has been addressed by a remote master that is asking for data to be transferred. The processor must respond to this interrupt and then write the requested data to the IC_DATA_CMD register. This bit is set to 0 just after the processor reads the IC_CLR_RD_REQ register. + + Reset value: 0x0 + [5:5] + read-only + + + INACTIVE + 0 + RD_REQ interrupt is inactive + + + ACTIVE + 1 + RD_REQ interrupt is active + + + + + TX_EMPTY + The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register and the transmission of the address/data from the internal shift register for the most recently popped command is completed. It is automatically cleared by hardware when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no data within it, so this bit is set to 1, provided there is activity in the master or slave state machines. When there is no longer any activity, then with ic_en=0, this bit is set to 0. + + Reset value: 0x0. + [4:4] + read-only + + + INACTIVE + 0 + TX_EMPTY interrupt is inactive + + + ACTIVE + 1 + TX_EMPTY interrupt is active + + + + + TX_OVER + Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and the processor attempts to issue another I2C command by writing to the IC_DATA_CMD register. When the module is disabled, this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. + + Reset value: 0x0 + [3:3] + read-only + + + INACTIVE + 0 + TX_OVER interrupt is inactive + + + ACTIVE + 1 + TX_OVER interrupt is active + + + + + RX_FULL + Set when the receive buffer reaches or goes above the RX_TL threshold in the IC_RX_TL register. It is automatically cleared by hardware when buffer level goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of the activity that continues. + + Reset value: 0x0 + [2:2] + read-only + + + INACTIVE + 0 + RX_FULL interrupt is inactive + + + ACTIVE + 1 + RX_FULL interrupt is active + + + + + RX_OVER + Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an additional byte is received from an external I2C device. The DW_apb_i2c acknowledges this, but any data bytes received after the FIFO is full are lost. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. + + Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never overflows. + + Reset value: 0x0 + [1:1] + read-only + + + INACTIVE + 0 + RX_OVER interrupt is inactive + + + ACTIVE + 1 + RX_OVER interrupt is active + + + + + RX_UNDER + Set if the processor attempts to read the receive buffer when it is empty by reading from the IC_DATA_CMD register. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. + + Reset value: 0x0 + [0:0] + read-only + + + INACTIVE + 0 + RX_UNDER interrupt is inactive + + + ACTIVE + 1 + RX_UNDER interrupt is active + + + + + + + IC_RX_TL + 0x00000038 + I2C Receive FIFO Threshold Register + 0x00000000 + + + RX_TL + Receive FIFO Threshold Level. + + Controls the level of entries (or above) that triggers the RX_FULL interrupt (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that hardware does not allow this value to be set to a value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. + [7:0] + read-write + + + + + IC_TX_TL + 0x0000003c + I2C Transmit FIFO Threshold Register + 0x00000000 + + + TX_TL + Transmit FIFO Threshold Level. + + Controls the level of entries (or below) that trigger the TX_EMPTY interrupt (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that it may not be set to value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and a value of 255 sets the threshold for 255 entries. + [7:0] + read-write + + + + + IC_CLR_INTR + 0x00000040 + Clear Combined and Individual Interrupt Register + 0x00000000 + + + CLR_INTR + Read this register to clear the combined interrupt, all individual interrupts, and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable interrupts but software clearable interrupts. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_RX_UNDER + 0x00000044 + Clear RX_UNDER Interrupt Register + 0x00000000 + + + CLR_RX_UNDER + Read this register to clear the RX_UNDER interrupt (bit 0) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_RX_OVER + 0x00000048 + Clear RX_OVER Interrupt Register + 0x00000000 + + + CLR_RX_OVER + Read this register to clear the RX_OVER interrupt (bit 1) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_TX_OVER + 0x0000004c + Clear TX_OVER Interrupt Register + 0x00000000 + + + CLR_TX_OVER + Read this register to clear the TX_OVER interrupt (bit 3) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_RD_REQ + 0x00000050 + Clear RD_REQ Interrupt Register + 0x00000000 + + + CLR_RD_REQ + Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_TX_ABRT + 0x00000054 + Clear TX_ABRT Interrupt Register + 0x00000000 + + + CLR_TX_ABRT + Read this register to clear the TX_ABRT interrupt (bit 6) of the IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also releases the TX FIFO from the flushed/reset state, allowing more writes to the TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_RX_DONE + 0x00000058 + Clear RX_DONE Interrupt Register + 0x00000000 + + + CLR_RX_DONE + Read this register to clear the RX_DONE interrupt (bit 7) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_ACTIVITY + 0x0000005c + Clear ACTIVITY Interrupt Register + 0x00000000 + + + CLR_ACTIVITY + Reading this register clears the ACTIVITY interrupt if the I2C is not active anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt bit continues to be set. It is automatically cleared by hardware if the module is disabled and if there is no further activity on the bus. The value read from this register to get status of the ACTIVITY interrupt (bit 8) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_STOP_DET + 0x00000060 + Clear STOP_DET Interrupt Register + 0x00000000 + + + CLR_STOP_DET + Read this register to clear the STOP_DET interrupt (bit 9) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_START_DET + 0x00000064 + Clear START_DET Interrupt Register + 0x00000000 + + + CLR_START_DET + Read this register to clear the START_DET interrupt (bit 10) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_GEN_CALL + 0x00000068 + Clear GEN_CALL Interrupt Register + 0x00000000 + + + CLR_GEN_CALL + Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_ENABLE + 0x0000006c + I2C Enable Register + 0x00000000 + + + TX_CMD_BLOCK + In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus automatically, as soon as the first data is available in the Tx FIFO. Note: To block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT + [2:2] + read-write + + + NOT_BLOCKED + 0 + Tx Command execution not blocked + + + BLOCKED + 1 + Tx Command execution blocked + + + + + ABORT + When set, the controller initiates the transfer abort. - 0: ABORT not initiated or ABORT done - 1: ABORT operation in progress The software can abort the I2C transfer in master mode by setting this bit. The software can set this bit only when ENABLE is already set; otherwise, the controller ignores any write to ABORT bit. The software cannot clear the ABORT bit once set. In response to an ABORT, the controller issues a STOP and flushes the Tx FIFO after completing the current transfer, then sets the TX_ABORT interrupt after the abort operation. The ABORT bit is cleared automatically after the abort operation. + + For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C Transfers'. + + Reset value: 0x0 + [1:1] + read-write + + + DISABLE + 0 + ABORT operation not in progress + + + ENABLED + 1 + ABORT operation in progress + + + + + ENABLE + Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable DW_apb_i2c while it is active. However, it is important that care be taken to ensure that DW_apb_i2c is disabled properly. A recommended procedure is described in 'Disabling DW_apb_i2c'. + + When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get flushed. - Status bits in the IC_INTR_STAT register are still active until DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well as deletes the contents of the transmit buffer after the current transfer is complete. If the module is receiving, the DW_apb_i2c stops the current transfer at the end of the current byte and does not acknowledge the transfer. + + In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to asynchronous (1), there is a two ic_clk delay when enabling or disabling the DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to 'Disabling DW_apb_i2c' + + Reset value: 0x0 + [0:0] + read-write + + + DISABLED + 0 + I2C is disabled + + + ENABLED + 1 + I2C is enabled + + + + + + + IC_STATUS + 0x00000070 + I2C Status Register + + This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt. + + When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 + 0x00000006 + + + SLV_ACTIVITY + Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the Slave part of DW_apb_i2c is Active Reset value: 0x0 + [6:6] + read-only + + + IDLE + 0 + Slave is idle + + + ACTIVE + 1 + Slave not idle + + + + + MST_ACTIVITY + Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is the OR of SLV_ACTIVITY and MST_ACTIVITY bits. + + Reset value: 0x0 + [5:5] + read-only + + + IDLE + 0 + Master is idle + + + ACTIVE + 1 + Master not idle + + + + + RFF + Receive FIFO Completely Full. When the receive FIFO is completely full, this bit is set. When the receive FIFO contains one or more empty location, this bit is cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: 0x0 + [4:4] + read-only + + + NOT_FULL + 0 + Rx FIFO not full + + + FULL + 1 + Rx FIFO is full + + + + + RFNE + Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is empty - 1: Receive FIFO is not empty Reset value: 0x0 + [3:3] + read-only + + + EMPTY + 0 + Rx FIFO is empty + + + NOT_EMPTY + 1 + Rx FIFO not empty + + + + + TFE + Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this bit is set. When it contains one or more valid entries, this bit is cleared. This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - 1: Transmit FIFO is empty Reset value: 0x1 + [2:2] + read-only + + + NON_EMPTY + 0 + Tx FIFO not empty + + + EMPTY + 1 + Tx FIFO is empty + + + + + TFNF + Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: Transmit FIFO is not full Reset value: 0x1 + [1:1] + read-only + + + FULL + 0 + Tx FIFO is full + + + NOT_FULL + 1 + Tx FIFO not full + + + + + ACTIVITY + I2C Activity Status. Reset value: 0x0 + [0:0] + read-only + + + INACTIVE + 0 + I2C is idle + + + ACTIVE + 1 + I2C is active + + + + + + + IC_TXFLR + 0x00000074 + I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO. + 0x00000000 + + + TXFLR + Transmit FIFO Level. Contains the number of valid data entries in the transmit FIFO. + + Reset value: 0x0 + [4:0] + read-only + + + + + IC_RXFLR + 0x00000078 + I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO. + 0x00000000 + + + RXFLR + Receive FIFO Level. Contains the number of valid data entries in the receive FIFO. + + Reset value: 0x0 + [4:0] + read-only + + + + + IC_SDA_HOLD + 0x0000007c + I2C SDA Hold Time Length Register + + The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW). + + The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode. + + Writes to this register succeed only when IC_ENABLE[0]=0. + + The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented. + + The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles. + 0x00000001 + + + IC_SDA_RX_HOLD + Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a receiver. + + Reset value: IC_DEFAULT_SDA_HOLD[23:16]. + [23:16] + read-write + + + IC_SDA_TX_HOLD + Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a transmitter. + + Reset value: IC_DEFAULT_SDA_HOLD[15:0]. + [15:0] + read-write + + + + + IC_TX_ABRT_SOURCE + 0x00000080 + I2C Transmit Abort Source Register + + This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). + + Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted. + 0x00000000 + + + TX_FLUSH_CNT + This field indicates the number of Tx FIFO Data Commands which are flushed due to TX_ABRT interrupt. It is cleared whenever I2C is disabled. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + [31:23] + read-only + + + ABRT_USER_ABRT + This is a master-mode-only bit. Master has detected the transfer abort (IC_ENABLE[1]) + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter + [16:16] + read-only + + + ABRT_USER_ABRT_VOID + 0 + Transfer abort detected by master- scenario not present + + + ABRT_USER_ABRT_GENERATED + 1 + Transfer abort detected by master + + + + + ABRT_SLVRD_INTX + 1: When the processor side responds to a slave mode request for data to be transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD register. + + Reset value: 0x0 + + Role of DW_apb_i2c: Slave-Transmitter + [15:15] + read-only + + + ABRT_SLVRD_INTX_VOID + 0 + Slave trying to transmit to remote master in read mode- scenario not present + + + ABRT_SLVRD_INTX_GENERATED + 1 + Slave trying to transmit to remote master in read mode + + + + + ABRT_SLV_ARBLOST + This field indicates that a Slave has lost the bus while transmitting data to a remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though the slave never 'owns' the bus, something could go wrong on the bus. This is a fail safe check. For instance, during a data transmission at the low-to-high transition of SCL, if what is on the data bus is not what is supposed to be transmitted, then DW_apb_i2c no longer own the bus. + + Reset value: 0x0 + + Role of DW_apb_i2c: Slave-Transmitter + [14:14] + read-only + + + ABRT_SLV_ARBLOST_VOID + 0 + Slave lost arbitration to remote master- scenario not present + + + ABRT_SLV_ARBLOST_GENERATED + 1 + Slave lost arbitration to remote master + + + + + ABRT_SLVFLUSH_TXFIFO + This field specifies that the Slave has received a read command and some data exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data in TX FIFO. + + Reset value: 0x0 + + Role of DW_apb_i2c: Slave-Transmitter + [13:13] + read-only + + + ABRT_SLVFLUSH_TXFIFO_VOID + 0 + Slave flushes existing data in TX-FIFO upon getting read command- scenario not present + + + ABRT_SLVFLUSH_TXFIFO_GENERATED + 1 + Slave flushes existing data in TX-FIFO upon getting read command + + + + + ARB_LOST + This field specifies that the Master has lost arbitration, or if IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost arbitration. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + [12:12] + read-only + + + ABRT_LOST_VOID + 0 + Master or Slave-Transmitter lost arbitration- scenario not present + + + ABRT_LOST_GENERATED + 1 + Master or Slave-Transmitter lost arbitration + + + + + ABRT_MASTER_DIS + This field indicates that the User tries to initiate a Master operation with the Master mode disabled. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + [11:11] + read-only + + + ABRT_MASTER_DIS_VOID + 0 + User initiating master operation when MASTER disabled- scenario not present + + + ABRT_MASTER_DIS_GENERATED + 1 + User initiating master operation when MASTER disabled + + + + + ABRT_10B_RD_NORSTRT + This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the master sends a read command in 10-bit addressing mode. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Receiver + [10:10] + read-only + + + ABRT_10B_RD_VOID + 0 + Master not trying to read in 10Bit addressing mode when RESTART disabled + + + ABRT_10B_RD_GENERATED + 1 + Master trying to read in 10Bit addressing mode when RESTART disabled + + + + + ABRT_SBYTE_NORSTRT + To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 clears for one cycle and then gets reasserted. When this field is set to 1, the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to send a START Byte. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master + [9:9] + read-only + + + ABRT_SBYTE_NORSTRT_VOID + 0 + User trying to send START byte when RESTART disabled- scenario not present + + + ABRT_SBYTE_NORSTRT_GENERATED + 1 + User trying to send START byte when RESTART disabled + + + + + ABRT_HS_NORSTRT + This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to use the master to transfer data in High Speed mode. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + [8:8] + read-only + + + ABRT_HS_NORSTRT_VOID + 0 + User trying to switch Master to HS mode when RESTART disabled- scenario not present + + + ABRT_HS_NORSTRT_GENERATED + 1 + User trying to switch Master to HS mode when RESTART disabled + + + + + ABRT_SBYTE_ACKDET + This field indicates that the Master has sent a START Byte and the START Byte was acknowledged (wrong behavior). + + Reset value: 0x0 + + Role of DW_apb_i2c: Master + [7:7] + read-only + + + ABRT_SBYTE_ACKDET_VOID + 0 + ACK detected for START byte- scenario not present + + + ABRT_SBYTE_ACKDET_GENERATED + 1 + ACK detected for START byte + + + + + ABRT_HS_ACKDET + This field indicates that the Master is in High Speed mode and the High Speed Master code was acknowledged (wrong behavior). + + Reset value: 0x0 + + Role of DW_apb_i2c: Master + [6:6] + read-only + + + ABRT_HS_ACK_VOID + 0 + HS Master code ACKed in HS Mode- scenario not present + + + ABRT_HS_ACK_GENERATED + 1 + HS Master code ACKed in HS Mode + + + + + ABRT_GCALL_READ + This field indicates that DW_apb_i2c in the master mode has sent a General Call but the user programmed the byte following the General Call to be a read from the bus (IC_DATA_CMD[9] is set to 1). + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter + [5:5] + read-only + + + ABRT_GCALL_READ_VOID + 0 + GCALL is followed by read from bus-scenario not present + + + ABRT_GCALL_READ_GENERATED + 1 + GCALL is followed by read from bus + + + + + ABRT_GCALL_NOACK + This field indicates that DW_apb_i2c in master mode has sent a General Call and no slave on the bus acknowledged the General Call. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter + [4:4] + read-only + + + ABRT_GCALL_NOACK_VOID + 0 + GCALL not ACKed by any slave-scenario not present + + + ABRT_GCALL_NOACK_GENERATED + 1 + GCALL not ACKed by any slave + + + + + ABRT_TXDATA_NOACK + This field indicates the master-mode only bit. When the master receives an acknowledgement for the address, but when it sends data byte(s) following the address, it did not receive an acknowledge from the remote slave(s). + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter + [3:3] + read-only + + + ABRT_TXDATA_NOACK_VOID + 0 + Transmitted data non-ACKed by addressed slave-scenario not present + + + ABRT_TXDATA_NOACK_GENERATED + 1 + Transmitted data not ACKed by addressed slave + + + + + ABRT_10ADDR2_NOACK + This field indicates that the Master is in 10-bit address mode and that the second address byte of the 10-bit address was not acknowledged by any slave. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + [2:2] + read-only + + + INACTIVE + 0 + This abort is not generated + + + ACTIVE + 1 + Byte 2 of 10Bit Address not ACKed by any slave + + + + + ABRT_10ADDR1_NOACK + This field indicates that the Master is in 10-bit address mode and the first 10-bit address byte was not acknowledged by any slave. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + [1:1] + read-only + + + INACTIVE + 0 + This abort is not generated + + + ACTIVE + 1 + Byte 1 of 10Bit Address not ACKed by any slave + + + + + ABRT_7B_ADDR_NOACK + This field indicates that the Master is in 7-bit addressing mode and the address sent was not acknowledged by any slave. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + [0:0] + read-only + + + INACTIVE + 0 + This abort is not generated + + + ACTIVE + 1 + This abort is generated because of NOACK for 7-bit address + + + + + + + IC_SLV_DATA_NACK_ONLY + 0x00000084 + Generate Slave Data NACK Register + + The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect. + + A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit. + 0x00000000 + + + NACK + Generate NACK. This NACK generation only occurs when DW_apb_i2c is a slave-receiver. If this register is set to a value of 1, it can only generate a NACK after a data byte is received; hence, the data transfer is aborted and the data received is not pushed to the receive buffer. + + When the register is set to a value of 0, it generates NACK/ACK, depending on normal criteria. - 1: generate NACK after data byte received - 0: generate NACK/ACK normally Reset value: 0x0 + [0:0] + read-write + + + DISABLED + 0 + Slave receiver generates NACK normally + + + ENABLED + 1 + Slave receiver generates NACK upon data reception only + + + + + + + IC_DMA_CR + 0x00000088 + DMA Control Register + + The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE. + 0x00000000 + + + TDMAE + Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. Reset value: 0x0 + [1:1] + read-write + + + DISABLED + 0 + transmit FIFO DMA channel disabled + + + ENABLED + 1 + Transmit FIFO DMA channel enabled + + + + + RDMAE + Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. Reset value: 0x0 + [0:0] + read-write + + + DISABLED + 0 + Receive FIFO DMA channel disabled + + + ENABLED + 1 + Receive FIFO DMA channel enabled + + + + + + + IC_DMA_TDLR + 0x0000008c + DMA Transmit Data Level Register + 0x00000000 + + + DMATDL + Transmit Data Level. This bit field controls the level at which a DMA request is made by the transmit logic. It is equal to the watermark level; that is, the dma_tx_req signal is generated when the number of valid data entries in the transmit FIFO is equal to or below this field value, and TDMAE = 1. + + Reset value: 0x0 + [3:0] + read-write + + + + + IC_DMA_RDLR + 0x00000090 + I2C Receive Data Level Register + 0x00000000 + + + DMARDL + Receive Data Level. This bit field controls the level at which a DMA request is made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req is generated when the number of valid data entries in the receive FIFO is equal to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is 0, then dma_rx_req is asserted when 1 or more data entries are present in the receive FIFO. + + Reset value: 0x0 + [3:0] + read-write + + + + + IC_SDA_SETUP + 0x00000094 + I2C SDA Setup Register + + This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2. + + Writes to this register succeed only when IC_ENABLE[0] = 0. + + Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter. + 0x00000064 + + + SDA_SETUP + SDA Setup. It is recommended that if the required delay is 1000ns, then for an ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. IC_SDA_SETUP must be programmed with a minimum value of 2. + [7:0] + read-write + + + + + IC_ACK_GENERAL_CALL + 0x00000098 + I2C ACK General Call Register + + The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address. + + This register is applicable only when the DW_apb_i2c is in slave mode. + 0x00000001 + + + ACK_GEN_CALL + ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with a NACK (by negating ic_data_oe). + [0:0] + read-write + + + DISABLED + 0 + Generate NACK for a General Call + + + ENABLED + 1 + Generate ACK for a General Call + + + + + + + IC_ENABLE_STATUS + 0x0000009c + I2C Enable Status Register + + The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled. + + If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1. + + If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'. + + Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities. + 0x00000000 + + + SLV_RX_DATA_LOST + Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has been aborted with at least one data byte received from an I2C transfer due to the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed to have been actively engaged in an aborted I2C transfer (with matching address) and the data phase of the I2C transfer has been entered, even though a data byte has been responded with a NACK. + + Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit is also set to 1. + + When read as 0, DW_apb_i2c is deemed to have been disabled without being actively involved in the data phase of a Slave-Receiver transfer. + + Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. + + Reset value: 0x0 + [2:2] + read-only + + + INACTIVE + 0 + Slave RX Data is not lost + + + ACTIVE + 1 + Slave RX Data is lost + + + + + SLV_DISABLED_WHILE_BUSY + Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential or active Slave operation has been aborted due to the setting bit 0 of the IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the IC_ENABLE register while: + + (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation from a remote master; + + OR, + + (b) address and data bytes of the Slave-Receiver operation from a remote master. + + When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an I2C transfer, irrespective of whether the I2C address matches the slave address set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before IC_ENABLE is set to 0 but has not taken effect. + + Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit will also be set to 1. + + When read as 0, DW_apb_i2c is deemed to have been disabled when there is master activity, or when the I2C bus is idle. + + Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. + + Reset value: 0x0 + [1:1] + read-only + + + INACTIVE + 0 + Slave is disabled when it is idle + + + ACTIVE + 1 + Slave is disabled when it is active + + + + + IC_EN + ic_en Status. This bit always reflects the value driven on the output port ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely read this bit anytime. When this bit is read as 0, the CPU can safely read SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1). + + Reset value: 0x0 + [0:0] + read-only + + + DISABLED + 0 + I2C disabled + + + ENABLED + 1 + I2C enabled + + + + + + + IC_FS_SPKLEN + 0x000000a0 + I2C SS, FS or FM+ spike suppression limit + + This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1. + 0x00000007 + + + IC_FS_SPKLEN + This register must be set before any I2C bus transaction can take place to ensure stable operation. This register sets the duration, measured in ic_clk cycles, of the longest spike in the SCL or SDA lines that will be filtered out by the spike suppression logic. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 1; hardware prevents values less than this being written, and if attempted results in 1 being set. or more information, refer to 'Spike Suppression'. + [7:0] + read-write + + + + + IC_CLR_RESTART_DET + 0x000000a8 + Clear RESTART_DET Interrupt Register + 0x00000000 + + + CLR_RESTART_DET + Read this register to clear the RESTART_DET interrupt (bit 12) of IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_COMP_PARAM_1 + 0x000000f4 + Component Parameter Register 1 + + Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters + 0x00000000 + + + TX_BUFFER_DEPTH + TX Buffer Depth = 16 + [23:16] + read-only + + + RX_BUFFER_DEPTH + RX Buffer Depth = 16 + [15:8] + read-only + + + ADD_ENCODED_PARAMS + Encoded parameters not visible + [7:7] + read-only + + + HAS_DMA + DMA handshaking signals are enabled + [6:6] + read-only + + + INTR_IO + COMBINED Interrupt outputs + [5:5] + read-only + + + HC_COUNT_VALUES + Programmable count values for each mode. + [4:4] + read-only + + + MAX_SPEED_MODE + MAX SPEED MODE = FAST MODE + [3:2] + read-only + + + APB_DATA_WIDTH + APB data bus width is 32 bits + [1:0] + read-only + + + + + IC_COMP_VERSION + 0x000000f8 + I2C Component Version Register + 0x3230312a + + + IC_COMP_VERSION + [31:0] + read-only + + + + + IC_COMP_TYPE + 0x000000fc + I2C Component Type Register + 0x44570140 + + + IC_COMP_TYPE + Designware Component Type number = 0x44_57_01_40. This assigned unique hex value is constant and is derived from the two ASCII letters 'DW' followed by a 16-bit unsigned number. + [31:0] + read-only + + + + + + + I2C1 + 0x40048000 + + I2C1_IRQ + 24 + + + + SPI0 + 0x4003c000 + + 0 + 4096 + registers + + + SPI0_IRQ + 18 + + + + SSPCR0 + 0x00000000 + Control register 0, SSPCR0 on page 3-4 + 0x00000000 + + + SCR + Serial clock rate. The value SCR is used to generate the transmit and receive bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and SCR is a value from 0-255. + [15:8] + read-write + + + SPH + SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + [7:7] + read-write + + + SPO + SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + [6:6] + read-write + + + FRF + Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame format. 10 National Microwire frame format. 11 Reserved, undefined operation. + [5:4] + read-write + + + DSS + Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. 1110 15-bit data. 1111 16-bit data. + [3:0] + read-write + + + + + SSPCR1 + 0x00000004 + Control register 1, SSPCR1 on page 3-5 + 0x00000000 + + + SOD + Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast a message to all slaves in the system while ensuring that only one slave drives data onto its serial output line. In such systems the RXD lines from multiple slaves could be tied together. To operate in such systems, the SOD bit can be set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD output in slave mode. + [3:3] + read-write + + + MS + Master or slave mode select. This bit can be modified only when the PrimeCell SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device configured as slave. + [2:2] + read-write + + + SSE + Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation enabled. + [1:1] + read-write + + + LBM + Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit serial shifter is connected to input of receive serial shifter internally. + [0:0] + read-write + + + + + SSPDR + 0x00000008 + Data register, SSPDR on page 3-6 + 0x00000000 + + + DATA + Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must right-justify data when the PrimeCell SSP is programmed for a data size that is less than 16 bits. Unused bits at the top are ignored by transmit logic. The receive logic automatically right-justifies. + [15:0] + read-write + modify + + + + + SSPSR + 0x0000000c + Status register, SSPSR on page 3-7 + 0x00000003 + + + BSY + PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting and/or receiving a frame or the transmit FIFO is not empty. + [4:4] + read-only + + + RFF + Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. + [3:3] + read-only + + + RNE + Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not empty. + [2:2] + read-only + + + TNF + Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not full. + [1:1] + read-only + + + TFE + Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. + [0:0] + read-only + + + + + SSPCPSR + 0x00000010 + Clock prescale register, SSPCPSR on page 3-8 + 0x00000000 + + + CPSDVSR + Clock prescale divisor. Must be an even number from 2-254, depending on the frequency of SSPCLK. The least significant bit always returns zero on reads. + [7:0] + read-write + + + + + SSPIMSC + 0x00000014 + Interrupt mask set or clear register, SSPIMSC on page 3-9 + 0x00000000 + + + TXIM + Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is not masked. + [3:3] + read-write + + + RXIM + Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not masked. + [2:2] + read-write + + + RTIM + Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior to timeout period interrupt is not masked. + [1:1] + read-write + + + RORIM + Receive overrun interrupt mask: 0 Receive FIFO written to while full condition interrupt is masked. 1 Receive FIFO written to while full condition interrupt is not masked. + [0:0] + read-write + + + + + SSPRIS + 0x00000018 + Raw interrupt status register, SSPRIS on page 3-10 + 0x00000008 + + + TXRIS + Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt + [3:3] + read-only + + + RXRIS + Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt + [2:2] + read-only + + + RTRIS + Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt + [1:1] + read-only + + + RORRIS + Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt + [0:0] + read-only + + + + + SSPMIS + 0x0000001c + Masked interrupt status register, SSPMIS on page 3-11 + 0x00000000 + + + TXMIS + Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt + [3:3] + read-only + + + RXMIS + Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt + [2:2] + read-only + + + RTMIS + Gives the receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt + [1:1] + read-only + + + RORMIS + Gives the receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt + [0:0] + read-only + + + + + SSPICR + 0x00000020 + Interrupt clear register, SSPICR on page 3-11 + 0x00000000 + + + RTIC + Clears the SSPRTINTR interrupt + [1:1] + read-write + oneToClear + + + RORIC + Clears the SSPRORINTR interrupt + [0:0] + read-write + oneToClear + + + + + SSPDMACR + 0x00000024 + DMA control register, SSPDMACR on page 3-12 + 0x00000000 + + + TXDMAE + Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + [1:1] + read-write + + + RXDMAE + Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is enabled. + [0:0] + read-write + + + + + SSPPERIPHID0 + 0x00000fe0 + Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + 0x00000022 + + + PARTNUMBER0 + These bits read back as 0x22 + [7:0] + read-only + + + + + SSPPERIPHID1 + 0x00000fe4 + Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + 0x00000010 + + + DESIGNER0 + These bits read back as 0x1 + [7:4] + read-only + + + PARTNUMBER1 + These bits read back as 0x0 + [3:0] + read-only + + + + + SSPPERIPHID2 + 0x00000fe8 + Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + 0x00000034 + + + REVISION + These bits return the peripheral revision + [7:4] + read-only + + + DESIGNER1 + These bits read back as 0x4 + [3:0] + read-only + + + + + SSPPERIPHID3 + 0x00000fec + Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + 0x00000000 + + + CONFIGURATION + These bits read back as 0x00 + [7:0] + read-only + + + + + SSPPCELLID0 + 0x00000ff0 + PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + 0x0000000d + + + SSPPCELLID0 + These bits read back as 0x0D + [7:0] + read-only + + + + + SSPPCELLID1 + 0x00000ff4 + PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + 0x000000f0 + + + SSPPCELLID1 + These bits read back as 0xF0 + [7:0] + read-only + + + + + SSPPCELLID2 + 0x00000ff8 + PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + 0x00000005 + + + SSPPCELLID2 + These bits read back as 0x05 + [7:0] + read-only + + + + + SSPPCELLID3 + 0x00000ffc + PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + 0x000000b1 + + + SSPPCELLID3 + These bits read back as 0xB1 + [7:0] + read-only + + + + + + + SPI1 + 0x40040000 + + SPI1_IRQ + 19 + + + + PIO0 + Programmable IO block + 0x50200000 + + 0 + 324 + registers + + + PIO0_IRQ_0 + 7 + + + PIO0_IRQ_1 + 8 + + + + CTRL + 0x00000000 + PIO control register + 0x00000000 + + + CLKDIV_RESTART + Restart a state machine's clock divider from an initial phase of 0. Clock dividers are free-running, so once started, their output (including fractional jitter) is completely determined by the integer/fractional divisor configured in SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor are restarted simultaneously, by writing multiple 1 bits to this field, the execution clocks of those state machines will run in precise lockstep. + + Note that setting/clearing SM_ENABLE does not stop the clock divider from running, so once multiple state machines' clocks are synchronised, it is safe to disable/reenable a state machine, whilst keeping the clock dividers in sync. + + Note also that CLKDIV_RESTART can be written to whilst the state machine is running, and this is useful to resynchronise clock dividers after the divisors (SMx_CLKDIV) have been changed on-the-fly. + [11:8] + write-only + + + SM_RESTART + Write 1 to instantly clear internal SM state which may be otherwise difficult to access and will affect future execution. + + Specifically, the following are cleared: input and output shift counters; the contents of the input shift register; the delay counter; the waiting-on-IRQ state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any pin write left asserted due to OUT_STICKY. + + The program counter, the contents of the output shift register and the X/Y scratch registers are not affected. + [7:4] + write-only + + + SM_ENABLE + Enable/disable each of the four state machines by writing 1/0 to each of these four bits. When disabled, a state machine will cease executing instructions, except those written directly to SMx_INSTR by the system. Multiple bits can be set/cleared at once to run/halt multiple state machines simultaneously. + [3:0] + read-write + + + + + FSTAT + 0x00000004 + FIFO status register + 0x0f000f00 + + + TXEMPTY + State machine TX FIFO is empty + [27:24] + read-only + + + TXFULL + State machine TX FIFO is full + [19:16] + read-only + + + RXEMPTY + State machine RX FIFO is empty + [11:8] + read-only + + + RXFULL + State machine RX FIFO is full + [3:0] + read-only + + + + + FDEBUG + 0x00000008 + FIFO debug register + 0x00000000 + + + TXSTALL + State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT with autopull enabled. Write 1 to clear. + [27:24] + read-write + oneToClear + + + TXOVER + TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to clear. Note that write-on-full does not alter the state or contents of the FIFO in any way, but the data that the system attempted to write is dropped, so if this flag is set, your software has quite likely dropped some data on the floor. + [19:16] + read-write + oneToClear + + + RXUNDER + RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to clear. Note that read-on-empty does not perturb the state of the FIFO in any way, but the data returned by reading from an empty FIFO is undefined, so this flag generally only becomes set due to some kind of software error. + [11:8] + read-write + oneToClear + + + RXSTALL + State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO took place, in which case the state machine has dropped data. Write 1 to clear. + [3:0] + read-write + oneToClear + + + + + FLEVEL + 0x0000000c + FIFO levels + 0x00000000 + + + RX3 + [31:28] + read-only + + + TX3 + [27:24] + read-only + + + RX2 + [23:20] + read-only + + + TX2 + [19:16] + read-only + + + RX1 + [15:12] + read-only + + + TX1 + [11:8] + read-only + + + RX0 + [7:4] + read-only + + + TX0 + [3:0] + read-only + + + + + TXF0 + 0x00000010 + Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + 0x00000000 + + + TXF0 + [31:0] + write-only + + + + + TXF1 + 0x00000014 + Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + 0x00000000 + + + TXF1 + [31:0] + write-only + + + + + TXF2 + 0x00000018 + Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + 0x00000000 + + + TXF2 + [31:0] + write-only + + + + + TXF3 + 0x0000001c + Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + 0x00000000 + + + TXF3 + [31:0] + write-only + + + + + RXF0 + 0x00000020 + Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + 0x00000000 + + + RXF0 + [31:0] + read-only + modify + + + + + RXF1 + 0x00000024 + Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + 0x00000000 + + + RXF1 + [31:0] + read-only + modify + + + + + RXF2 + 0x00000028 + Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + 0x00000000 + + + RXF2 + [31:0] + read-only + modify + + + + + RXF3 + 0x0000002c + Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + 0x00000000 + + + RXF3 + [31:0] + read-only + modify + + + + + IRQ + 0x00000030 + State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag. + + Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE. + 0x00000000 + + + IRQ + [7:0] + read-write + oneToClear + + + + + IRQ_FORCE + 0x00000034 + Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. + 0x00000000 + + + IRQ_FORCE + [7:0] + write-only + + + + + INPUT_SYNC_BYPASS + 0x00000038 + There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. + 0 -> input is synchronized (default) + 1 -> synchronizer is bypassed + If in doubt, leave this register as all zeroes. + 0x00000000 + + + INPUT_SYNC_BYPASS + [31:0] + read-write + + + + + DBG_PADOUT + 0x0000003c + Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + 0x00000000 + + + DBG_PADOUT + [31:0] + read-only + + + + + DBG_PADOE + 0x00000040 + Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + 0x00000000 + + + DBG_PADOE + [31:0] + read-only + + + + + DBG_CFGINFO + 0x00000044 + The PIO hardware has some free parameters that may vary between chip products. + These should be provided in the chip datasheet, but are also exposed here. + 0x00000000 + + + IMEM_SIZE + The size of the instruction memory, measured in units of one instruction + [21:16] + read-only + + + SM_COUNT + The number of state machines this PIO instance is equipped with. + [11:8] + read-only + + + FIFO_DEPTH + The depth of the state machine TX/RX FIFOs, measured in words. + Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double + this depth. + [5:0] + read-only + + + + + INSTR_MEM0 + 0x00000048 + Write-only access to instruction memory location 0 + 0x00000000 + + + INSTR_MEM0 + [15:0] + write-only + + + + + INSTR_MEM1 + 0x0000004c + Write-only access to instruction memory location 1 + 0x00000000 + + + INSTR_MEM1 + [15:0] + write-only + + + + + INSTR_MEM2 + 0x00000050 + Write-only access to instruction memory location 2 + 0x00000000 + + + INSTR_MEM2 + [15:0] + write-only + + + + + INSTR_MEM3 + 0x00000054 + Write-only access to instruction memory location 3 + 0x00000000 + + + INSTR_MEM3 + [15:0] + write-only + + + + + INSTR_MEM4 + 0x00000058 + Write-only access to instruction memory location 4 + 0x00000000 + + + INSTR_MEM4 + [15:0] + write-only + + + + + INSTR_MEM5 + 0x0000005c + Write-only access to instruction memory location 5 + 0x00000000 + + + INSTR_MEM5 + [15:0] + write-only + + + + + INSTR_MEM6 + 0x00000060 + Write-only access to instruction memory location 6 + 0x00000000 + + + INSTR_MEM6 + [15:0] + write-only + + + + + INSTR_MEM7 + 0x00000064 + Write-only access to instruction memory location 7 + 0x00000000 + + + INSTR_MEM7 + [15:0] + write-only + + + + + INSTR_MEM8 + 0x00000068 + Write-only access to instruction memory location 8 + 0x00000000 + + + INSTR_MEM8 + [15:0] + write-only + + + + + INSTR_MEM9 + 0x0000006c + Write-only access to instruction memory location 9 + 0x00000000 + + + INSTR_MEM9 + [15:0] + write-only + + + + + INSTR_MEM10 + 0x00000070 + Write-only access to instruction memory location 10 + 0x00000000 + + + INSTR_MEM10 + [15:0] + write-only + + + + + INSTR_MEM11 + 0x00000074 + Write-only access to instruction memory location 11 + 0x00000000 + + + INSTR_MEM11 + [15:0] + write-only + + + + + INSTR_MEM12 + 0x00000078 + Write-only access to instruction memory location 12 + 0x00000000 + + + INSTR_MEM12 + [15:0] + write-only + + + + + INSTR_MEM13 + 0x0000007c + Write-only access to instruction memory location 13 + 0x00000000 + + + INSTR_MEM13 + [15:0] + write-only + + + + + INSTR_MEM14 + 0x00000080 + Write-only access to instruction memory location 14 + 0x00000000 + + + INSTR_MEM14 + [15:0] + write-only + + + + + INSTR_MEM15 + 0x00000084 + Write-only access to instruction memory location 15 + 0x00000000 + + + INSTR_MEM15 + [15:0] + write-only + + + + + INSTR_MEM16 + 0x00000088 + Write-only access to instruction memory location 16 + 0x00000000 + + + INSTR_MEM16 + [15:0] + write-only + + + + + INSTR_MEM17 + 0x0000008c + Write-only access to instruction memory location 17 + 0x00000000 + + + INSTR_MEM17 + [15:0] + write-only + + + + + INSTR_MEM18 + 0x00000090 + Write-only access to instruction memory location 18 + 0x00000000 + + + INSTR_MEM18 + [15:0] + write-only + + + + + INSTR_MEM19 + 0x00000094 + Write-only access to instruction memory location 19 + 0x00000000 + + + INSTR_MEM19 + [15:0] + write-only + + + + + INSTR_MEM20 + 0x00000098 + Write-only access to instruction memory location 20 + 0x00000000 + + + INSTR_MEM20 + [15:0] + write-only + + + + + INSTR_MEM21 + 0x0000009c + Write-only access to instruction memory location 21 + 0x00000000 + + + INSTR_MEM21 + [15:0] + write-only + + + + + INSTR_MEM22 + 0x000000a0 + Write-only access to instruction memory location 22 + 0x00000000 + + + INSTR_MEM22 + [15:0] + write-only + + + + + INSTR_MEM23 + 0x000000a4 + Write-only access to instruction memory location 23 + 0x00000000 + + + INSTR_MEM23 + [15:0] + write-only + + + + + INSTR_MEM24 + 0x000000a8 + Write-only access to instruction memory location 24 + 0x00000000 + + + INSTR_MEM24 + [15:0] + write-only + + + + + INSTR_MEM25 + 0x000000ac + Write-only access to instruction memory location 25 + 0x00000000 + + + INSTR_MEM25 + [15:0] + write-only + + + + + INSTR_MEM26 + 0x000000b0 + Write-only access to instruction memory location 26 + 0x00000000 + + + INSTR_MEM26 + [15:0] + write-only + + + + + INSTR_MEM27 + 0x000000b4 + Write-only access to instruction memory location 27 + 0x00000000 + + + INSTR_MEM27 + [15:0] + write-only + + + + + INSTR_MEM28 + 0x000000b8 + Write-only access to instruction memory location 28 + 0x00000000 + + + INSTR_MEM28 + [15:0] + write-only + + + + + INSTR_MEM29 + 0x000000bc + Write-only access to instruction memory location 29 + 0x00000000 + + + INSTR_MEM29 + [15:0] + write-only + + + + + INSTR_MEM30 + 0x000000c0 + Write-only access to instruction memory location 30 + 0x00000000 + + + INSTR_MEM30 + [15:0] + write-only + + + + + INSTR_MEM31 + 0x000000c4 + Write-only access to instruction memory location 31 + 0x00000000 + + + INSTR_MEM31 + [15:0] + write-only + + + + + SM0_CLKDIV + 0x000000c8 + Clock divisor register for state machine 0 + Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + 0x00010000 + + + INT + Effective frequency is sysclk/(int + frac/256). + Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + [31:16] + read-write + + + FRAC + Fractional part of clock divisor + [15:8] + read-write + + + + + SM0_EXECCTRL + 0x000000cc + Execution/behavioural settings for state machine 0 + 0x0001f000 + + + EXEC_STALLED + If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + [31:31] + read-only + + + SIDE_EN + If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + [30:30] + read-write + + + SIDE_PINDIR + If 1, side-set data is asserted to pin directions, instead of pin values + [29:29] + read-write + + + JMP_PIN + The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + [28:24] + read-write + + + OUT_EN_SEL + Which data bit to use for inline OUT enable + [23:19] + read-write + + + INLINE_OUT_EN + If 1, use a bit of OUT data as an auxiliary write enable + When used in conjunction with OUT_STICKY, writes with an enable of 0 will + deassert the latest pin write. This can create useful masking/override behaviour + due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + [18:18] + read-write + + + OUT_STICKY + Continuously assert the most recent OUT/SET to the pins + [17:17] + read-write + + + WRAP_TOP + After reaching this address, execution is wrapped to wrap_bottom. + If the instruction is a jump, and the jump condition is true, the jump takes priority. + [16:12] + read-write + + + WRAP_BOTTOM + After reaching wrap_top, execution is wrapped to this address. + [11:7] + read-write + + + STATUS_SEL + Comparison used for the MOV x, STATUS instruction. + [4:4] + read-write + + + TXLEVEL + 0 + All-ones if TX FIFO level < N, otherwise all-zeroes + + + RXLEVEL + 1 + All-ones if RX FIFO level < N, otherwise all-zeroes + + + + + STATUS_N + Comparison level for the MOV x, STATUS instruction + [3:0] + read-write + + + + + SM0_SHIFTCTRL + 0x000000d0 + Control behaviour of the input/output shift registers for state machine 0 + 0x000c0000 + + + FJOIN_RX + When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + TX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [31:31] + read-write + + + FJOIN_TX + When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + RX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [30:30] + read-write + + + PULL_THRESH + Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + Write 0 for value of 32. + [29:25] + read-write + + + PUSH_THRESH + Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + Write 0 for value of 32. + [24:20] + read-write + + + OUT_SHIFTDIR + 1 = shift out of output shift register to right. 0 = to left. + [19:19] + read-write + + + IN_SHIFTDIR + 1 = shift input shift register to right (data enters from left). 0 = to left. + [18:18] + read-write + + + AUTOPULL + Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + [17:17] + read-write + + + AUTOPUSH + Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + [16:16] + read-write + + + + + SM0_ADDR + 0x000000d4 + Current instruction address of state machine 0 + 0x00000000 + + + SM0_ADDR + [4:0] + read-only + + + + + SM0_INSTR + 0x000000d8 + Read to see the instruction currently addressed by state machine 0's program counter + Write to execute an instruction immediately (including jumps) and then resume execution. + 0x00000000 + + + SM0_INSTR + [15:0] + read-write + + + + + SM0_PINCTRL + 0x000000dc + State machine pin control + 0x14000000 + + + SIDESET_COUNT + The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + [31:29] + read-write + + + SET_COUNT + The number of pins asserted by a SET. In the range 0 to 5 inclusive. + [28:26] + read-write + + + OUT_COUNT + The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + [25:20] + read-write + + + IN_BASE + The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + [19:15] + read-write + + + SIDESET_BASE + The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + [14:10] + read-write + + + SET_BASE + The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + [9:5] + read-write + + + OUT_BASE + The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + [4:0] + read-write + + + + + SM1_CLKDIV + 0x000000e0 + Clock divisor register for state machine 1 + Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + 0x00010000 + + + INT + Effective frequency is sysclk/(int + frac/256). + Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + [31:16] + read-write + + + FRAC + Fractional part of clock divisor + [15:8] + read-write + + + + + SM1_EXECCTRL + 0x000000e4 + Execution/behavioural settings for state machine 1 + 0x0001f000 + + + EXEC_STALLED + If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + [31:31] + read-only + + + SIDE_EN + If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + [30:30] + read-write + + + SIDE_PINDIR + If 1, side-set data is asserted to pin directions, instead of pin values + [29:29] + read-write + + + JMP_PIN + The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + [28:24] + read-write + + + OUT_EN_SEL + Which data bit to use for inline OUT enable + [23:19] + read-write + + + INLINE_OUT_EN + If 1, use a bit of OUT data as an auxiliary write enable + When used in conjunction with OUT_STICKY, writes with an enable of 0 will + deassert the latest pin write. This can create useful masking/override behaviour + due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + [18:18] + read-write + + + OUT_STICKY + Continuously assert the most recent OUT/SET to the pins + [17:17] + read-write + + + WRAP_TOP + After reaching this address, execution is wrapped to wrap_bottom. + If the instruction is a jump, and the jump condition is true, the jump takes priority. + [16:12] + read-write + + + WRAP_BOTTOM + After reaching wrap_top, execution is wrapped to this address. + [11:7] + read-write + + + STATUS_SEL + Comparison used for the MOV x, STATUS instruction. + [4:4] + read-write + + + TXLEVEL + 0 + All-ones if TX FIFO level < N, otherwise all-zeroes + + + RXLEVEL + 1 + All-ones if RX FIFO level < N, otherwise all-zeroes + + + + + STATUS_N + Comparison level for the MOV x, STATUS instruction + [3:0] + read-write + + + + + SM1_SHIFTCTRL + 0x000000e8 + Control behaviour of the input/output shift registers for state machine 1 + 0x000c0000 + + + FJOIN_RX + When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + TX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [31:31] + read-write + + + FJOIN_TX + When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + RX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [30:30] + read-write + + + PULL_THRESH + Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + Write 0 for value of 32. + [29:25] + read-write + + + PUSH_THRESH + Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + Write 0 for value of 32. + [24:20] + read-write + + + OUT_SHIFTDIR + 1 = shift out of output shift register to right. 0 = to left. + [19:19] + read-write + + + IN_SHIFTDIR + 1 = shift input shift register to right (data enters from left). 0 = to left. + [18:18] + read-write + + + AUTOPULL + Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + [17:17] + read-write + + + AUTOPUSH + Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + [16:16] + read-write + + + + + SM1_ADDR + 0x000000ec + Current instruction address of state machine 1 + 0x00000000 + + + SM1_ADDR + [4:0] + read-only + + + + + SM1_INSTR + 0x000000f0 + Read to see the instruction currently addressed by state machine 1's program counter + Write to execute an instruction immediately (including jumps) and then resume execution. + 0x00000000 + + + SM1_INSTR + [15:0] + read-write + + + + + SM1_PINCTRL + 0x000000f4 + State machine pin control + 0x14000000 + + + SIDESET_COUNT + The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + [31:29] + read-write + + + SET_COUNT + The number of pins asserted by a SET. In the range 0 to 5 inclusive. + [28:26] + read-write + + + OUT_COUNT + The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + [25:20] + read-write + + + IN_BASE + The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + [19:15] + read-write + + + SIDESET_BASE + The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + [14:10] + read-write + + + SET_BASE + The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + [9:5] + read-write + + + OUT_BASE + The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + [4:0] + read-write + + + + + SM2_CLKDIV + 0x000000f8 + Clock divisor register for state machine 2 + Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + 0x00010000 + + + INT + Effective frequency is sysclk/(int + frac/256). + Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + [31:16] + read-write + + + FRAC + Fractional part of clock divisor + [15:8] + read-write + + + + + SM2_EXECCTRL + 0x000000fc + Execution/behavioural settings for state machine 2 + 0x0001f000 + + + EXEC_STALLED + If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + [31:31] + read-only + + + SIDE_EN + If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + [30:30] + read-write + + + SIDE_PINDIR + If 1, side-set data is asserted to pin directions, instead of pin values + [29:29] + read-write + + + JMP_PIN + The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + [28:24] + read-write + + + OUT_EN_SEL + Which data bit to use for inline OUT enable + [23:19] + read-write + + + INLINE_OUT_EN + If 1, use a bit of OUT data as an auxiliary write enable + When used in conjunction with OUT_STICKY, writes with an enable of 0 will + deassert the latest pin write. This can create useful masking/override behaviour + due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + [18:18] + read-write + + + OUT_STICKY + Continuously assert the most recent OUT/SET to the pins + [17:17] + read-write + + + WRAP_TOP + After reaching this address, execution is wrapped to wrap_bottom. + If the instruction is a jump, and the jump condition is true, the jump takes priority. + [16:12] + read-write + + + WRAP_BOTTOM + After reaching wrap_top, execution is wrapped to this address. + [11:7] + read-write + + + STATUS_SEL + Comparison used for the MOV x, STATUS instruction. + [4:4] + read-write + + + TXLEVEL + 0 + All-ones if TX FIFO level < N, otherwise all-zeroes + + + RXLEVEL + 1 + All-ones if RX FIFO level < N, otherwise all-zeroes + + + + + STATUS_N + Comparison level for the MOV x, STATUS instruction + [3:0] + read-write + + + + + SM2_SHIFTCTRL + 0x00000100 + Control behaviour of the input/output shift registers for state machine 2 + 0x000c0000 + + + FJOIN_RX + When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + TX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [31:31] + read-write + + + FJOIN_TX + When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + RX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [30:30] + read-write + + + PULL_THRESH + Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + Write 0 for value of 32. + [29:25] + read-write + + + PUSH_THRESH + Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + Write 0 for value of 32. + [24:20] + read-write + + + OUT_SHIFTDIR + 1 = shift out of output shift register to right. 0 = to left. + [19:19] + read-write + + + IN_SHIFTDIR + 1 = shift input shift register to right (data enters from left). 0 = to left. + [18:18] + read-write + + + AUTOPULL + Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + [17:17] + read-write + + + AUTOPUSH + Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + [16:16] + read-write + + + + + SM2_ADDR + 0x00000104 + Current instruction address of state machine 2 + 0x00000000 + + + SM2_ADDR + [4:0] + read-only + + + + + SM2_INSTR + 0x00000108 + Read to see the instruction currently addressed by state machine 2's program counter + Write to execute an instruction immediately (including jumps) and then resume execution. + 0x00000000 + + + SM2_INSTR + [15:0] + read-write + + + + + SM2_PINCTRL + 0x0000010c + State machine pin control + 0x14000000 + + + SIDESET_COUNT + The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + [31:29] + read-write + + + SET_COUNT + The number of pins asserted by a SET. In the range 0 to 5 inclusive. + [28:26] + read-write + + + OUT_COUNT + The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + [25:20] + read-write + + + IN_BASE + The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + [19:15] + read-write + + + SIDESET_BASE + The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + [14:10] + read-write + + + SET_BASE + The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + [9:5] + read-write + + + OUT_BASE + The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + [4:0] + read-write + + + + + SM3_CLKDIV + 0x00000110 + Clock divisor register for state machine 3 + Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + 0x00010000 + + + INT + Effective frequency is sysclk/(int + frac/256). + Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + [31:16] + read-write + + + FRAC + Fractional part of clock divisor + [15:8] + read-write + + + + + SM3_EXECCTRL + 0x00000114 + Execution/behavioural settings for state machine 3 + 0x0001f000 + + + EXEC_STALLED + If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + [31:31] + read-only + + + SIDE_EN + If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + [30:30] + read-write + + + SIDE_PINDIR + If 1, side-set data is asserted to pin directions, instead of pin values + [29:29] + read-write + + + JMP_PIN + The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + [28:24] + read-write + + + OUT_EN_SEL + Which data bit to use for inline OUT enable + [23:19] + read-write + + + INLINE_OUT_EN + If 1, use a bit of OUT data as an auxiliary write enable + When used in conjunction with OUT_STICKY, writes with an enable of 0 will + deassert the latest pin write. This can create useful masking/override behaviour + due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + [18:18] + read-write + + + OUT_STICKY + Continuously assert the most recent OUT/SET to the pins + [17:17] + read-write + + + WRAP_TOP + After reaching this address, execution is wrapped to wrap_bottom. + If the instruction is a jump, and the jump condition is true, the jump takes priority. + [16:12] + read-write + + + WRAP_BOTTOM + After reaching wrap_top, execution is wrapped to this address. + [11:7] + read-write + + + STATUS_SEL + Comparison used for the MOV x, STATUS instruction. + [4:4] + read-write + + + TXLEVEL + 0 + All-ones if TX FIFO level < N, otherwise all-zeroes + + + RXLEVEL + 1 + All-ones if RX FIFO level < N, otherwise all-zeroes + + + + + STATUS_N + Comparison level for the MOV x, STATUS instruction + [3:0] + read-write + + + + + SM3_SHIFTCTRL + 0x00000118 + Control behaviour of the input/output shift registers for state machine 3 + 0x000c0000 + + + FJOIN_RX + When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + TX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [31:31] + read-write + + + FJOIN_TX + When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + RX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [30:30] + read-write + + + PULL_THRESH + Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + Write 0 for value of 32. + [29:25] + read-write + + + PUSH_THRESH + Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + Write 0 for value of 32. + [24:20] + read-write + + + OUT_SHIFTDIR + 1 = shift out of output shift register to right. 0 = to left. + [19:19] + read-write + + + IN_SHIFTDIR + 1 = shift input shift register to right (data enters from left). 0 = to left. + [18:18] + read-write + + + AUTOPULL + Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + [17:17] + read-write + + + AUTOPUSH + Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + [16:16] + read-write + + + + + SM3_ADDR + 0x0000011c + Current instruction address of state machine 3 + 0x00000000 + + + SM3_ADDR + [4:0] + read-only + + + + + SM3_INSTR + 0x00000120 + Read to see the instruction currently addressed by state machine 3's program counter + Write to execute an instruction immediately (including jumps) and then resume execution. + 0x00000000 + + + SM3_INSTR + [15:0] + read-write + + + + + SM3_PINCTRL + 0x00000124 + State machine pin control + 0x14000000 + + + SIDESET_COUNT + The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + [31:29] + read-write + + + SET_COUNT + The number of pins asserted by a SET. In the range 0 to 5 inclusive. + [28:26] + read-write + + + OUT_COUNT + The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + [25:20] + read-write + + + IN_BASE + The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + [19:15] + read-write + + + SIDESET_BASE + The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + [14:10] + read-write + + + SET_BASE + The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + [9:5] + read-write + + + OUT_BASE + The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + [4:0] + read-write + + + + + INTR + 0x00000128 + Raw Interrupts + 0x00000000 + + + SM3 + [11:11] + read-only + + + SM2 + [10:10] + read-only + + + SM1 + [9:9] + read-only + + + SM0 + [8:8] + read-only + + + SM3_TXNFULL + [7:7] + read-only + + + SM2_TXNFULL + [6:6] + read-only + + + SM1_TXNFULL + [5:5] + read-only + + + SM0_TXNFULL + [4:4] + read-only + + + SM3_RXNEMPTY + [3:3] + read-only + + + SM2_RXNEMPTY + [2:2] + read-only + + + SM1_RXNEMPTY + [1:1] + read-only + + + SM0_RXNEMPTY + [0:0] + read-only + + + + + IRQ0_INTE + 0x0000012c + Interrupt Enable for irq0 + 0x00000000 + + + SM3 + [11:11] + read-write + + + SM2 + [10:10] + read-write + + + SM1 + [9:9] + read-write + + + SM0 + [8:8] + read-write + + + SM3_TXNFULL + [7:7] + read-write + + + SM2_TXNFULL + [6:6] + read-write + + + SM1_TXNFULL + [5:5] + read-write + + + SM0_TXNFULL + [4:4] + read-write + + + SM3_RXNEMPTY + [3:3] + read-write + + + SM2_RXNEMPTY + [2:2] + read-write + + + SM1_RXNEMPTY + [1:1] + read-write + + + SM0_RXNEMPTY + [0:0] + read-write + + + + + IRQ0_INTF + 0x00000130 + Interrupt Force for irq0 + 0x00000000 + + + SM3 + [11:11] + read-write + + + SM2 + [10:10] + read-write + + + SM1 + [9:9] + read-write + + + SM0 + [8:8] + read-write + + + SM3_TXNFULL + [7:7] + read-write + + + SM2_TXNFULL + [6:6] + read-write + + + SM1_TXNFULL + [5:5] + read-write + + + SM0_TXNFULL + [4:4] + read-write + + + SM3_RXNEMPTY + [3:3] + read-write + + + SM2_RXNEMPTY + [2:2] + read-write + + + SM1_RXNEMPTY + [1:1] + read-write + + + SM0_RXNEMPTY + [0:0] + read-write + + + + + IRQ0_INTS + 0x00000134 + Interrupt status after masking & forcing for irq0 + 0x00000000 + + + SM3 + [11:11] + read-only + + + SM2 + [10:10] + read-only + + + SM1 + [9:9] + read-only + + + SM0 + [8:8] + read-only + + + SM3_TXNFULL + [7:7] + read-only + + + SM2_TXNFULL + [6:6] + read-only + + + SM1_TXNFULL + [5:5] + read-only + + + SM0_TXNFULL + [4:4] + read-only + + + SM3_RXNEMPTY + [3:3] + read-only + + + SM2_RXNEMPTY + [2:2] + read-only + + + SM1_RXNEMPTY + [1:1] + read-only + + + SM0_RXNEMPTY + [0:0] + read-only + + + + + IRQ1_INTE + 0x00000138 + Interrupt Enable for irq1 + 0x00000000 + + + SM3 + [11:11] + read-write + + + SM2 + [10:10] + read-write + + + SM1 + [9:9] + read-write + + + SM0 + [8:8] + read-write + + + SM3_TXNFULL + [7:7] + read-write + + + SM2_TXNFULL + [6:6] + read-write + + + SM1_TXNFULL + [5:5] + read-write + + + SM0_TXNFULL + [4:4] + read-write + + + SM3_RXNEMPTY + [3:3] + read-write + + + SM2_RXNEMPTY + [2:2] + read-write + + + SM1_RXNEMPTY + [1:1] + read-write + + + SM0_RXNEMPTY + [0:0] + read-write + + + + + IRQ1_INTF + 0x0000013c + Interrupt Force for irq1 + 0x00000000 + + + SM3 + [11:11] + read-write + + + SM2 + [10:10] + read-write + + + SM1 + [9:9] + read-write + + + SM0 + [8:8] + read-write + + + SM3_TXNFULL + [7:7] + read-write + + + SM2_TXNFULL + [6:6] + read-write + + + SM1_TXNFULL + [5:5] + read-write + + + SM0_TXNFULL + [4:4] + read-write + + + SM3_RXNEMPTY + [3:3] + read-write + + + SM2_RXNEMPTY + [2:2] + read-write + + + SM1_RXNEMPTY + [1:1] + read-write + + + SM0_RXNEMPTY + [0:0] + read-write + + + + + IRQ1_INTS + 0x00000140 + Interrupt status after masking & forcing for irq1 + 0x00000000 + + + SM3 + [11:11] + read-only + + + SM2 + [10:10] + read-only + + + SM1 + [9:9] + read-only + + + SM0 + [8:8] + read-only + + + SM3_TXNFULL + [7:7] + read-only + + + SM2_TXNFULL + [6:6] + read-only + + + SM1_TXNFULL + [5:5] + read-only + + + SM0_TXNFULL + [4:4] + read-only + + + SM3_RXNEMPTY + [3:3] + read-only + + + SM2_RXNEMPTY + [2:2] + read-only + + + SM1_RXNEMPTY + [1:1] + read-only + + + SM0_RXNEMPTY + [0:0] + read-only + + + + + + + PIO1 + 0x50300000 + + PIO1_IRQ_0 + 9 + + + PIO1_IRQ_1 + 10 + + + + BUSCTRL + Register block for busfabric control signals and performance counters + 0x40030000 + + 0 + 40 + registers + + + + BUS_PRIORITY + 0x00000000 + Set the priority of each master for bus arbitration. + 0x00000000 + + + DMA_W + 0 - low priority, 1 - high priority + [12:12] + read-write + + + DMA_R + 0 - low priority, 1 - high priority + [8:8] + read-write + + + PROC1 + 0 - low priority, 1 - high priority + [4:4] + read-write + + + PROC0 + 0 - low priority, 1 - high priority + [0:0] + read-write + + + + + BUS_PRIORITY_ACK + 0x00000004 + Bus priority acknowledge + 0x00000000 + + + BUS_PRIORITY_ACK + Goes to 1 once all arbiters have registered the new global priority levels. + Arbiters update their local priority when servicing a new nonsequential access. + In normal circumstances this will happen almost immediately. + [0:0] + read-only + + + + + PERFCTR0 + 0x00000008 + Bus fabric performance counter 0 + 0x00000000 + + + PERFCTR0 + Busfabric saturating performance counter 0 + Count some event signal from the busfabric arbiters. + Write any value to clear. Select an event to count using PERFSEL0 + [23:0] + read-write + oneToClear + + + + + PERFSEL0 + 0x0000000c + Bus fabric performance event select for PERFCTR0 + 0x0000001f + + + PERFSEL0 + Select an event for PERFCTR0. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + [4:0] + read-write + + + apb_contested + 0 + + + apb + 1 + + + fastperi_contested + 2 + + + fastperi + 3 + + + sram5_contested + 4 + + + sram5 + 5 + + + sram4_contested + 6 + + + sram4 + 7 + + + sram3_contested + 8 + + + sram3 + 9 + + + sram2_contested + 10 + + + sram2 + 11 + + + sram1_contested + 12 + + + sram1 + 13 + + + sram0_contested + 14 + + + sram0 + 15 + + + xip_main_contested + 16 + + + xip_main + 17 + + + rom_contested + 18 + + + rom + 19 + + + + + + + PERFCTR1 + 0x00000010 + Bus fabric performance counter 1 + 0x00000000 + + + PERFCTR1 + Busfabric saturating performance counter 1 + Count some event signal from the busfabric arbiters. + Write any value to clear. Select an event to count using PERFSEL1 + [23:0] + read-write + oneToClear + + + + + PERFSEL1 + 0x00000014 + Bus fabric performance event select for PERFCTR1 + 0x0000001f + + + PERFSEL1 + Select an event for PERFCTR1. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + [4:0] + read-write + + + apb_contested + 0 + + + apb + 1 + + + fastperi_contested + 2 + + + fastperi + 3 + + + sram5_contested + 4 + + + sram5 + 5 + + + sram4_contested + 6 + + + sram4 + 7 + + + sram3_contested + 8 + + + sram3 + 9 + + + sram2_contested + 10 + + + sram2 + 11 + + + sram1_contested + 12 + + + sram1 + 13 + + + sram0_contested + 14 + + + sram0 + 15 + + + xip_main_contested + 16 + + + xip_main + 17 + + + rom_contested + 18 + + + rom + 19 + + + + + + + PERFCTR2 + 0x00000018 + Bus fabric performance counter 2 + 0x00000000 + + + PERFCTR2 + Busfabric saturating performance counter 2 + Count some event signal from the busfabric arbiters. + Write any value to clear. Select an event to count using PERFSEL2 + [23:0] + read-write + oneToClear + + + + + PERFSEL2 + 0x0000001c + Bus fabric performance event select for PERFCTR2 + 0x0000001f + + + PERFSEL2 + Select an event for PERFCTR2. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + [4:0] + read-write + + + apb_contested + 0 + + + apb + 1 + + + fastperi_contested + 2 + + + fastperi + 3 + + + sram5_contested + 4 + + + sram5 + 5 + + + sram4_contested + 6 + + + sram4 + 7 + + + sram3_contested + 8 + + + sram3 + 9 + + + sram2_contested + 10 + + + sram2 + 11 + + + sram1_contested + 12 + + + sram1 + 13 + + + sram0_contested + 14 + + + sram0 + 15 + + + xip_main_contested + 16 + + + xip_main + 17 + + + rom_contested + 18 + + + rom + 19 + + + + + + + PERFCTR3 + 0x00000020 + Bus fabric performance counter 3 + 0x00000000 + + + PERFCTR3 + Busfabric saturating performance counter 3 + Count some event signal from the busfabric arbiters. + Write any value to clear. Select an event to count using PERFSEL3 + [23:0] + read-write + oneToClear + + + + + PERFSEL3 + 0x00000024 + Bus fabric performance event select for PERFCTR3 + 0x0000001f + + + PERFSEL3 + Select an event for PERFCTR3. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + [4:0] + read-write + + + apb_contested + 0 + + + apb + 1 + + + fastperi_contested + 2 + + + fastperi + 3 + + + sram5_contested + 4 + + + sram5 + 5 + + + sram4_contested + 6 + + + sram4 + 7 + + + sram3_contested + 8 + + + sram3 + 9 + + + sram2_contested + 10 + + + sram2 + 11 + + + sram1_contested + 12 + + + sram1 + 13 + + + sram0_contested + 14 + + + sram0 + 15 + + + xip_main_contested + 16 + + + xip_main + 17 + + + rom_contested + 18 + + + rom + 19 + + + + + + + + + SIO + Single-cycle IO block + Provides core-local and inter-core hardware for the two processors, with single-cycle access. + 0xd0000000 + + 0 + 384 + registers + + + SIO_IRQ_PROC0 + 15 + + + SIO_IRQ_PROC1 + 16 + + + + CPUID + 0x00000000 + Processor core identifier + 0x00000000 + + + CPUID + Value is 0 when read from processor core 0, and 1 when read from processor core 1. + [31:0] + read-only + + + + + GPIO_IN + 0x00000004 + Input value for GPIO pins + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_HI_IN + 0x00000008 + Input value for QSPI pins + 0x00000000 + + + GPIO_HI_IN + Input value on QSPI IO in order 0..5: SCLK, SSn, SD0, SD1, SD2, SD3 + [5:0] + read-only + + + + + GPIO_OUT + 0x00000010 + GPIO output value: Set output level (1/0 -> high/low) for GPIO0...29. + Reading back gives the last value written, NOT the input value from the pins. + If core 0 and core 1 both write to GPIO_OUT simultaneously (or to a SET/CLR/XOR alias), + the result is as though the write from core 0 took place first, + and the write from core 1 was then applied to that intermediate result. + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OUT_SET + 0x00000014 + GPIO output value set: Perform an atomic bit-set on GPIO_OUT, i.e. `GPIO_OUT |= wdata` + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OUT_CLR + 0x00000018 + GPIO output value clear + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OUT_XOR + 0x0000001c + GPIO output value XOR + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OE + 0x00000020 + GPIO output enable: Set output enable (1/0 -> output/input) for GPIO0...29. + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OE_SET + 0x00000024 + GPIO output enable set: Perform an atomic bit-set on GPIO_OE, i.e. `GPIO_OE |= wdata` + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OE_CLR + 0x00000028 + GPIO output enable clear: Perform an atomic bit-clear on GPIO_OE, i.e. `GPIO_OE &= ~wdata` + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OE_XOR + 0x0000002c + GPIO output enable XOR: Perform an atomic bitwise XOR on GPIO_OE, i.e. `GPIO_OE ^= wdata` + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_HI_OUT + 0x00000030 + QSPI output value + 0x00000000 + + + GPIO_HI_OUT + Set output level (1/0 -> high/low) for QSPI IO0...5. + Reading back gives the last value written, NOT the input value from the pins. + If core 0 and core 1 both write to GPIO_HI_OUT simultaneously (or to a SET/CLR/XOR alias), + the result is as though the write from core 0 took place first, + and the write from core 1 was then applied to that intermediate result. + [5:0] + read-write + + + + + GPIO_HI_OUT_SET + 0x00000034 + QSPI output value set + 0x00000000 + + + GPIO_HI_OUT_SET + Perform an atomic bit-set on GPIO_HI_OUT, i.e. `GPIO_HI_OUT |= wdata` + [5:0] + write-only + + + + + GPIO_HI_OUT_CLR + 0x00000038 + QSPI output value clear + 0x00000000 + + + GPIO_HI_OUT_CLR + Perform an atomic bit-clear on GPIO_HI_OUT, i.e. `GPIO_HI_OUT &= ~wdata` + [5:0] + write-only + + + + + GPIO_HI_OUT_XOR + 0x0000003c + QSPI output value XOR + 0x00000000 + + + GPIO_HI_OUT_XOR + Perform an atomic bitwise XOR on GPIO_HI_OUT, i.e. `GPIO_HI_OUT ^= wdata` + [5:0] + write-only + + + + + GPIO_HI_OE + 0x00000040 + QSPI output enable + 0x00000000 + + + GPIO_HI_OE + Set output enable (1/0 -> output/input) for QSPI IO0...5. + Reading back gives the last value written. + If core 0 and core 1 both write to GPIO_HI_OE simultaneously (or to a SET/CLR/XOR alias), + the result is as though the write from core 0 took place first, + and the write from core 1 was then applied to that intermediate result. + [5:0] + read-write + + + + + GPIO_HI_OE_SET + 0x00000044 + QSPI output enable set + 0x00000000 + + + GPIO_HI_OE_SET + Perform an atomic bit-set on GPIO_HI_OE, i.e. `GPIO_HI_OE |= wdata` + [5:0] + write-only + + + + + GPIO_HI_OE_CLR + 0x00000048 + QSPI output enable clear + 0x00000000 + + + GPIO_HI_OE_CLR + Perform an atomic bit-clear on GPIO_HI_OE, i.e. `GPIO_HI_OE &= ~wdata` + [5:0] + write-only + + + + + GPIO_HI_OE_XOR + 0x0000004c + QSPI output enable XOR + 0x00000000 + + + GPIO_HI_OE_XOR + Perform an atomic bitwise XOR on GPIO_HI_OE, i.e. `GPIO_HI_OE ^= wdata` + [5:0] + write-only + + + + + FIFO_ST + 0x00000050 + Status register for inter-core FIFOs (mailboxes). + There is one FIFO in the core 0 -> core 1 direction, and one core 1 -> core 0. Both are 32 bits wide and 8 words deep. + Core 0 can see the read side of the 1->0 FIFO (RX), and the write side of 0->1 FIFO (TX). + Core 1 can see the read side of the 0->1 FIFO (RX), and the write side of 1->0 FIFO (TX). + The SIO IRQ for each core is the logical OR of the VLD, WOF and ROE fields of its FIFO_ST register. + 0x00000002 + + + ROE + Sticky flag indicating the RX FIFO was read when empty. This read was ignored by the FIFO. + [3:3] + read-write + oneToClear + + + WOF + Sticky flag indicating the TX FIFO was written when full. This write was ignored by the FIFO. + [2:2] + read-write + oneToClear + + + RDY + Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more data) + [1:1] + read-only + + + VLD + Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid) + [0:0] + read-only + + + + + FIFO_WR + 0x00000054 + Write access to this core's TX FIFO + 0x00000000 + + + FIFO_WR + [31:0] + write-only + + + + + FIFO_RD + 0x00000058 + Read access to this core's RX FIFO + 0x00000000 + + + FIFO_RD + [31:0] + read-only + modify + + + + + SPINLOCK_ST + 0x0000005c + Spinlock state + A bitmap containing the state of all 32 spinlocks (1=locked). + Mainly intended for debugging. + 0x00000000 + + + SPINLOCK_ST + [31:0] + read-only + + + + + DIV_UDIVIDEND + 0x00000060 + Divider unsigned dividend + Write to the DIVIDEND operand of the divider, i.e. the p in `p / q`. + Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. + UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias starts an + unsigned calculation, and the S alias starts a signed calculation. + 0x00000000 + + + DIV_UDIVIDEND + [31:0] + read-write + + + + + DIV_UDIVISOR + 0x00000064 + Divider unsigned divisor + Write to the DIVISOR operand of the divider, i.e. the q in `p / q`. + Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. + UDIVISOR/SDIVISOR are aliases of the same internal register. The U alias starts an + unsigned calculation, and the S alias starts a signed calculation. + 0x00000000 + + + DIV_UDIVISOR + [31:0] + read-write + + + + + DIV_SDIVIDEND + 0x00000068 + Divider signed dividend + The same as UDIVIDEND, but starts a signed calculation, rather than unsigned. + 0x00000000 + + + DIV_SDIVIDEND + [31:0] + read-write + + + + + DIV_SDIVISOR + 0x0000006c + Divider signed divisor + The same as UDIVISOR, but starts a signed calculation, rather than unsigned. + 0x00000000 + + + DIV_SDIVISOR + [31:0] + read-write + + + + + DIV_QUOTIENT + 0x00000070 + Divider result quotient + The result of `DIVIDEND / DIVISOR` (division). Contents undefined while CSR_READY is low. + For signed calculations, QUOTIENT is negative when the signs of DIVIDEND and DIVISOR differ. + This register can be written to directly, for context save/restore purposes. This halts any + in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. + Reading from QUOTIENT clears the CSR_DIRTY flag, so should read results in the order + REMAINDER, QUOTIENT if CSR_DIRTY is used. + 0x00000000 + + + DIV_QUOTIENT + [31:0] + read-write + + + + + DIV_REMAINDER + 0x00000074 + Divider result remainder + The result of `DIVIDEND % DIVISOR` (modulo). Contents undefined while CSR_READY is low. + For signed calculations, REMAINDER is negative only when DIVIDEND is negative. + This register can be written to directly, for context save/restore purposes. This halts any + in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. + 0x00000000 + + + DIV_REMAINDER + [31:0] + read-write + + + + + DIV_CSR + 0x00000078 + Control and status register for divider. + 0x00000001 + + + DIRTY + Changes to 1 when any register is written, and back to 0 when QUOTIENT is read. + Software can use this flag to make save/restore more efficient (skip if not DIRTY). + If the flag is used in this way, it's recommended to either read QUOTIENT only, + or REMAINDER and then QUOTIENT, to prevent data loss on context switch. + [1:1] + read-only + + + READY + Reads as 0 when a calculation is in progress, 1 otherwise. + Writing an operand (xDIVIDEND, xDIVISOR) will immediately start a new calculation, no + matter if one is already in progress. + Writing to a result register will immediately terminate any in-progress calculation + and set the READY and DIRTY flags. + [0:0] + read-only + + + + + INTERP0_ACCUM0 + 0x00000080 + Read/write access to accumulator 0 + 0x00000000 + + + INTERP0_ACCUM0 + [31:0] + read-write + + + + + INTERP0_ACCUM1 + 0x00000084 + Read/write access to accumulator 1 + 0x00000000 + + + INTERP0_ACCUM1 + [31:0] + read-write + + + + + INTERP0_BASE0 + 0x00000088 + Read/write access to BASE0 register. + 0x00000000 + + + INTERP0_BASE0 + [31:0] + read-write + + + + + INTERP0_BASE1 + 0x0000008c + Read/write access to BASE1 register. + 0x00000000 + + + INTERP0_BASE1 + [31:0] + read-write + + + + + INTERP0_BASE2 + 0x00000090 + Read/write access to BASE2 register. + 0x00000000 + + + INTERP0_BASE2 + [31:0] + read-write + + + + + INTERP0_POP_LANE0 + 0x00000094 + Read LANE0 result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP0_POP_LANE0 + [31:0] + read-only + + + + + INTERP0_POP_LANE1 + 0x00000098 + Read LANE1 result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP0_POP_LANE1 + [31:0] + read-only + + + + + INTERP0_POP_FULL + 0x0000009c + Read FULL result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP0_POP_FULL + [31:0] + read-only + + + + + INTERP0_PEEK_LANE0 + 0x000000a0 + Read LANE0 result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP0_PEEK_LANE0 + [31:0] + read-only + + + + + INTERP0_PEEK_LANE1 + 0x000000a4 + Read LANE1 result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP0_PEEK_LANE1 + [31:0] + read-only + + + + + INTERP0_PEEK_FULL + 0x000000a8 + Read FULL result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP0_PEEK_FULL + [31:0] + read-only + + + + + INTERP0_CTRL_LANE0 + 0x000000ac + Control register for lane 0 + 0x00000000 + + + OVERF + Set if either OVERF0 or OVERF1 is set. + [25:25] + read-only + + + OVERF1 + Indicates if any masked-off MSBs in ACCUM1 are set. + [24:24] + read-only + + + OVERF0 + Indicates if any masked-off MSBs in ACCUM0 are set. + [23:23] + read-only + + + BLEND + Only present on INTERP0 on each core. If BLEND mode is enabled: + - LANE1 result is a linear interpolation between BASE0 and BASE1, controlled + by the 8 LSBs of lane 1 shift and mask value (a fractional number between + 0 and 255/256ths) + - LANE0 result does not have BASE0 added (yields only the 8 LSBs of lane 1 shift+mask value) + - FULL result does not have lane 1 shift+mask value added (BASE2 + lane 0 shift+mask) + LANE1 SIGNED flag controls whether the interpolation is signed or unsigned. + [21:21] + read-write + + + FORCE_MSB + ORed into bits 29:28 of the lane result presented to the processor on the bus. + No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + of pointers into flash or SRAM. + [20:19] + read-write + + + ADD_RAW + If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. + [18:18] + read-write + + + CROSS_RESULT + If 1, feed the opposite lane's result into this lane's accumulator on POP. + [17:17] + read-write + + + CROSS_INPUT + If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + [16:16] + read-write + + + SIGNED + If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. + [15:15] + read-write + + + MASK_MSB + The most-significant bit allowed to pass by the mask (inclusive) + Setting MSB < LSB may cause chip to turn inside-out + [14:10] + read-write + + + MASK_LSB + The least-significant bit allowed to pass by the mask (inclusive) + [9:5] + read-write + + + SHIFT + Logical right-shift applied to accumulator before masking + [4:0] + read-write + + + + + INTERP0_CTRL_LANE1 + 0x000000b0 + Control register for lane 1 + 0x00000000 + + + FORCE_MSB + ORed into bits 29:28 of the lane result presented to the processor on the bus. + No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + of pointers into flash or SRAM. + [20:19] + read-write + + + ADD_RAW + If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. + [18:18] + read-write + + + CROSS_RESULT + If 1, feed the opposite lane's result into this lane's accumulator on POP. + [17:17] + read-write + + + CROSS_INPUT + If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + [16:16] + read-write + + + SIGNED + If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. + [15:15] + read-write + + + MASK_MSB + The most-significant bit allowed to pass by the mask (inclusive) + Setting MSB < LSB may cause chip to turn inside-out + [14:10] + read-write + + + MASK_LSB + The least-significant bit allowed to pass by the mask (inclusive) + [9:5] + read-write + + + SHIFT + Logical right-shift applied to accumulator before masking + [4:0] + read-write + + + + + INTERP0_ACCUM0_ADD + 0x000000b4 + Values written here are atomically added to ACCUM0 + Reading yields lane 0's raw shift and mask value (BASE0 not added). + 0x00000000 + + + INTERP0_ACCUM0_ADD + [23:0] + read-write + + + + + INTERP0_ACCUM1_ADD + 0x000000b8 + Values written here are atomically added to ACCUM1 + Reading yields lane 1's raw shift and mask value (BASE1 not added). + 0x00000000 + + + INTERP0_ACCUM1_ADD + [23:0] + read-write + + + + + INTERP0_BASE_1AND0 + 0x000000bc + On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. + Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + 0x00000000 + + + INTERP0_BASE_1AND0 + [31:0] + write-only + + + + + INTERP1_ACCUM0 + 0x000000c0 + Read/write access to accumulator 0 + 0x00000000 + + + INTERP1_ACCUM0 + [31:0] + read-write + + + + + INTERP1_ACCUM1 + 0x000000c4 + Read/write access to accumulator 1 + 0x00000000 + + + INTERP1_ACCUM1 + [31:0] + read-write + + + + + INTERP1_BASE0 + 0x000000c8 + Read/write access to BASE0 register. + 0x00000000 + + + INTERP1_BASE0 + [31:0] + read-write + + + + + INTERP1_BASE1 + 0x000000cc + Read/write access to BASE1 register. + 0x00000000 + + + INTERP1_BASE1 + [31:0] + read-write + + + + + INTERP1_BASE2 + 0x000000d0 + Read/write access to BASE2 register. + 0x00000000 + + + INTERP1_BASE2 + [31:0] + read-write + + + + + INTERP1_POP_LANE0 + 0x000000d4 + Read LANE0 result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP1_POP_LANE0 + [31:0] + read-only + + + + + INTERP1_POP_LANE1 + 0x000000d8 + Read LANE1 result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP1_POP_LANE1 + [31:0] + read-only + + + + + INTERP1_POP_FULL + 0x000000dc + Read FULL result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP1_POP_FULL + [31:0] + read-only + + + + + INTERP1_PEEK_LANE0 + 0x000000e0 + Read LANE0 result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP1_PEEK_LANE0 + [31:0] + read-only + + + + + INTERP1_PEEK_LANE1 + 0x000000e4 + Read LANE1 result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP1_PEEK_LANE1 + [31:0] + read-only + + + + + INTERP1_PEEK_FULL + 0x000000e8 + Read FULL result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP1_PEEK_FULL + [31:0] + read-only + + + + + INTERP1_CTRL_LANE0 + 0x000000ec + Control register for lane 0 + 0x00000000 + + + OVERF + Set if either OVERF0 or OVERF1 is set. + [25:25] + read-only + + + OVERF1 + Indicates if any masked-off MSBs in ACCUM1 are set. + [24:24] + read-only + + + OVERF0 + Indicates if any masked-off MSBs in ACCUM0 are set. + [23:23] + read-only + + + CLAMP + Only present on INTERP1 on each core. If CLAMP mode is enabled: + - LANE0 result is shifted and masked ACCUM0, clamped by a lower bound of + BASE0 and an upper bound of BASE1. + - Signedness of these comparisons is determined by LANE0_CTRL_SIGNED + [22:22] + read-write + + + FORCE_MSB + ORed into bits 29:28 of the lane result presented to the processor on the bus. + No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + of pointers into flash or SRAM. + [20:19] + read-write + + + ADD_RAW + If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. + [18:18] + read-write + + + CROSS_RESULT + If 1, feed the opposite lane's result into this lane's accumulator on POP. + [17:17] + read-write + + + CROSS_INPUT + If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + [16:16] + read-write + + + SIGNED + If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. + [15:15] + read-write + + + MASK_MSB + The most-significant bit allowed to pass by the mask (inclusive) + Setting MSB < LSB may cause chip to turn inside-out + [14:10] + read-write + + + MASK_LSB + The least-significant bit allowed to pass by the mask (inclusive) + [9:5] + read-write + + + SHIFT + Logical right-shift applied to accumulator before masking + [4:0] + read-write + + + + + INTERP1_CTRL_LANE1 + 0x000000f0 + Control register for lane 1 + 0x00000000 + + + FORCE_MSB + ORed into bits 29:28 of the lane result presented to the processor on the bus. + No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + of pointers into flash or SRAM. + [20:19] + read-write + + + ADD_RAW + If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. + [18:18] + read-write + + + CROSS_RESULT + If 1, feed the opposite lane's result into this lane's accumulator on POP. + [17:17] + read-write + + + CROSS_INPUT + If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + [16:16] + read-write + + + SIGNED + If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. + [15:15] + read-write + + + MASK_MSB + The most-significant bit allowed to pass by the mask (inclusive) + Setting MSB < LSB may cause chip to turn inside-out + [14:10] + read-write + + + MASK_LSB + The least-significant bit allowed to pass by the mask (inclusive) + [9:5] + read-write + + + SHIFT + Logical right-shift applied to accumulator before masking + [4:0] + read-write + + + + + INTERP1_ACCUM0_ADD + 0x000000f4 + Values written here are atomically added to ACCUM0 + Reading yields lane 0's raw shift and mask value (BASE0 not added). + 0x00000000 + + + INTERP1_ACCUM0_ADD + [23:0] + read-write + + + + + INTERP1_ACCUM1_ADD + 0x000000f8 + Values written here are atomically added to ACCUM1 + Reading yields lane 1's raw shift and mask value (BASE1 not added). + 0x00000000 + + + INTERP1_ACCUM1_ADD + [23:0] + read-write + + + + + INTERP1_BASE_1AND0 + 0x000000fc + On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. + Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + 0x00000000 + + + INTERP1_BASE_1AND0 + [31:0] + write-only + + + + + SPINLOCK0 + 0x00000100 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK0 + [31:0] + read-write + modify + + + + + SPINLOCK1 + 0x00000104 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK1 + [31:0] + read-write + modify + + + + + SPINLOCK2 + 0x00000108 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK2 + [31:0] + read-write + modify + + + + + SPINLOCK3 + 0x0000010c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK3 + [31:0] + read-write + modify + + + + + SPINLOCK4 + 0x00000110 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK4 + [31:0] + read-write + modify + + + + + SPINLOCK5 + 0x00000114 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK5 + [31:0] + read-write + modify + + + + + SPINLOCK6 + 0x00000118 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK6 + [31:0] + read-write + modify + + + + + SPINLOCK7 + 0x0000011c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK7 + [31:0] + read-write + modify + + + + + SPINLOCK8 + 0x00000120 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK8 + [31:0] + read-write + modify + + + + + SPINLOCK9 + 0x00000124 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK9 + [31:0] + read-write + modify + + + + + SPINLOCK10 + 0x00000128 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK10 + [31:0] + read-write + modify + + + + + SPINLOCK11 + 0x0000012c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK11 + [31:0] + read-write + modify + + + + + SPINLOCK12 + 0x00000130 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK12 + [31:0] + read-write + modify + + + + + SPINLOCK13 + 0x00000134 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK13 + [31:0] + read-write + modify + + + + + SPINLOCK14 + 0x00000138 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK14 + [31:0] + read-write + modify + + + + + SPINLOCK15 + 0x0000013c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK15 + [31:0] + read-write + modify + + + + + SPINLOCK16 + 0x00000140 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK16 + [31:0] + read-write + modify + + + + + SPINLOCK17 + 0x00000144 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK17 + [31:0] + read-write + modify + + + + + SPINLOCK18 + 0x00000148 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK18 + [31:0] + read-write + modify + + + + + SPINLOCK19 + 0x0000014c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK19 + [31:0] + read-write + modify + + + + + SPINLOCK20 + 0x00000150 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK20 + [31:0] + read-write + modify + + + + + SPINLOCK21 + 0x00000154 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK21 + [31:0] + read-write + modify + + + + + SPINLOCK22 + 0x00000158 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK22 + [31:0] + read-write + modify + + + + + SPINLOCK23 + 0x0000015c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK23 + [31:0] + read-write + modify + + + + + SPINLOCK24 + 0x00000160 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK24 + [31:0] + read-write + modify + + + + + SPINLOCK25 + 0x00000164 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK25 + [31:0] + read-write + modify + + + + + SPINLOCK26 + 0x00000168 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK26 + [31:0] + read-write + modify + + + + + SPINLOCK27 + 0x0000016c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK27 + [31:0] + read-write + modify + + + + + SPINLOCK28 + 0x00000170 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK28 + [31:0] + read-write + modify + + + + + SPINLOCK29 + 0x00000174 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK29 + [31:0] + read-write + modify + + + + + SPINLOCK30 + 0x00000178 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK30 + [31:0] + read-write + modify + + + + + SPINLOCK31 + 0x0000017c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK31 + [31:0] + read-write + modify + + + + + + + USB + USB FS/LS controller device registers + 0x50110000 + + 0 + 156 + registers + + + USBCTRL_IRQ + 5 + + + + ADDR_ENDP + 0x00000000 + Device address and endpoint control + 0x00000000 + + + ENDPOINT + Device endpoint to send data to. Only valid for HOST mode. + [19:16] + read-write + + + ADDRESS + In device mode, the address that the device should respond to. Set in response to a SET_ADDR setup packet from the host. In host mode set to the address of the device to communicate with. + [6:0] + read-write + + + + + ADDR_ENDP1 + 0x00000004 + Interrupt endpoint 1. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP2 + 0x00000008 + Interrupt endpoint 2. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP3 + 0x0000000c + Interrupt endpoint 3. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP4 + 0x00000010 + Interrupt endpoint 4. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP5 + 0x00000014 + Interrupt endpoint 5. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP6 + 0x00000018 + Interrupt endpoint 6. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP7 + 0x0000001c + Interrupt endpoint 7. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP8 + 0x00000020 + Interrupt endpoint 8. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP9 + 0x00000024 + Interrupt endpoint 9. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP10 + 0x00000028 + Interrupt endpoint 10. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP11 + 0x0000002c + Interrupt endpoint 11. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP12 + 0x00000030 + Interrupt endpoint 12. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP13 + 0x00000034 + Interrupt endpoint 13. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP14 + 0x00000038 + Interrupt endpoint 14. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP15 + 0x0000003c + Interrupt endpoint 15. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + MAIN_CTRL + 0x00000040 + Main control register + 0x00000000 + + + SIM_TIMING + Reduced timings for simulation + [31:31] + read-write + + + HOST_NDEVICE + Device mode = 0, Host mode = 1 + [1:1] + read-write + + + CONTROLLER_EN + Enable controller + [0:0] + read-write + + + + + SOF_WR + 0x00000044 + Set the SOF (Start of Frame) frame number in the host controller. The SOF packet is sent every 1ms and the host will increment the frame number by 1 each time. + 0x00000000 + + + COUNT + [10:0] + write-only + + + + + SOF_RD + 0x00000048 + Read the last SOF (Start of Frame) frame number seen. In device mode the last SOF received from the host. In host mode the last SOF sent by the host. + 0x00000000 + + + COUNT + [10:0] + read-only + + + + + SIE_CTRL + 0x0000004c + SIE control register + 0x00000000 + + + EP0_INT_STALL + Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a STALL + [31:31] + read-write + + + EP0_DOUBLE_BUF + Device: EP0 single buffered = 0, double buffered = 1 + [30:30] + read-write + + + EP0_INT_1BUF + Device: Set bit in BUFF_STATUS for every buffer completed on EP0 + [29:29] + read-write + + + EP0_INT_2BUF + Device: Set bit in BUFF_STATUS for every 2 buffers completed on EP0 + [28:28] + read-write + + + EP0_INT_NAK + Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a NAK + [27:27] + read-write + + + DIRECT_EN + Direct bus drive enable + [26:26] + read-write + + + DIRECT_DP + Direct control of DP + [25:25] + read-write + + + DIRECT_DM + Direct control of DM + [24:24] + read-write + + + TRANSCEIVER_PD + Power down bus transceiver + [18:18] + read-write + + + RPU_OPT + Device: Pull-up strength (0=1K2, 1=2k3) + [17:17] + read-write + + + PULLUP_EN + Device: Enable pull up resistor + [16:16] + read-write + + + PULLDOWN_EN + Host: Enable pull down resistors + [15:15] + read-write + + + RESET_BUS + Host: Reset bus + [13:13] + write-only + + + RESUME + Device: Remote wakeup. Device can initiate its own resume after suspend. + [12:12] + write-only + + + VBUS_EN + Host: Enable VBUS + [11:11] + read-write + + + KEEP_ALIVE_EN + Host: Enable keep alive packet (for low speed bus) + [10:10] + read-write + + + SOF_EN + Host: Enable SOF generation (for full speed bus) + [9:9] + read-write + + + SOF_SYNC + Host: Delay packet(s) until after SOF + [8:8] + read-write + + + PREAMBLE_EN + Host: Preable enable for LS device on FS hub + [6:6] + read-write + + + STOP_TRANS + Host: Stop transaction + [4:4] + write-only + + + RECEIVE_DATA + Host: Receive transaction (IN to host) + [3:3] + read-write + + + SEND_DATA + Host: Send transaction (OUT from host) + [2:2] + read-write + + + SEND_SETUP + Host: Send Setup packet + [1:1] + read-write + + + START_TRANS + Host: Start transaction + [0:0] + write-only + + + + + SIE_STATUS + 0x00000050 + SIE status register + 0x00000000 + + + DATA_SEQ_ERROR + Data Sequence Error. + + The device can raise a sequence error in the following conditions: + + * A SETUP packet is received followed by a DATA1 packet (data phase should always be DATA0) * An OUT packet is received from the host but doesn't match the data pid in the buffer control register read from DPSRAM + + The host can raise a data sequence error in the following conditions: + + * An IN packet from the device has the wrong data PID + [31:31] + read-write + oneToClear + + + ACK_REC + ACK received. Raised by both host and device. + [30:30] + read-write + oneToClear + + + STALL_REC + Host: STALL received + [29:29] + read-write + oneToClear + + + NAK_REC + Host: NAK received + [28:28] + read-write + oneToClear + + + RX_TIMEOUT + RX timeout is raised by both the host and device if an ACK is not received in the maximum time specified by the USB spec. + [27:27] + read-write + oneToClear + + + RX_OVERFLOW + RX overflow is raised by the Serial RX engine if the incoming data is too fast. + [26:26] + read-write + oneToClear + + + BIT_STUFF_ERROR + Bit Stuff Error. Raised by the Serial RX engine. + [25:25] + read-write + oneToClear + + + CRC_ERROR + CRC Error. Raised by the Serial RX engine. + [24:24] + read-write + oneToClear + + + BUS_RESET + Device: bus reset received + [19:19] + read-write + oneToClear + + + TRANS_COMPLETE + Transaction complete. + + Raised by device if: + + * An IN or OUT packet is sent with the `LAST_BUFF` bit set in the buffer control register + + Raised by host if: + + * A setup packet is sent when no data in or data out transaction follows * An IN packet is received and the `LAST_BUFF` bit is set in the buffer control register * An IN packet is received with zero length * An OUT packet is sent and the `LAST_BUFF` bit is set + [18:18] + read-write + oneToClear + + + SETUP_REC + Device: Setup packet received + [17:17] + read-write + oneToClear + + + CONNECTED + Device: connected + [16:16] + read-only + + + RESUME + Host: Device has initiated a remote resume. Device: host has initiated a resume. + [11:11] + read-write + oneToClear + + + VBUS_OVER_CURR + VBUS over current detected + [10:10] + read-only + + + SPEED + Host: device speed. Disconnected = 00, LS = 01, FS = 10 + [9:8] + read-only + + + SUSPENDED + Bus in suspended state. Valid for device and host. Host and device will go into suspend if neither Keep Alive / SOF frames are enabled. + [4:4] + read-only + + + LINE_STATE + USB bus line state + [3:2] + read-only + + + VBUS_DETECTED + Device: VBUS Detected + [0:0] + read-only + + + + + INT_EP_CTRL + 0x00000054 + interrupt endpoint control register + 0x00000000 + + + INT_EP_ACTIVE + Host: Enable interrupt endpoint 1 => 15 + [15:1] + read-write + + + + + BUFF_STATUS + 0x00000058 + Buffer status register. A bit set here indicates that a buffer has completed on the endpoint (if the buffer interrupt is enabled). It is possible for 2 buffers to be completed, so clearing the buffer status bit may instantly re set it on the next clock cycle. + 0x00000000 + + + EP15_OUT + [31:31] + read-write + oneToClear + + + EP15_IN + [30:30] + read-write + oneToClear + + + EP14_OUT + [29:29] + read-write + oneToClear + + + EP14_IN + [28:28] + read-write + oneToClear + + + EP13_OUT + [27:27] + read-write + oneToClear + + + EP13_IN + [26:26] + read-write + oneToClear + + + EP12_OUT + [25:25] + read-write + oneToClear + + + EP12_IN + [24:24] + read-write + oneToClear + + + EP11_OUT + [23:23] + read-write + oneToClear + + + EP11_IN + [22:22] + read-write + oneToClear + + + EP10_OUT + [21:21] + read-write + oneToClear + + + EP10_IN + [20:20] + read-write + oneToClear + + + EP9_OUT + [19:19] + read-write + oneToClear + + + EP9_IN + [18:18] + read-write + oneToClear + + + EP8_OUT + [17:17] + read-write + oneToClear + + + EP8_IN + [16:16] + read-write + oneToClear + + + EP7_OUT + [15:15] + read-write + oneToClear + + + EP7_IN + [14:14] + read-write + oneToClear + + + EP6_OUT + [13:13] + read-write + oneToClear + + + EP6_IN + [12:12] + read-write + oneToClear + + + EP5_OUT + [11:11] + read-write + oneToClear + + + EP5_IN + [10:10] + read-write + oneToClear + + + EP4_OUT + [9:9] + read-write + oneToClear + + + EP4_IN + [8:8] + read-write + oneToClear + + + EP3_OUT + [7:7] + read-write + oneToClear + + + EP3_IN + [6:6] + read-write + oneToClear + + + EP2_OUT + [5:5] + read-write + oneToClear + + + EP2_IN + [4:4] + read-write + oneToClear + + + EP1_OUT + [3:3] + read-write + oneToClear + + + EP1_IN + [2:2] + read-write + oneToClear + + + EP0_OUT + [1:1] + read-write + oneToClear + + + EP0_IN + [0:0] + read-write + oneToClear + + + + + BUFF_CPU_SHOULD_HANDLE + 0x0000005c + Which of the double buffers should be handled. Only valid if using an interrupt per buffer (i.e. not per 2 buffers). Not valid for host interrupt endpoint polling because they are only single buffered. + 0x00000000 + + + EP15_OUT + [31:31] + read-only + + + EP15_IN + [30:30] + read-only + + + EP14_OUT + [29:29] + read-only + + + EP14_IN + [28:28] + read-only + + + EP13_OUT + [27:27] + read-only + + + EP13_IN + [26:26] + read-only + + + EP12_OUT + [25:25] + read-only + + + EP12_IN + [24:24] + read-only + + + EP11_OUT + [23:23] + read-only + + + EP11_IN + [22:22] + read-only + + + EP10_OUT + [21:21] + read-only + + + EP10_IN + [20:20] + read-only + + + EP9_OUT + [19:19] + read-only + + + EP9_IN + [18:18] + read-only + + + EP8_OUT + [17:17] + read-only + + + EP8_IN + [16:16] + read-only + + + EP7_OUT + [15:15] + read-only + + + EP7_IN + [14:14] + read-only + + + EP6_OUT + [13:13] + read-only + + + EP6_IN + [12:12] + read-only + + + EP5_OUT + [11:11] + read-only + + + EP5_IN + [10:10] + read-only + + + EP4_OUT + [9:9] + read-only + + + EP4_IN + [8:8] + read-only + + + EP3_OUT + [7:7] + read-only + + + EP3_IN + [6:6] + read-only + + + EP2_OUT + [5:5] + read-only + + + EP2_IN + [4:4] + read-only + + + EP1_OUT + [3:3] + read-only + + + EP1_IN + [2:2] + read-only + + + EP0_OUT + [1:1] + read-only + + + EP0_IN + [0:0] + read-only + + + + + EP_ABORT + 0x00000060 + Device only: Can be set to ignore the buffer control register for this endpoint in case you would like to revoke a buffer. A NAK will be sent for every access to the endpoint until this bit is cleared. A corresponding bit in `EP_ABORT_DONE` is set when it is safe to modify the buffer control register. + 0x00000000 + + + EP15_OUT + [31:31] + read-write + + + EP15_IN + [30:30] + read-write + + + EP14_OUT + [29:29] + read-write + + + EP14_IN + [28:28] + read-write + + + EP13_OUT + [27:27] + read-write + + + EP13_IN + [26:26] + read-write + + + EP12_OUT + [25:25] + read-write + + + EP12_IN + [24:24] + read-write + + + EP11_OUT + [23:23] + read-write + + + EP11_IN + [22:22] + read-write + + + EP10_OUT + [21:21] + read-write + + + EP10_IN + [20:20] + read-write + + + EP9_OUT + [19:19] + read-write + + + EP9_IN + [18:18] + read-write + + + EP8_OUT + [17:17] + read-write + + + EP8_IN + [16:16] + read-write + + + EP7_OUT + [15:15] + read-write + + + EP7_IN + [14:14] + read-write + + + EP6_OUT + [13:13] + read-write + + + EP6_IN + [12:12] + read-write + + + EP5_OUT + [11:11] + read-write + + + EP5_IN + [10:10] + read-write + + + EP4_OUT + [9:9] + read-write + + + EP4_IN + [8:8] + read-write + + + EP3_OUT + [7:7] + read-write + + + EP3_IN + [6:6] + read-write + + + EP2_OUT + [5:5] + read-write + + + EP2_IN + [4:4] + read-write + + + EP1_OUT + [3:3] + read-write + + + EP1_IN + [2:2] + read-write + + + EP0_OUT + [1:1] + read-write + + + EP0_IN + [0:0] + read-write + + + + + EP_ABORT_DONE + 0x00000064 + Device only: Used in conjunction with `EP_ABORT`. Set once an endpoint is idle so the programmer knows it is safe to modify the buffer control register. + 0x00000000 + + + EP15_OUT + [31:31] + read-write + oneToClear + + + EP15_IN + [30:30] + read-write + oneToClear + + + EP14_OUT + [29:29] + read-write + oneToClear + + + EP14_IN + [28:28] + read-write + oneToClear + + + EP13_OUT + [27:27] + read-write + oneToClear + + + EP13_IN + [26:26] + read-write + oneToClear + + + EP12_OUT + [25:25] + read-write + oneToClear + + + EP12_IN + [24:24] + read-write + oneToClear + + + EP11_OUT + [23:23] + read-write + oneToClear + + + EP11_IN + [22:22] + read-write + oneToClear + + + EP10_OUT + [21:21] + read-write + oneToClear + + + EP10_IN + [20:20] + read-write + oneToClear + + + EP9_OUT + [19:19] + read-write + oneToClear + + + EP9_IN + [18:18] + read-write + oneToClear + + + EP8_OUT + [17:17] + read-write + oneToClear + + + EP8_IN + [16:16] + read-write + oneToClear + + + EP7_OUT + [15:15] + read-write + oneToClear + + + EP7_IN + [14:14] + read-write + oneToClear + + + EP6_OUT + [13:13] + read-write + oneToClear + + + EP6_IN + [12:12] + read-write + oneToClear + + + EP5_OUT + [11:11] + read-write + oneToClear + + + EP5_IN + [10:10] + read-write + oneToClear + + + EP4_OUT + [9:9] + read-write + oneToClear + + + EP4_IN + [8:8] + read-write + oneToClear + + + EP3_OUT + [7:7] + read-write + oneToClear + + + EP3_IN + [6:6] + read-write + oneToClear + + + EP2_OUT + [5:5] + read-write + oneToClear + + + EP2_IN + [4:4] + read-write + oneToClear + + + EP1_OUT + [3:3] + read-write + oneToClear + + + EP1_IN + [2:2] + read-write + oneToClear + + + EP0_OUT + [1:1] + read-write + oneToClear + + + EP0_IN + [0:0] + read-write + oneToClear + + + + + EP_STALL_ARM + 0x00000068 + Device: this bit must be set in conjunction with the `STALL` bit in the buffer control register to send a STALL on EP0. The device controller clears these bits when a SETUP packet is received because the USB spec requires that a STALL condition is cleared when a SETUP packet is received. + 0x00000000 + + + EP0_OUT + [1:1] + read-write + + + EP0_IN + [0:0] + read-write + + + + + NAK_POLL + 0x0000006c + Used by the host controller. Sets the wait time in microseconds before trying again if the device replies with a NAK. + 0x00100010 + + + DELAY_FS + NAK polling interval for a full speed device + [25:16] + read-write + + + DELAY_LS + NAK polling interval for a low speed device + [9:0] + read-write + + + + + EP_STATUS_STALL_NAK + 0x00000070 + Device: bits are set when the `IRQ_ON_NAK` or `IRQ_ON_STALL` bits are set. For EP0 this comes from `SIE_CTRL`. For all other endpoints it comes from the endpoint control register. + 0x00000000 + + + EP15_OUT + [31:31] + read-write + oneToClear + + + EP15_IN + [30:30] + read-write + oneToClear + + + EP14_OUT + [29:29] + read-write + oneToClear + + + EP14_IN + [28:28] + read-write + oneToClear + + + EP13_OUT + [27:27] + read-write + oneToClear + + + EP13_IN + [26:26] + read-write + oneToClear + + + EP12_OUT + [25:25] + read-write + oneToClear + + + EP12_IN + [24:24] + read-write + oneToClear + + + EP11_OUT + [23:23] + read-write + oneToClear + + + EP11_IN + [22:22] + read-write + oneToClear + + + EP10_OUT + [21:21] + read-write + oneToClear + + + EP10_IN + [20:20] + read-write + oneToClear + + + EP9_OUT + [19:19] + read-write + oneToClear + + + EP9_IN + [18:18] + read-write + oneToClear + + + EP8_OUT + [17:17] + read-write + oneToClear + + + EP8_IN + [16:16] + read-write + oneToClear + + + EP7_OUT + [15:15] + read-write + oneToClear + + + EP7_IN + [14:14] + read-write + oneToClear + + + EP6_OUT + [13:13] + read-write + oneToClear + + + EP6_IN + [12:12] + read-write + oneToClear + + + EP5_OUT + [11:11] + read-write + oneToClear + + + EP5_IN + [10:10] + read-write + oneToClear + + + EP4_OUT + [9:9] + read-write + oneToClear + + + EP4_IN + [8:8] + read-write + oneToClear + + + EP3_OUT + [7:7] + read-write + oneToClear + + + EP3_IN + [6:6] + read-write + oneToClear + + + EP2_OUT + [5:5] + read-write + oneToClear + + + EP2_IN + [4:4] + read-write + oneToClear + + + EP1_OUT + [3:3] + read-write + oneToClear + + + EP1_IN + [2:2] + read-write + oneToClear + + + EP0_OUT + [1:1] + read-write + oneToClear + + + EP0_IN + [0:0] + read-write + oneToClear + + + + + USB_MUXING + 0x00000074 + Where to connect the USB controller. Should be to_phy by default. + 0x00000000 + + + SOFTCON + [3:3] + read-write + + + TO_DIGITAL_PAD + [2:2] + read-write + + + TO_EXTPHY + [1:1] + read-write + + + TO_PHY + [0:0] + read-write + + + + + USB_PWR + 0x00000078 + Overrides for the power signals in the event that the VBUS signals are not hooked up to GPIO. Set the value of the override and then the override enable so switch over to the override value. + 0x00000000 + + + OVERCURR_DETECT_EN + [5:5] + read-write + + + OVERCURR_DETECT + [4:4] + read-write + + + VBUS_DETECT_OVERRIDE_EN + [3:3] + read-write + + + VBUS_DETECT + [2:2] + read-write + + + VBUS_EN_OVERRIDE_EN + [1:1] + read-write + + + VBUS_EN + [0:0] + read-write + + + + + USBPHY_DIRECT + 0x0000007c + Note that most functions are driven directly from usb_fsls controller. This register allows more detailed control/status from the USB PHY. Useful for debug but not expected to be used in normal operation + Use in conjunction with usbphy_direct_override register + 0x00000000 + + + DM_OVV + Status bit from USB PHY + [22:22] + read-only + + + DP_OVV + Status bit from USB PHY + [21:21] + read-only + + + DM_OVCN + Status bit from USB PHY + [20:20] + read-only + + + DP_OVCN + Status bit from USB PHY + [19:19] + read-only + + + RX_DM + Status bit from USB PHY + DPM pin state + [18:18] + read-only + + + RX_DP + Status bit from USB PHY + DPP pin state + [17:17] + read-only + + + RX_DD + Status bit from USB PHY + RX Diff data + [16:16] + read-only + + + TX_DIFFMODE + [15:15] + read-write + + + TX_FSSLEW + [14:14] + read-write + + + TX_PD + [13:13] + read-write + + + RX_PD + [12:12] + read-write + + + TX_DM + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + TX_SEMODE=0, Ignored + TX_SEMODE=1, Drives DPM only. TX_DM_OE=1 to enable drive. DPM=TX_DM + [11:11] + read-write + + + TX_DP + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + TX_SEMODE=0, Drives DPP/DPM diff pair. TX_DP_OE=1 to enable drive. DPP=TX_DP, DPM=~TX_DP + TX_SEMODE=1, Drives DPP only. TX_DP_OE=1 to enable drive. DPP=TX_DP + [10:10] + read-write + + + TX_DM_OE + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + TX_SEMODE=0, Ignored. + TX_SEMODE=1, OE for DPM only. 0 - DPM in Hi-Z state; 1 - DPM driving + [9:9] + read-write + + + TX_DP_OE + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + TX_SEMODE=0, OE for DPP/DPM diff pair. 0 - DPP/DPM in Hi-Z state; 1 - DPP/DPM driving + TX_SEMODE=1, OE for DPP only. 0 - DPP in Hi-Z state; 1 - DPP driving + [8:8] + read-write + + + DM_PULLDN_EN + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + 1 - Enable Rpd on DPM + [6:6] + read-write + + + DM_PULLUP_EN + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + 1 - Enable Rpu on DPM + [5:5] + read-write + + + DM_PULLUP_HISEL + when dm_pullup_en is set high, this enables second resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + [4:4] + read-write + + + DP_PULLDN_EN + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + 1 - Enable Rpd on DPP + [2:2] + read-write + + + DP_PULLUP_EN + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + [1:1] + read-write + + + DP_PULLUP_HISEL + when dp_pullup_en is set high, this enables second resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + [0:0] + read-write + + + + + USBPHY_DIRECT_OVERRIDE + 0x00000080 + 0x00000000 + + + TX_DIFFMODE_OVERRIDE_EN + [15:15] + read-write + + + DM_PULLUP_OVERRIDE_EN + [12:12] + read-write + + + TX_FSSLEW_OVERRIDE_EN + [11:11] + read-write + + + TX_PD_OVERRIDE_EN + [10:10] + read-write + + + RX_PD_OVERRIDE_EN + [9:9] + read-write + + + TX_DM_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [8:8] + read-write + + + TX_DP_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [7:7] + read-write + + + TX_DM_OE_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [6:6] + read-write + + + TX_DP_OE_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [5:5] + read-write + + + DM_PULLDN_EN_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [4:4] + read-write + + + DP_PULLDN_EN_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [3:3] + read-write + + + DP_PULLUP_EN_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [2:2] + read-write + + + DM_PULLUP_HISEL_OVERRIDE_EN + [1:1] + read-write + + + DP_PULLUP_HISEL_OVERRIDE_EN + [0:0] + read-write + + + + + USBPHY_TRIM + 0x00000084 + Note that most functions are driven directly from usb_fsls controller. This register allows more detailed control/status from the USB PHY. Useful for debug but not expected to be used in normal operation + 0x00001f1f + + + DM_PULLDN_TRIM + Value to drive to USB PHY + DM pulldown resistor trim control + Experimental data suggests that the reset value will work, but this register allows adjustment if required + [12:8] + read-write + + + DP_PULLDN_TRIM + Value to drive to USB PHY + DP pulldown resistor trim control + Experimental data suggests that the reset value will work, but this register allows adjustment if required + [4:0] + read-write + + + + + INTR + 0x0000008c + Raw Interrupts + 0x00000000 + + + EP_STALL_NAK + Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + [19:19] + read-only + + + ABORT_DONE + Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + [18:18] + read-only + + + DEV_SOF + Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + [17:17] + read-only + + + SETUP_REQ + Device. Source: SIE_STATUS.SETUP_REC + [16:16] + read-only + + + DEV_RESUME_FROM_HOST + Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [15:15] + read-only + + + DEV_SUSPEND + Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + [14:14] + read-only + + + DEV_CONN_DIS + Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + [13:13] + read-only + + + BUS_RESET + Source: SIE_STATUS.BUS_RESET + [12:12] + read-only + + + VBUS_DETECT + Source: SIE_STATUS.VBUS_DETECT + [11:11] + read-only + + + STALL + Source: SIE_STATUS.STALL_REC + [10:10] + read-only + + + ERROR_CRC + Source: SIE_STATUS.CRC_ERROR + [9:9] + read-only + + + ERROR_BIT_STUFF + Source: SIE_STATUS.BIT_STUFF_ERROR + [8:8] + read-only + + + ERROR_RX_OVERFLOW + Source: SIE_STATUS.RX_OVERFLOW + [7:7] + read-only + + + ERROR_RX_TIMEOUT + Source: SIE_STATUS.RX_TIMEOUT + [6:6] + read-only + + + ERROR_DATA_SEQ + Source: SIE_STATUS.DATA_SEQ_ERROR + [5:5] + read-only + + + BUFF_STATUS + Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + [4:4] + read-only + + + TRANS_COMPLETE + Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + [3:3] + read-only + + + HOST_SOF + Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + [2:2] + read-only + + + HOST_RESUME + Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [1:1] + read-only + + + HOST_CONN_DIS + Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + [0:0] + read-only + + + + + INTE + 0x00000090 + Interrupt Enable + 0x00000000 + + + EP_STALL_NAK + Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + [19:19] + read-write + + + ABORT_DONE + Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + [18:18] + read-write + + + DEV_SOF + Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + [17:17] + read-write + + + SETUP_REQ + Device. Source: SIE_STATUS.SETUP_REC + [16:16] + read-write + + + DEV_RESUME_FROM_HOST + Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [15:15] + read-write + + + DEV_SUSPEND + Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + [14:14] + read-write + + + DEV_CONN_DIS + Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + [13:13] + read-write + + + BUS_RESET + Source: SIE_STATUS.BUS_RESET + [12:12] + read-write + + + VBUS_DETECT + Source: SIE_STATUS.VBUS_DETECT + [11:11] + read-write + + + STALL + Source: SIE_STATUS.STALL_REC + [10:10] + read-write + + + ERROR_CRC + Source: SIE_STATUS.CRC_ERROR + [9:9] + read-write + + + ERROR_BIT_STUFF + Source: SIE_STATUS.BIT_STUFF_ERROR + [8:8] + read-write + + + ERROR_RX_OVERFLOW + Source: SIE_STATUS.RX_OVERFLOW + [7:7] + read-write + + + ERROR_RX_TIMEOUT + Source: SIE_STATUS.RX_TIMEOUT + [6:6] + read-write + + + ERROR_DATA_SEQ + Source: SIE_STATUS.DATA_SEQ_ERROR + [5:5] + read-write + + + BUFF_STATUS + Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + [4:4] + read-write + + + TRANS_COMPLETE + Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + [3:3] + read-write + + + HOST_SOF + Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + [2:2] + read-write + + + HOST_RESUME + Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [1:1] + read-write + + + HOST_CONN_DIS + Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + [0:0] + read-write + + + + + INTF + 0x00000094 + Interrupt Force + 0x00000000 + + + EP_STALL_NAK + Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + [19:19] + read-write + + + ABORT_DONE + Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + [18:18] + read-write + + + DEV_SOF + Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + [17:17] + read-write + + + SETUP_REQ + Device. Source: SIE_STATUS.SETUP_REC + [16:16] + read-write + + + DEV_RESUME_FROM_HOST + Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [15:15] + read-write + + + DEV_SUSPEND + Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + [14:14] + read-write + + + DEV_CONN_DIS + Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + [13:13] + read-write + + + BUS_RESET + Source: SIE_STATUS.BUS_RESET + [12:12] + read-write + + + VBUS_DETECT + Source: SIE_STATUS.VBUS_DETECT + [11:11] + read-write + + + STALL + Source: SIE_STATUS.STALL_REC + [10:10] + read-write + + + ERROR_CRC + Source: SIE_STATUS.CRC_ERROR + [9:9] + read-write + + + ERROR_BIT_STUFF + Source: SIE_STATUS.BIT_STUFF_ERROR + [8:8] + read-write + + + ERROR_RX_OVERFLOW + Source: SIE_STATUS.RX_OVERFLOW + [7:7] + read-write + + + ERROR_RX_TIMEOUT + Source: SIE_STATUS.RX_TIMEOUT + [6:6] + read-write + + + ERROR_DATA_SEQ + Source: SIE_STATUS.DATA_SEQ_ERROR + [5:5] + read-write + + + BUFF_STATUS + Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + [4:4] + read-write + + + TRANS_COMPLETE + Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + [3:3] + read-write + + + HOST_SOF + Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + [2:2] + read-write + + + HOST_RESUME + Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [1:1] + read-write + + + HOST_CONN_DIS + Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + [0:0] + read-write + + + + + INTS + 0x00000098 + Interrupt status after masking & forcing + 0x00000000 + + + EP_STALL_NAK + Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + [19:19] + read-only + + + ABORT_DONE + Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + [18:18] + read-only + + + DEV_SOF + Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + [17:17] + read-only + + + SETUP_REQ + Device. Source: SIE_STATUS.SETUP_REC + [16:16] + read-only + + + DEV_RESUME_FROM_HOST + Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [15:15] + read-only + + + DEV_SUSPEND + Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + [14:14] + read-only + + + DEV_CONN_DIS + Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + [13:13] + read-only + + + BUS_RESET + Source: SIE_STATUS.BUS_RESET + [12:12] + read-only + + + VBUS_DETECT + Source: SIE_STATUS.VBUS_DETECT + [11:11] + read-only + + + STALL + Source: SIE_STATUS.STALL_REC + [10:10] + read-only + + + ERROR_CRC + Source: SIE_STATUS.CRC_ERROR + [9:9] + read-only + + + ERROR_BIT_STUFF + Source: SIE_STATUS.BIT_STUFF_ERROR + [8:8] + read-only + + + ERROR_RX_OVERFLOW + Source: SIE_STATUS.RX_OVERFLOW + [7:7] + read-only + + + ERROR_RX_TIMEOUT + Source: SIE_STATUS.RX_TIMEOUT + [6:6] + read-only + + + ERROR_DATA_SEQ + Source: SIE_STATUS.DATA_SEQ_ERROR + [5:5] + read-only + + + BUFF_STATUS + Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + [4:4] + read-only + + + TRANS_COMPLETE + Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + [3:3] + read-only + + + HOST_SOF + Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + [2:2] + read-only + + + HOST_RESUME + Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [1:1] + read-only + + + HOST_CONN_DIS + Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + [0:0] + read-only + + + + + + + USB_DPRAM + DPRAM layout for USB device. + 0x50100000 + + 0 + 256 + registers + + + + SETUP_PACKET_LOW + 0x00000000 + Bytes 0-3 of the SETUP packet from the host. + 0x00000000 + + + WVALUE + [31:16] + read-write + + + BREQUEST + [15:8] + read-write + + + BMREQUESTTYPE + [7:0] + read-write + + + + + SETUP_PACKET_HIGH + 0x00000004 + Bytes 4-7 of the setup packet from the host. + 0x00000000 + + + WLENGTH + [31:16] + read-write + + + WINDEX + [15:0] + read-write + + + + + EP1_IN_CONTROL + 0x00000008 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP1_OUT_CONTROL + 0x0000000c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP2_IN_CONTROL + 0x00000010 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP2_OUT_CONTROL + 0x00000014 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP3_IN_CONTROL + 0x00000018 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP3_OUT_CONTROL + 0x0000001c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP4_IN_CONTROL + 0x00000020 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP4_OUT_CONTROL + 0x00000024 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP5_IN_CONTROL + 0x00000028 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP5_OUT_CONTROL + 0x0000002c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP6_IN_CONTROL + 0x00000030 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP6_OUT_CONTROL + 0x00000034 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP7_IN_CONTROL + 0x00000038 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP7_OUT_CONTROL + 0x0000003c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP8_IN_CONTROL + 0x00000040 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP8_OUT_CONTROL + 0x00000044 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP9_IN_CONTROL + 0x00000048 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP9_OUT_CONTROL + 0x0000004c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP10_IN_CONTROL + 0x00000050 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP10_OUT_CONTROL + 0x00000054 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP11_IN_CONTROL + 0x00000058 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP11_OUT_CONTROL + 0x0000005c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP12_IN_CONTROL + 0x00000060 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP12_OUT_CONTROL + 0x00000064 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP13_IN_CONTROL + 0x00000068 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP13_OUT_CONTROL + 0x0000006c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP14_IN_CONTROL + 0x00000070 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP14_OUT_CONTROL + 0x00000074 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP15_IN_CONTROL + 0x00000078 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP15_OUT_CONTROL + 0x0000007c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP0_IN_BUFFER_CONTROL + 0x00000080 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP0_OUT_BUFFER_CONTROL + 0x00000084 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP1_IN_BUFFER_CONTROL + 0x00000088 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP1_OUT_BUFFER_CONTROL + 0x0000008c + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP2_IN_BUFFER_CONTROL + 0x00000090 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP2_OUT_BUFFER_CONTROL + 0x00000094 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP3_IN_BUFFER_CONTROL + 0x00000098 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP3_OUT_BUFFER_CONTROL + 0x0000009c + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP4_IN_BUFFER_CONTROL + 0x000000a0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP4_OUT_BUFFER_CONTROL + 0x000000a4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP5_IN_BUFFER_CONTROL + 0x000000a8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP5_OUT_BUFFER_CONTROL + 0x000000ac + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP6_IN_BUFFER_CONTROL + 0x000000b0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP6_OUT_BUFFER_CONTROL + 0x000000b4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP7_IN_BUFFER_CONTROL + 0x000000b8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP7_OUT_BUFFER_CONTROL + 0x000000bc + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP8_IN_BUFFER_CONTROL + 0x000000c0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP8_OUT_BUFFER_CONTROL + 0x000000c4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP9_IN_BUFFER_CONTROL + 0x000000c8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP9_OUT_BUFFER_CONTROL + 0x000000cc + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP10_IN_BUFFER_CONTROL + 0x000000d0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP10_OUT_BUFFER_CONTROL + 0x000000d4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP11_IN_BUFFER_CONTROL + 0x000000d8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP11_OUT_BUFFER_CONTROL + 0x000000dc + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP12_IN_BUFFER_CONTROL + 0x000000e0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP12_OUT_BUFFER_CONTROL + 0x000000e4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP13_IN_BUFFER_CONTROL + 0x000000e8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP13_OUT_BUFFER_CONTROL + 0x000000ec + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP14_IN_BUFFER_CONTROL + 0x000000f0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP14_OUT_BUFFER_CONTROL + 0x000000f4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP15_IN_BUFFER_CONTROL + 0x000000f8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP15_OUT_BUFFER_CONTROL + 0x000000fc + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + + + TBMAN + Testbench manager. Allows the programmer to know what platform their software is running on. + 0x4006c000 + + 0 + 4 + registers + + + + PLATFORM + 0x00000000 + Indicates the type of platform in use + 0x00000005 + + + FPGA + Indicates the platform is an FPGA + [1:1] + read-only + + + ASIC + Indicates the platform is an ASIC + [0:0] + read-only + + + + + + + VREG_AND_CHIP_RESET + control and status for on-chip voltage regulator and chip level reset subsystem + 0x40064000 + + 0 + 12 + registers + + + + VREG + 0x00000000 + Voltage regulator control and status + 0x000000b1 + + + ROK + regulation status + 0=not in regulation, 1=in regulation + [12:12] + read-only + + + VSEL + output voltage select + 0000 to 0101 - 0.80V + 0110 - 0.85V + 0111 - 0.90V + 1000 - 0.95V + 1001 - 1.00V + 1010 - 1.05V + 1011 - 1.10V (default) + 1100 - 1.15V + 1101 - 1.20V + 1110 - 1.25V + 1111 - 1.30V + [7:4] + read-write + + + HIZ + high impedance mode select + 0=not in high impedance mode, 1=in high impedance mode + [1:1] + read-write + + + EN + enable + 0=not enabled, 1=enabled + [0:0] + read-write + + + + + BOD + 0x00000004 + brown-out detection control + 0x00000091 + + + VSEL + threshold select + 0000 - 0.473V + 0001 - 0.516V + 0010 - 0.559V + 0011 - 0.602V + 0100 - 0.645V + 0101 - 0.688V + 0110 - 0.731V + 0111 - 0.774V + 1000 - 0.817V + 1001 - 0.860V (default) + 1010 - 0.903V + 1011 - 0.946V + 1100 - 0.989V + 1101 - 1.032V + 1110 - 1.075V + 1111 - 1.118V + [7:4] + read-write + + + EN + enable + 0=not enabled, 1=enabled + [0:0] + read-write + + + + + CHIP_RESET + 0x00000008 + Chip reset control and status + 0x00000000 + + + PSM_RESTART_FLAG + This is set by psm_restart from the debugger. + Its purpose is to branch bootcode to a safe mode when the debugger has issued a psm_restart in order to recover from a boot lock-up. + In the safe mode the debugger can repair the boot code, clear this flag then reboot the processor. + [24:24] + read-write + oneToClear + + + HAD_PSM_RESTART + Last reset was from the debug port + [20:20] + read-only + + + HAD_RUN + Last reset was from the RUN pin + [16:16] + read-only + + + HAD_POR + Last reset was from the power-on reset or brown-out detection blocks + [8:8] + read-only + + + + + + + RTC + Register block to control RTC + 0x4005c000 + + 0 + 48 + registers + + + RTC_IRQ + 25 + + + + CLKDIV_M1 + 0x00000000 + Divider minus 1 for the 1 second counter. Safe to change the value when RTC is not enabled. + 0x00000000 + + + CLKDIV_M1 + [15:0] + read-write + + + + + SETUP_0 + 0x00000004 + RTC setup register 0 + 0x00000000 + + + YEAR + Year + [23:12] + read-write + + + MONTH + Month (1..12) + [11:8] + read-write + + + DAY + Day of the month (1..31) + [4:0] + read-write + + + + + SETUP_1 + 0x00000008 + RTC setup register 1 + 0x00000000 + + + DOTW + Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7 + [26:24] + read-write + + + HOUR + Hours + [20:16] + read-write + + + MIN + Minutes + [13:8] + read-write + + + SEC + Seconds + [5:0] + read-write + + + + + CTRL + 0x0000000c + RTC Control and status + 0x00000000 + + + FORCE_NOTLEAPYEAR + If set, leapyear is forced off. + Useful for years divisible by 100 but not by 400 + [8:8] + read-write + + + LOAD + Load RTC + [4:4] + write-only + + + RTC_ACTIVE + RTC enabled (running) + [1:1] + read-only + + + RTC_ENABLE + Enable RTC + [0:0] + read-write + + + + + IRQ_SETUP_0 + 0x00000010 + Interrupt setup register 0 + 0x00000000 + + + MATCH_ACTIVE + [29:29] + read-only + + + MATCH_ENA + Global match enable. Don't change any other value while this one is enabled + [28:28] + read-write + + + YEAR_ENA + Enable year matching + [26:26] + read-write + + + MONTH_ENA + Enable month matching + [25:25] + read-write + + + DAY_ENA + Enable day matching + [24:24] + read-write + + + YEAR + Year + [23:12] + read-write + + + MONTH + Month (1..12) + [11:8] + read-write + + + DAY + Day of the month (1..31) + [4:0] + read-write + + + + + IRQ_SETUP_1 + 0x00000014 + Interrupt setup register 1 + 0x00000000 + + + DOTW_ENA + Enable day of the week matching + [31:31] + read-write + + + HOUR_ENA + Enable hour matching + [30:30] + read-write + + + MIN_ENA + Enable minute matching + [29:29] + read-write + + + SEC_ENA + Enable second matching + [28:28] + read-write + + + DOTW + Day of the week + [26:24] + read-write + + + HOUR + Hours + [20:16] + read-write + + + MIN + Minutes + [13:8] + read-write + + + SEC + Seconds + [5:0] + read-write + + + + + RTC_1 + 0x00000018 + RTC register 1. + 0x00000000 + + + YEAR + Year + [23:12] + read-only + + + MONTH + Month (1..12) + [11:8] + read-only + + + DAY + Day of the month (1..31) + [4:0] + read-only + + + + + RTC_0 + 0x0000001c + RTC register 0 + Read this before RTC 1! + 0x00000000 + + + DOTW + Day of the week + [26:24] + read-only + modify + + + HOUR + Hours + [20:16] + read-only + modify + + + MIN + Minutes + [13:8] + read-only + modify + + + SEC + Seconds + [5:0] + read-only + modify + + + + + INTR + 0x00000020 + Raw Interrupts + 0x00000000 + + + RTC + [0:0] + read-only + + + + + INTE + 0x00000024 + Interrupt Enable + 0x00000000 + + + RTC + [0:0] + read-write + + + + + INTF + 0x00000028 + Interrupt Force + 0x00000000 + + + RTC + [0:0] + read-write + + + + + INTS + 0x0000002c + Interrupt status after masking & forcing + 0x00000000 + + + RTC + [0:0] + read-only + + + + + + + diff --git a/lib/arch/stm32/stm32f1.rob b/lib/arch/stm32/stm32f1.rob new file mode 100644 index 0000000..0e3dfe2 --- /dev/null +++ b/lib/arch/stm32/stm32f1.rob @@ -0,0 +1,311 @@ + +use intfs.mcu; +use intfs.ports; +use intfs.databus; + +use stm32f1regs; + +type stm32f1 implements mcu { + + uint32 clock() inline { + // TODO: provide 25Mhz and 72Mhz selection + return 8E6; + } + + void set_interruptions(bool enabled) { + return; + } + + a2 implements digitalport { + void mode_input(PIN_MODE mode, INPUT_MODE cnf) inline { + GPIOA_CRL.mode2 = mode; + GPIOA_CRL.cnf2 = cnf; + } + void mode_output(PIN_MODE mode, OUTPUT_MODE cnf) inline { + GPIOA_CRL.mode2 = mode; + GPIOA_CRL.cnf2 = cnf; + } + void mode(port_mode m) { + APB2EN.iopa = true; + if (m == port_mode.input) { + mode_input(PIN_MODE.INPUT, INPUT_MODE.PULLUPDOWN); + } else { + mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.PUSHPULL); + } + } + void set(bool v) inline { GPIOA_ODR.odr2 = v; } + bool get() inline { return GPIOA_IDR.idr2; } + } + + a3 implements digitalport { + void mode_input(PIN_MODE mode, INPUT_MODE cnf) inline { + GPIOA_CRL.mode3 = mode; + GPIOA_CRL.cnf3 = cnf; + } + void mode_output(PIN_MODE mode, OUTPUT_MODE cnf) inline { + GPIOA_CRL.mode3 = mode; + GPIOA_CRL.cnf3 = cnf; + } + void mode(port_mode m) { + APB2EN.iopa = true; + if (m == port_mode.input) { + mode_input(PIN_MODE.INPUT, INPUT_MODE.PULLUPDOWN); + } else { + mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.PUSHPULL); + } + } + void set(bool v) inline { GPIOA_ODR.odr3 = v; } + bool get() inline { return GPIOA_IDR.idr3; } + } + + c13 implements digitalport { + void mode(port_mode m) { + APB2EN.iopc = true; + if (m == port_mode.input) { + GPIOC_CRH.mode13 = PIN_MODE.INPUT; + GPIOC_CRH.cnf13 = INPUT_MODE.PULLUPDOWN; + } else { + GPIOC_CRH.mode13 = PIN_MODE.OUTPUT50MHz; + GPIOC_CRH.cnf13 = OUTPUT_MODE.PUSHPULL; + } + } + void set(bool v) inline { GPIOC_ODR.odr13 = v; } + bool get() inline { return GPIOC_IDR.idr13; } + } + + b6 implements digitalport { + void mode_input(PIN_MODE mode, INPUT_MODE cnf) { + GPIOB_CRL.mode6 = mode; + GPIOB_CRL.cnf6 = cnf; + } + void mode_output(PIN_MODE mode, OUTPUT_MODE cnf) { + GPIOB_CRL.mode6 = mode; + GPIOB_CRL.cnf6 = cnf; + } + void mode(port_mode m) { + APB2EN.iopb = true; + if (m == port_mode.input) { + mode_input(PIN_MODE.INPUT, INPUT_MODE.PULLUPDOWN); + } else { + mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.PUSHPULL); + } + } + void set(bool v) inline { GPIOB_ODR.odr6 = v; } + bool get() inline { return GPIOB_IDR.idr6; } + } + + b7 implements digitalport { + void mode_input(PIN_MODE mode, INPUT_MODE cnf) { + GPIOB_CRL.mode7 = mode; + GPIOB_CRL.cnf7 = cnf; + } + void mode_output(PIN_MODE mode, OUTPUT_MODE cnf) { + GPIOB_CRL.mode7 = mode; + GPIOB_CRL.cnf7 = cnf; + } + void mode(port_mode m) { + APB2EN.iopb = true; + if (m == port_mode.input) { + mode_input(PIN_MODE.INPUT, INPUT_MODE.PULLUPDOWN); + } else { + mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.PUSHPULL); + } + } + void set(bool v) inline { GPIOB_ODR.odr7 = v; } + bool get() inline { return GPIOB_IDR.idr7; } + } + + void wait_us(uint16 us) { + ticks = clock()/1E6 * us; + start_tick = SYSTICK_VAL; + while start_tick - SYSTICK_VAL < ticks; + } + + void wait_ms(uint16 ms) { + while ms > 0 { + wait_us(1000); + ms--; + } + } + + uint32 micros() { + return SYSTICK_VAL / (clock()/1E6); + } + + uint32 millis() { + return micros() / 1000; + } + + spi implements databus { + /* setup hardware SPI at: + xx = MOSI + xx = MISO + xx = SCK */ + void setup(uint32 speed) {} + void enable() {} + void disable() {} + void write(uint8 b) {} + void write_array(int8[] data) {} + uint8 read() { return 0; } + bool has_data() { return false; } + bool start_transaction(uint16 address) { return true; } + void end_transaction() { } + void async_read_to(interrupt_i8 i) {} + + databus_protocol get_protocol() { + return databus_protocol.SPI; + } + } + + uart2 implements databus { + void setup(uint32 baud) { + APB1EN.usart2 = true; // enable usart2 clock + //AHBENR.sdio = true; // enable SDIO clock + APB2EN.afio = true; //? enable alternate function I/O clock + APB2EN.iopa = true; // port A clock + + // set ports a2 (output TX) and a3 (input RX) + a2.mode_output(PIN_MODE.OUTPUT2MHz, OUTPUT_MODE.APUSH_PULL); + a3.mode_input(PIN_MODE.INPUT, INPUT_MODE.FLOATING); + + // assuming reset configuration, that is 8 bits per byte, + // no parity checks, and 1 “stop bit”. + + // set baudrate + uartdiv = clock() / baud; + USART2_BRR.DIV_Fraction = uint4(uartdiv % 16); + USART2_BRR.DIV_Mantissa = uint12(uartdiv / 16); + } + + void async_read_to(interrupt_i8 i) {} + + void enable() { + USART2_CR1.RE = true; // receptor + USART2_CR1.TE = true; // transmiter + USART2_CR1.UE = true; // usart enable + } + + void disable() { + USART2_CR1.UE = false; + } + + void write(uint8 b) inline { + while !USART2_SR.TXE; + USART2_DR.DR = b; + } + + void write_array(int8[] data) { + i = 0u; + while i < data.size { + write(uint8(data[i])); + i++; + } + } + + uint8 read() { + while !USART2_SR.RXNE; + return uint8(USART2_DR.DR); + } + + bool has_data() { + return USART2_SR.RXNE; + } + + bool start_transaction(uint16 address) { return true; } + void end_transaction() {} + + databus_protocol get_protocol() { + return databus_protocol.UART; + } + } + + i2c1 implements databus { + /* + * Supports I2C on pins PB6 and PB7 + */ + + void setup(uint32 speed) { + APB1EN.i2c1 = true; // enable I2C clock + AHBENR.sdio = true; // enable SDIO clock + APB2EN.afio = true; // enable alternate function I/O clock + APB2EN.iopb = true; // port b clock + + // set ports B6 and B7 as alternate function I2C + b6.mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.AOPENDRAIN); + b7.mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.AOPENDRAIN); + + // disable peripheral to configure + I2C1_CR1.pe = false; + + /* How to compute the values below (assuming 8Mhz Clock, PRESCALER=1) + fs == true and duty == true (400Khz) + CCR = ((1/400000)/PRESCALER) / (25/8000000) + CCR = 2500ns/3125ns = 0.8 = ~0 -> won't work at 8Mhz + + fs == true and duty == false (400Khz) + CCR = ((1/400000)/PRESCALER) / (3/8000000) + CCR = 2500ns/375ns = ~6.6667 = ~ 6 + + TRISE calculated by PCLK (in MHz) * 0.3ms + 1 + */ + + I2C1_CCR.fs = true; + //I2C1_CCR.duty = true; + I2C1_CR2.freq = uint6(clock()/1E6); // no APB1 prescaler + I2C1_CCR.ccr = uint12(((1.0/400000)/2) / (3.0/clock())); + I2C1_TRISE = uint16(clock()/1E6*0.3+1); + } + + void async_read_to(interrupt_i8 i) {} + + void enable() { + I2C1_CR1.pe = true; + } + + void disable() { + APB1EN.i2c1 = false; + I2C1_CR1.pe = false; + } + + bool start_transaction(uint16 addr) { + // send start condition + I2C1_CR1.start = true; + while !I2C1_SR1.sb and !I2C1_SR2.msl and !I2C1_SR2.busy; // wait for start + + // send address + I2C1_DR = addr; + while !I2C1_SR1.addr; // wait addr send + + // clear ADDR condition + volatile temp = I2C1_SR2.msl; + + return true; + } + + void end_transaction() { + I2C1_CR1.stop = true; + } + + void write(uint8 b) inline { + I2C1_DR = b; + while !I2C1_SR1.btf; + } + + void write_array(int8[] data) { + i = 0u; + while (i < data.size) { + I2C1_DR = uint8(data[i]); + while !I2C1_SR1.btf; + i++; + } + } + + uint8 read() { return 0; } + + bool has_data() { return false; } + + databus_protocol get_protocol() { + return databus_protocol.I2C; + } + } +} diff --git a/lib/arch/stm32/stm32f1regs.rob b/lib/arch/stm32/stm32f1regs.rob new file mode 100644 index 0000000..261b2e6 --- /dev/null +++ b/lib/arch/stm32/stm32f1regs.rob @@ -0,0 +1,503 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* + * Global Registers + */ + +type SYSTICK_CTRL_t { + enable = false; + tickint = false; + clksource = false; + _res1 = uint5(0); + _res2 = uint8(0); + countflag = uint16(0); +} + +const SCS_BASE = 0xE000E000; + +//register SYSTICK_t SYSTICK at 0xE000E010; +register SYSTICK_CTRL_t SYSTICK_CTRL at 0xE000E010; +register uint32 SYSTICK_LOAD at 0xE000E014; +register uint32 SYSTICK_VAL at 0xE000E018; +register uint32 SYSTICK_CALIB at 0xE000E01C; + + +type AHBENR_t { + dma1 = false; // DMA1 clock enable + dma2 = false; // DMA2 clock enable + sram = false; // SRAM interface clock enable + _res1 = false; + flitf = false; // FLITF clock enable + _res2 = false; + crc = false; // CRC clock enable + _res3 = false; + fsmc = false; // FSMC clock enable + _res4 = false; + sdio = false; // SDIO clock enable + _res5 = uint5(0); + _res6 = uint16(0); +} + +type APB2EN_t { + afio = false; // Alternate function I/O clock enable + _res1 = false; + iopa = false; // I/O port A clock enable + iopb = false; // I/O port B clock enable + iopc = false; // I/O port C clock enable + iopd = false; // I/O port D clock enable + iope = false; // I/O port E clock enable + iopf = false; // I/O port F clock enable + iopg = false; // I/O port G clock enable + adc1 = false; // ADC1 interface clock enable + adc2 = false; // ADC2 interface clock enable + tim1 = false; // TIM1 Timer clock enable + spi1 = false; // SPI1 clock enable + tim8 = false; // TIM8 Timer clock enable + usart1 = false; // USART1 clock enable + adc3 = false; // ADC3 interface clock enable + _res2 = uint16(0); +} + +type APB1EN_t { + tim2 = false; // Timer 2 clock enable + tim3 = false; // Timer 3 clock enable + tim4 = false; // Timer 4 clock enable + tim5 = false; // Timer 5 clock enable + tim6 = false; // Timer 6 clock enable + tim7 = false; // Timer 7 clock enable + _res1 = uint5(0); + wwdg = false; // Window watchdog clock enable + _res2 = uint2(0); + spi2 = false; // SPI2 clock enable + spi3 = false; // SPI3 clock enable + _res3 = false; + usart2 = false; // USART 2 clock enable + usart3 = false; // USART 3 clock enable + usart4 = false; // USART 4 clock enable + usart5 = false; // USART 5 clock enable + i2c1 = false; // I2C 1 clock enable + i2c2 = false; // I2C 2 clock enable + usb = false; // USB clock enable + _res4 = false; + can = false; // CAN clock enable + _res5 = false; + bkp = false; // Backup interface clock enable + pwr = false; // Power interface clock enable + dac = false; // DAC interface clock enable + _res6 = uint2(0); +} + +// AHB peripheral clock enable register +register AHBENR_t AHBENR at 0x40021014; +// APB1 peripheral clock enable register +register APB1EN_t APB1EN at 0x4002101C; +// APB2 peripheral clock enable register +register APB2EN_t APB2EN at 0x40021018; + + +// APB1 peripheral reset register +type APB1RSTR_t { + tim2rst = false; + tim3rst = false; + tim4rst = false; + tim5rst = false; + tim6rst = false; + tim7rst = false; + _res1 = uint5(0); + wwdgrst = false; + _res2 = uint2(0); + spi2rst = false; + spi3rst = false; + _res3 = false; + usart2rst = false; + usart3rst = false; + uart4rst = false; + uart5rst = false; + i2c1rst = false; + i2c2rst = false; + usbrst = false; + _res4 = false; + canrst = false; + _res5 = false; + bkprst = false; + pwrrst = false; + dacrst = false; + _res6 = uint2(0); +} +register APB1RSTR_t APB1RSTR at 0x40021010; + +/*type GPIO_t { + uint32_t CRL; // GPIO port configuration register low, Address offset: 0x00 + uint32_t CRH; // GPIO port configuration register high, Address offset: 0x04 + uint32_t IDR; // GPIO port input data register, Address offset: 0x08 + uint32_t ODR; // GPIO port output data register, Address offset: 0x0C + uint32_t BSRR; // GPIO port bit set/reset register, Address offset: 0x10 + uint32_t BRR; // GPIO port bit reset register, Address offset: 0x14 + uint32_t LCKR; // GPIO port configuration lock register, Address offset: 0x18 +}*/ + +type RCC_t { + cr = uint32(0); // RCC clock control register, Address offset: 0x00 + cfgr = uint32(0); // RCC clock configuration register, Address offset: 0x04 + cir = uint32(0); // RCC clock interrupt register, Address offset: 0x08 + apb2rstr = uint32(0); // RCC APB2 peripheral reset register, Address offset: 0x0C + apb1rstr = uint32(0); // RCC APB1 peripheral reset register, Address offset: 0x10 + ahbenr = uint32(0); // RCC AHB peripheral clock enable register, Address offset: 0x14 + apb2enr = uint32(0); // RCC APB2 peripheral clock enable register, Address offset: 0x18 + apb1enr = uint32(0); // RCC APB1 peripheral clock enable register, Address offset: 0x1C + bdcr = uint32(0); // RCC backup domain control register, Address offset: 0x20 + csr = uint32(0); // RCC control/status register, Address offset: 0x24 + ahbrstr = uint32(0); // RCC AHB peripheral clock reset register, Address offset: 0x28 + cfgr2 = uint32(0); // RCC clock configuration register2, Address offset: 0x2C +} + +type RCC_CR_t { + hsi_on = false; + hsi_rdy = false; + _res1 = false; + hsi_trim = uint5(0); + hsi_call = uint8(0); + hse_on = false; + hse_rdy = false; + hse_byp = false; + css_on = false; + _res2 = uint4(0); + pll_on = false; + pll_rdy = false; + _res3 = uint6(0); +} + +type RCC_CFGR_t { + sw = uint2(0); // System clock switch + sws = uint2(0); + hpre = uint4(0); + ppre1 = uint3(0); + ppre2 = uint3(0); + adc_pre = uint2(0); + pll_src = false; + pll_xtpre = false; + pll_mul = uint4(0); + usb_pre = false; + _res1 = false; + mco = uint3(0); + _res2 = uint5(0); +} + +// +register RCC_t RCC at 0x40021000; +// Clock control register +register RCC_CR_t RCC_CR at 0x40021000; +// Clock configuration register +register RCC_CFGR_t RCC_CFGR at 0x40021004; + + +type FLASH_t { + acr = uint32(0); + keyr = uint32(0); + optkeyr = uint32(0); + sr = uint32(0); + cr = uint32(0); + ar = uint32(0); + _res = uint32(0); + obr = uint32(0); + wrpr = uint32(0); +} + +register FLASH_t FLASH at 0x40022000; + +/* + * PORT registers + */ + +// PORT x Control Register Low (x=A..G) +type GPIOx_CRL_t { + mode0 = uint2(0); + cnf0 = uint2(0); + mode1 = uint2(0); + cnf1 = uint2(0); + mode2 = uint2(0); + cnf2 = uint2(0); + mode3 = uint2(0); + cnf3 = uint2(0); + mode4 = uint2(0); + cnf4 = uint2(0); + mode5 = uint2(0); + cnf5 = uint2(0); + mode6 = uint2(0); + cnf6 = uint2(0); + mode7 = uint2(0); + cnf7 = uint2(0); +} + +// PORT x Control Register High (x=A..G) +type GPIOx_CRH_t { + mode8 = uint2(0); + cnf8 = uint2(0); + mode9 = uint2(0); + cnf9 = uint2(0); + mode10 = uint2(0); + cnf10 = uint2(0); + mode11 = uint2(0); + cnf11 = uint2(0); + mode12 = uint2(0); + cnf12 = uint2(0); + mode13 = uint2(0); + cnf13 = uint2(0); + mode14 = uint2(0); + cnf14 = uint2(0); + mode15 = uint2(0); + cnf15 = uint2(0); +} + +// Port x output data register (x=A..G) +type GPIOx_ODR_t { + odr0 = false; + odr1 = false; + odr2 = false; + odr3 = false; + odr4 = false; + odr5 = false; + odr6 = false; + odr7 = false; + odr8 = false; + odr9 = false; + odr10 = false; + odr11 = false; + odr12 = false; + odr13 = false; + odr14 = false; + odr15 = false; + _res = uint16(0); +} + +// Port x input data register (x=A..G) +type GPIOx_IDR_t { + idr0 = false; + idr1 = false; + idr2 = false; + idr3 = false; + idr4 = false; + idr5 = false; + idr6 = false; + idr7 = false; + idr8 = false; + idr9 = false; + idr10 = false; + idr11 = false; + idr12 = false; + idr13 = false; + idr14 = false; + idr15 = false; + _res = uint16(0); +} + + +// GPIO PORT A base address +const GPIO_PORTA_BASE = 0x40010800; +// PORT A Control Register Low +register GPIOx_CRL_t GPIOA_CRL at 0x40010800; +// PORT A Control Register High +register GPIOx_CRH_t GPIOA_CRH at 0x40010804; +// PORT A Input Data Register +register GPIOx_IDR_t GPIOA_IDR at 0x40010808; +// PORT A Output Data Register +register GPIOx_ODR_t GPIOA_ODR at 0x4001080C; + + +// GPIO PORT B base address +const GPIO_PORTB_BASE = 0x40010C00; +// PORT B Control Register Low +register GPIOx_CRL_t GPIOB_CRL at 0x40010C00; +// PORT B Control Register High +register GPIOx_CRH_t GPIOB_CRH at 0x40010C04; +// PORT B Input Data Register +register GPIOx_IDR_t GPIOB_IDR at 0x40010C08; +// PORT B Output Data Register +register GPIOx_ODR_t GPIOB_ODR at 0x40010C0C; + + +// GPIO PORT C base address +const GPIO_PORTC_BASE = 0x40011000; +// PORT C Control Register Low +register GPIOx_CRL_t GPIOC_CRL at 0x40011000; +// PORT C Control Register High +register GPIOx_CRH_t GPIOC_CRH at 0x40011004; +// PORT C Input Data Register +register GPIOx_IDR_t GPIOC_IDR at 0x40011008; +// PORT C Output Data Register +register GPIOx_ODR_t GPIOC_ODR at 0x4001100C; + + +enum PIN_MODE {INPUT = 0x0, OUTPUT10MHz = 0x1, OUTPUT2MHz = 0x2, OUTPUT50MHz = 0x3 } +enum INPUT_MODE {ANALOG = 0x0, FLOATING = 0x1, PULLUPDOWN = 0x2 } +enum OUTPUT_MODE {PUSHPULL = 0x0, OPENDRAIN = 0x1, APUSH_PULL = 0x2, AOPENDRAIN = 0x3 } + + +/* + * I2C Registers + */ + +type I2C_CR1_t { + pe = false; // peripheral enable + smbus = false; // true = SMBus mode = true, false = I2C + _res1 = false; + smbtype = false; // false = SMBus device, SMBus Host + enarp = false; // ARP enable + enpec = false; // PEC enable + engc = false; // General call enable + nostretch = false; // Clock stretching disable (0=enabled) + start = false; // Start generation + stop = false; // Stop generation + ack = false; // Acknowledge enable + pos = false; // Acknowledge/PEC Position (for data reception) + pec = false; // Packet error checking + alert = false; // SMBus alert + _res2 = false; + swrst = false; // Software reset +} + +type I2C_CR2_t { + freq = uint6(0); // Peripheral clock frequency (in Mhz, from 2 to 36) + _res1 = uint2(0); + iterren = false; // Error interrupt enable + itevten = false; // Event interrupt enable + itbufen = false; // Buffer interrupt enable + dmaen = false; // DMA requests enable + last = false; // DMA last transfer + _res2 = uint3(0); +} + +type I2C_SR1_t { + sb = false; // Start bit (Master mode) + addr = false; // Address sent (mastermode) / matched (slave mode) + btf = false; // Byte transfer finished + add10 = false; // 10-bit header sent (Master mode) + stopf = false; // Stop detection (slavemode) + _res1 = false; + rxne = false; // Data register not empty (receivers) + txe = false; // Data register empty (transmitters) + berr = false; // Bus error + arlo = false; // Arbitration lost (master mode) + af = false; // Acknowledge failure + ovr = false; // Overrun/Underrun + pecerr = false; // PEC Error in reception + _res2 = false; + timeout = false; // Timeout or Tlow error + smbalert = false; // SMBus alert +} + +type I2C_SR2_t { + msl = false; // Master/slave + busy = false; // Bus busy + tra = false; // Transmitter/receiver false=data bytes received, true=data bytes transmited + _res = false; + gencall = false; // General call address (Slave mode) + smbdefault = false; // SMBus device default address (Slave mode) + smbhost = false; // SMBus host header (Slave mode) + dualf = false; // Dual flag (Slave mode) + pec = uint8(0); // Packet error checking register +} + +type I2C_CCR_t { + ccr = uint12(0); // Clock control register in Fast/Standard mode (Master mode) + _res = uint2(0); + duty = false; // Fast mode duty cycle + fs = false; // I2C master mode selection false=Standard, true=Fast +} + + +// I2C 1 Control 1 Register +register I2C_CR1_t I2C1_CR1 at 0x40005400; +// I2C 1 Control 2 Register +register I2C_CR2_t I2C1_CR2 at 0x40005404; +// I2C 1 Data Register (8 bits) +register uint16 I2C1_DR at 0x40005410; +// I2C 1 Status 1 Register +register I2C_SR1_t I2C1_SR1 at 0x40005414; +// I2C 1 Status 2 Register +register I2C_SR2_t I2C1_SR2 at 0x40005418; +// I2C 1 Clock control register +register I2C_CCR_t I2C1_CCR at 0x4000541C; +// I2C 1 T RISE register +register uint16 I2C1_TRISE at 0x40005420; + +// I2C 2 Control 1 Register +register I2C_CR1_t I2C2_CR1 at 0x40005800; +// I2C 2 Control 2 Register +register I2C_CR2_t I2C2_CR2 at 0x40005804; +// I2C 2 Data Register (8 bits) +register uint16 I2C2_DR at 0x40005810; +// I2C 2 Status 1 Register +register I2C_SR1_t I2C2_SR1 at 0x40005814; +// I2C 2 Status 2 Register +register I2C_SR2_t I2C2_SR2 at 0x40005818; +// I2C 2 Clock control register +register I2C_CCR_t I2C2_CCR at 0x4000581C; +// I2C 2 T RISE register +register uint16 I2C2_TRISE at 0x40005820; + +/* + * USART types + */ + + type SR_t { + PE = false; // Parity error + FE = false; // Framing error + NE = false; // Noise error flag + ORE = false; // Overrun error + IDLE = false; // IDLE line detected + RXNE = false; // Read data register not empty + TC = false; // Transmission complete + TXE = false; // Transmit data register empty + LBD = false; // LIN break detection flag + CTS = false; // CTS flag + _res1 = uint16(0); // Reserved, 22 bits + _res2 = uint6(0); // + } + + type CR1_t { + SBK = false; // Send break + RWU = false; // Receiver wakeup + RE = false; // Receiver enable + TE = false; // Transmitter enable + IDLEIE = false; // IDLE interrupt enable + RXNEIE = false; // RXNE interrupt enable + TCIE = false; // Transmission complete interrupt enable + TXEIE = false; // TXE interrupt enable + PEIE = false; // PE interrupt enable + PS = false; // Parity selection + PCE = false; // Parity control enable + WAKE = false; // Wakeup method + M = false; // Word length + UE = false; // USART enable + _res1 = uint16(0); // Reserved, 18 bits + _res2 = uint2(0); // + } + + type DR_t { + DR = uint9(0); // Data value + _res1 = uint16(0); // Reserved, 23 bits + _res2 = uint7(0); // + } + + type BRR_t { + DIV_Fraction = uint4(0); // fraction of USARTDIV + DIV_Mantissa = uint12(0); // mantissa of USARTDIV + _res1 = uint16(0); // Reserved, 16 bits + } + + // Status register + register SR_t USART2_SR at 0x40004400; + + // Data register + register DR_t USART2_DR at 0x40004404; + + // Baud rate register + register BRR_t USART2_BRR at 0x40004408; + + // Control register 1 + register CR1_t USART2_CR1 at 0x4000440C; + diff --git a/lib/arch/svd2rob.py b/lib/arch/svd2rob.py new file mode 100644 index 0000000..807b4bd --- /dev/null +++ b/lib/arch/svd2rob.py @@ -0,0 +1,273 @@ +# +# This program converts a svd file +# into the types needed to programm +# the board using the Robotics Language +# +# Author: Thiago Borges de Oliveira +# Date: 24-Jun-2024 +# + +import sys +import re +import xml.etree.ElementTree as ET + +tree = ET.parse(sys.argv[1]) +root = tree.getroot() + +header = """ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + * + * This file was machine generated from %s. Don't edit. + */ +""" % sys.argv[1] +print(header) + +peripheral_header = """ +/* Types and registers for {name} {desc} */ +""" + +template_type = """\ + type {type}_t {{ +{fields} + }} +""" + +template_register = """\ + // {prefix_desc}{description} + register {type} {prefix_name}{name} at {addr}; +""" + +template_register_raw = " register {type_raw} {prefix_name}{name}_raw at {addr};\n" + +template_field = "\t{name:<{maxlen}} = {type:<20}// {description}" + + +def clear_description(string): + return " ".join(string.split()) + + +def get_type_for_size(size): + if size <= 8: + return 'uint8' + elif size <= 16: + return 'uint16' + elif size <= 32: + return 'uint32' + else: + return 'uint64' + + +def get_field_for_type(string): + bits = re.search(r"\[(\d+):(\d+)\]", string) + field = {} + field['start'] = int(bits.group(2)) + field['end'] = int(bits.group(1)) + size = field['end'] - field['start'] + 1 + if size == 1: + field['type'] = 'false;' + else: + field['type'] = 'uint' + str(size) + '(0);' + return field + + +def add_reserved(reservedfields, start, size, resnum): + fres = {} + fres['name'] = f'_res{resnum}' + fres['description'] = f'Reserved, {size} bits' + if size == 1: + fres['type'] = "false;" + else: + fres['type'] = f"uint{size}(0);" + fres['start'] = start + reservedfields.append(fres) + + +def print_field_enumeration(register_name, field, enum_node): + enum_values = list(enum_node.iter('enumeratedValue')) + last = len(enum_values)-1 + maxlen = max([len(f.find('name').text) + len(f.find('value').text) for f in enum_values]) + + print(f" enum {register_name}_{field['name']} {{") + for i, enum_value in enumerate(enum_values): + name = enum_value.find('name').text + if name[0] >= '0' and name[0] <= '9': + name = "_" + name + value = enum_value.find('value').text + desc = enum_value.find('description') + desc = '' if desc is None else desc.text + comma = '' if i == last else ',' + leftstr = f"\t{name} = {value}{comma}" + print(f"{leftstr:<{maxlen+6}} // {desc}") + print(" }\n") + + +def get_fields_str(register_name, fields_node, size): + if fields_node == None: + return "" + + fields = [] + for field_node in fields_node.iter('field'): + bitRange = field_node.find('bitRange') + if bitRange == None: + bitOffset = field_node.find('bitOffset').text + bitWidth = field_node.find('bitWidth').text + bitRange = "[%d:%s]" % (int(bitOffset) + int(bitWidth)-1, bitOffset) + else: + bitRange = bitRange.text + field = get_field_for_type(bitRange) + field['name'] = field_node.find('name').text + + field['description'] = '' + description_node = field_node.find('description') + if description_node is not None: + field['description'] = clear_description(description_node.text) + + enum_node = field_node.find('enumeratedValues') + if enum_node is not None: + print_field_enumeration(register_name, field, enum_node) + + fields.append(field) + + fields = sorted(fields, key=lambda field: field['start']) + + # add missing fields as reserved + reservedfields = [] + i = 0 + resnum = 1 + for f in fields: + if f['start'] > i: + #print("start: %d, i: %d\n" % (f['start'], i)) + add_reserved(reservedfields, i, f['start']-i, resnum) + resnum = resnum + 1 + i = f['end'] + 1 + + # missing bits at end + if i < size: + add_reserved(reservedfields, i-1, size-i, resnum) + + fields = fields + reservedfields + maxlen = max([len(f['name']) for f in fields]) + fields = sorted(fields, key=lambda field: field['start']) + return "\n".join([template_field.format(**f, maxlen=maxlen) for f in fields]) + + +# map dependencies to generate peripherals prefixes +derived = {} +for peripheral in root.iterfind('.//peripheral[@derivedFrom]'): + name = peripheral.find('name').text + derivedFrom = peripheral.attrib['derivedFrom'] + derived[name] = derivedFrom + # register the inherited peripheral to prefix it latter + derived[derivedFrom] = derivedFrom + + +# map repeated register names +repeated_regs = {} +for register in root.iterfind('.//register'): + name = register.find('name').text + if name in repeated_regs: + repeated_regs[name] = True + else: + repeated_regs[name] = False + + +# generate code! +def print_tags(tags): + for t in tags: + node = root.find(t) + if node is not None: + print("\t%s: %s" % (t, node.text)) + +print("/*") +print_tags(['vendor', 'name', 'series', 'version', 'description', 'width', 'size']) +print("*/") + +default_size = int(root.find('width').text) + +for peripheral in root.iter('peripheral'): + # peripheral name + pname = peripheral.find('name').text + + # peripheral description + pdesc_node = peripheral.find('description') + pdesc = '' + if pdesc_node is not None: + pdesc = "\n " + clear_description(pdesc_node.text) + "\n" + + # peripheral base address + baseAddr = peripheral.find('baseAddress').text + + # print peripheral header + print(peripheral_header.format(name=pname,desc=pdesc)) + + # prefix base and derived peripherals registers + prefix_name = '' + prefix_desc = '' + if pname in derived: + prefix_name = pname + "_" + prefix_desc = pname + " " + + # loop through base registers + registers = None + isDerived = False + if (pname in derived) and (derived[pname] != pname): + isDerived = True + # change the peripheral to the inherited one + peripheral = root.find(".//peripheral[name = '%s']" % derived[pname]) + + for register in peripheral.iter('register'): + regdata = {} + regdata['prefix_desc'] = prefix_desc + regdata['prefix_name'] = prefix_name + regdata['name'] = register.find('name').text + + if repeated_regs[regdata['name']] and not isDerived: + # The register being created exists in more than one peripheral + # Thus, we prefix it with the peripheral name + regdata['name'] = pname + '_' + regdata['name'] + + if isDerived: + original_register = register.find('name').text + inherited_name = '' + if repeated_regs[original_register]: + inherited_name = peripheral.find('name').text + "_" + regdata['type'] = inherited_name + register.find('name').text + else: + regdata['type'] = regdata['name'] + + regdata['description'] = '' + description_node = register.find('description') + if description_node is not None: + regdata['description'] = clear_description(description_node.text) + + offset = register.find('addressOffset').text + intoffset = int(offset, 16) + if intoffset == 0: + regdata['addr'] = "%s" % (baseAddr) + else: + intaddr = int(baseAddr, 16) + intoffset + regdata['addr'] = "%#x" % (intaddr) + + # print register tree + size = 0 + size_node = register.find('size') + if size_node is not None: + size = int(size_node.text, 0) + else: + size = default_size + regdata['type_raw'] = get_type_for_size(size) + + fields = register.find('fields') + if fields == None: + regdata['type'] = get_type_for_size(size) + print(template_register.format(**regdata)) + else: + if not isDerived: + regdata['fields'] = get_fields_str(regdata['name'], fields, size) + print(template_type.format(**regdata)) + regdata['type'] = regdata['type'] + "_t" + print(template_register.format(**regdata), end="") + print(template_register_raw.format(**regdata)) + diff --git a/lib/arm-eabi-libgcc.a b/lib/arm-eabi-libgcc.a new file mode 100644 index 0000000..bed37c8 Binary files /dev/null and b/lib/arm-eabi-libgcc.a differ diff --git a/lib/arm-missing.c b/lib/arm-missing.c new file mode 100644 index 0000000..93f3ef8 --- /dev/null +++ b/lib/arm-missing.c @@ -0,0 +1,16 @@ + +void abort (void) { + while(1); +} + +void *memcpy(void *dst, const void *src, unsigned int len) +{ + const char *s = src; + char *d = dst; + + while (len--) + *d++ = *s++; + + return dst; +} + diff --git a/lib/assert.rob b/lib/assert.rob new file mode 100644 index 0000000..314cb94 --- /dev/null +++ b/lib/assert.rob @@ -0,0 +1,17 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* + * An assertion function that loops infinitely if the tested condition is false. + * The noinline attribute maintains the caller function in the stack + * (even for interrupts), easing the identification of the cause. + * The debugonly attribute ensures that the function is compiled only + * while debugging (-g) + */ + +void assert(bool a, char[] message) noinline, debugonly { + volatile x = message; + if (!a) { loop {} } +} \ No newline at end of file diff --git a/lib/atmega1284p.ld b/lib/atmega1284p.ld new file mode 100644 index 0000000..1c114b9 --- /dev/null +++ b/lib/atmega1284p.ld @@ -0,0 +1,17 @@ +/* + * RobCmp linker script for atmega1284p + */ + +MEMORY +{ + text (rx) : ORIGIN = 0, LENGTH = 128K + data (rw!x) : ORIGIN = 0x800100, LENGTH = 16K + eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 4K + fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K + lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K + signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K + user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = 1K +} + +INCLUDE avr5.ld + diff --git a/lib/atmega1284p.rob b/lib/atmega1284p.rob new file mode 100644 index 0000000..7bab194 --- /dev/null +++ b/lib/atmega1284p.rob @@ -0,0 +1,147 @@ +/* + * Robcmp interruptions vector for atmega1284p + */ + +int8 main(); + +void __do_copy_data() naked { +asm " + ldi r17, hi8(__data_end) + ldi r26, lo8(__data_start) + ldi r27, hi8(__data_start) + ldi r30, lo8(__data_load_start) + ldi r31, hi8(__data_load_start) + rjmp __do_copy_data_start + __do_copy_data_loop: + lpm r0, Z+ + st X+, r0 + __do_copy_data_start: + cpi r26, lo8(__data_end) + cpc r27, r17 + brne __do_copy_data_loop + ret"; +} + +void __do_clear_bss() naked { +asm " + ldi r17, hi8(__bss_end) + ldi r26, lo8(__bss_start) + ldi r27, hi8(__bss_start) + rjmp __do_clear_bss_start + __do_clear_bss_loop: + st X+, r1 + __do_clear_bss_start: + cpi r26, lo8(__bss_end) + cpc r27, r17 + brne __do_clear_bss_loop + ret"; +} + +void __delay_us() naked { +asm " + ldi r18, 5 + __delay_ms_loop: + dec r18 + brne __delay_ms_loop + nop + ret"; +} + +/* Weak definitions for supported interruptions + */ + void irq_usart_rx() naked, weak, section __irqs { } + void irq_usart_tx() naked, weak, section __irqs { } + +/* Timer0 is used to provide milliseconds time readings + */ + const fcpu = 16E6; + const cycles_per_us = fcpu / 1E6; + const usec_per_ovf = (64 * 256) / cycles_per_us; + const millis_per_ovf = usec_per_ovf / 1000; + const millis_frac_per_ovf = uint16(usec_per_ovf % 1000); + timer0_millis = uint32(0); + timer0_fract = uint16(0); + + void irq_timer0_ovf() signal, weak, section __irqs { + timer0_millis += millis_per_ovf; + timer0_fract += millis_frac_per_ovf; + if (timer0_fract > 1000) { + timer0_fract -= 1000; + timer0_millis += 1; + } + } + + register int8 SREG at 0x5f; + + uint32 millis() { + sreg_bkp = SREG; + asm "cli"; + result = timer0_millis; + SREG = sreg_bkp; + return result; + } + +void __default_irq() naked, section __irqs { + asm "jmp __default_irq"; +} + +void __vectors() naked, section __isr { + + /* atmega1284p has 31 interruptions */ + asm "jmp __init"; + asm "jmp __default_irq"; // IRQ0 + asm "jmp __default_irq"; // IRQ1 + asm "jmp __default_irq"; // IRQ2 + asm "jmp __default_irq"; // PCINT0 + asm "jmp __default_irq"; // PCINT1 + asm "jmp __default_irq"; // PCINT2 + asm "jmp __default_irq"; // PCINT3 + asm "jmp __default_irq"; // Watchdog Timer + asm "jmp __default_irq"; // Timer2 Compare A + asm "jmp __default_irq"; // Timer2 Compare B + asm "jmp __default_irq"; // Timer2 Overflow + asm "jmp __default_irq"; // Timer1 Capture + asm "jmp __default_irq"; // Timer1 Compare A + asm "jmp __default_irq"; // Timer1 Compare B + asm "jmp __default_irq"; // Timer1 Overflow + asm "jmp __default_irq"; // Timer0 Compare A + asm "jmp __default_irq"; // Timer0 Compare B + asm "jmp irq_timer0_ovf"; // Timer0 Overflow + asm "jmp __default_irq"; // SPI Transfer Complete + asm "jmp irq_usart_rx"; // USART, RX Complete + asm "jmp __default_irq"; // USART, UDR Empty + asm "jmp irq_usart_tx"; // USART, TX Complete + asm "jmp __default_irq"; // Analog Comparator + asm "jmp __default_irq"; // ADC Conversion + asm "jmp __default_irq"; // EEPROM Ready + asm "jmp __default_irq"; // 2-wire Serial Interface (TWI) + asm "jmp __default_irq"; // Store Program Memory Ready + asm "jmp __default_irq"; // USART1 Rx Complete + asm "jmp __default_irq"; // USART1 Data Register Empty + asm "jmp __default_irq"; // USART1 Tx Complete + + asm "__init:"; + // clear r1 (zero reg) + asm "clr r1"; + // clear sreg + asm "out 0x3f, r1"; + // set stack at 0x40FF (0x100+16K-1) + asm "ldi r28, 0xFF"; + asm "ldi r29, 0x40"; + asm "out 0x3e, r29"; + asm "out 0x3d, r28"; + + // copy global vars init data + __do_copy_data(); + + // clear zeroed global vars + __do_clear_bss(); + + main(); + + // if main returns, disable interruptions and sleep. + // this is used to quit simavr in our tests + asm "cli"; + asm "sleep"; + } + diff --git a/lib/atmega328p.ld b/lib/atmega328p.ld new file mode 100644 index 0000000..150eced --- /dev/null +++ b/lib/atmega328p.ld @@ -0,0 +1,17 @@ +/* + * RobCmp linker script for atmega328p + */ + +MEMORY +{ + text (rx) : ORIGIN = 0, LENGTH = 32K + data (rw!x) : ORIGIN = 0x800100, LENGTH = 2K + eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 1K + fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K + lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K + signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K + user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = 1K +} + +INCLUDE avr5.ld + diff --git a/lib/atmega328p.rob b/lib/atmega328p.rob new file mode 100644 index 0000000..13e4edf --- /dev/null +++ b/lib/atmega328p.rob @@ -0,0 +1,138 @@ +/* + * Robcmp interruptions vector for atmega328p + */ + +int16 main(); + +void __do_copy_data() naked { +asm " + ldi r17, hi8(__data_end) + ldi r26, lo8(__data_start) + ldi r27, hi8(__data_start) + ldi r30, lo8(__data_load_start) + ldi r31, hi8(__data_load_start) + rjmp __do_copy_data_start + __do_copy_data_loop: + lpm r0, Z+ + st X+, r0 + __do_copy_data_start: + cpi r26, lo8(__data_end) + cpc r27, r17 + brne __do_copy_data_loop + ret"; +} + +void __do_clear_bss() naked { +asm " + ldi r17, hi8(__bss_end) + ldi r26, lo8(__bss_start) + ldi r27, hi8(__bss_start) + rjmp __do_clear_bss_start + __do_clear_bss_loop: + st X+, r1 + __do_clear_bss_start: + cpi r26, lo8(__bss_end) + cpc r27, r17 + brne __do_clear_bss_loop + ret"; +} + +/* Weak definitions for supported interruptions + */ + void irq_usart_rx() naked, weak, section __irqs { } + void irq_usart_tx() naked, weak, section __irqs { } + +/* Timer0 is used to provide milliseconds time readings + */ + const fcpu = 16E6; + const cycles_per_us = fcpu / 1E6; + const usec_per_ovf = (64 * 256) / cycles_per_us; + const millis_per_ovf = usec_per_ovf / 1000; + const millis_frac_per_ovf = uint16(usec_per_ovf % 1000); + timer0_millis = uint32(0); + timer0_fract = uint16(0); + +void irq_timer0_ovf() signal, weak, section __irqs { + timer0_millis += millis_per_ovf; + timer0_fract += millis_frac_per_ovf; + if (timer0_fract > 1000) { + timer0_fract -= 1000; + timer0_millis += 1; + } + } + + register int8 SREG at 0x5f; + + uint32 millis() { + sreg_bkp = SREG; + asm "cli"; + result = timer0_millis; + SREG = sreg_bkp; + return result; + } + +void __default_irq() naked, section __irqs { + asm "jmp __default_irq"; +} + +void __vectors() naked, section __isr { + + /* atmega328p has 26 interruptions */ + asm "jmp __init"; + asm "jmp __default_irq"; // IRQ0 + asm "jmp __default_irq"; // IRQ1 + asm "jmp __default_irq"; // PCINT0 + asm "jmp __default_irq"; // PCINT1 + asm "jmp __default_irq"; // PCINT2 + asm "jmp __default_irq"; // Watchdog Timer + asm "jmp __default_irq"; // Timer2 Compare A + asm "jmp __default_irq"; // Timer2 Compare B + asm "jmp __default_irq"; // Timer2 Overflow + asm "jmp __default_irq"; // Timer1 Capture + asm "jmp __default_irq"; // Timer1 Compare A + asm "jmp __default_irq"; // Timer1 Compare B + asm "jmp __default_irq"; // Timer1 Overflow + asm "jmp __default_irq"; // Timer0 Compare A + asm "jmp __default_irq"; // Timer0 Compare B + asm "jmp irq_timer0_ovf"; // Timer0 Overflow + asm "jmp __default_irq"; // SPI Transfer Complete + asm "jmp irq_usart_rx"; // USART, RX Complete + asm "jmp __default_irq"; // USART, UDR Empty + asm "jmp irq_usart_tx"; // USART, TX Complete + asm "jmp __default_irq"; // ADC Conversion + asm "jmp __default_irq"; // EEPROM Ready + asm "jmp __default_irq"; // Analog Comparator + asm "jmp __default_irq"; // 2-wire Serial Interface + asm "jmp __default_irq"; // Store Program Memory Ready + + asm "__init:"; + // clear r1 (zero reg) + asm "clr r1"; + // clear sreg + asm "out 0x3f, r1"; + // set stack at 0x08FF (0x100+2K-1) + asm "ldi r28, 0xFF"; + asm "ldi r29, 0x08"; + asm "out 0x3e, r29"; + asm "out 0x3d, r28"; + + /* same code in .rob, but it produces a larger assembly code + /*register int8 SREG at 0x3f; + register int16 STACK at 0x3d; + SREG = 0; + STACK = 0x08FF;*/ + + // copy global vars init data + __do_copy_data(); + + // clear zeroed global vars + __do_clear_bss(); + + main(); + + // if main returns, disable interruptions and sleep. + // this is used to quit simavr in our tests + asm "cli"; + asm "sleep"; + } + diff --git a/lib/atmega328p.svd b/lib/atmega328p.svd new file mode 100644 index 0000000..5bca166 --- /dev/null +++ b/lib/atmega328p.svd @@ -0,0 +1,3510 @@ + + + Atmel + ATmega328P + 8 + 8 + read-write + 0 + 0xff + + + AC + Analog Comparator + 0x50 + + 0 + 0x100 + registers + + + + ACSR + Analog Comparator Control And Status Register + 0x0 + read-only + + + ACIS + Analog Comparator Interrupt Mode Select bits + [1:0] + + true + + + + VAL_0x00 + Interrupt on Toggle + 0 + + + VAL_0x01 + Reserved + 1 + + + VAL_0x02 + Interrupt on Falling Edge + 2 + + + VAL_0x03 + Interrupt on Rising Edge + 3 + + + + + ACIC + Analog Comparator Input Capture Enable + [2:2] + + + ACIE + Analog Comparator Interrupt Enable + [3:3] + + + ACI + Analog Comparator Interrupt Flag + [4:4] + + + ACO + Analog Compare Output + [5:5] + + + ACBG + Analog Comparator Bandgap Select + [6:6] + + + ACD + Analog Comparator Disable + [7:7] + + + + + DIDR1 + Digital Input Disable Register 1 + 0x2F + + + AIN0D + AIN0 Digital Input Disable + [0:0] + + + AIN1D + AIN1 Digital Input Disable + [1:1] + + + + + + + ADC + Analog-to-Digital Converter + 0x78 + + 0 + 0x100 + registers + + + + ADC + ADC Data Register Bytes + 0x0 + 16 + + + 0 + 65535 + + + + + ADCSRA + The ADC Control and Status register A + 0x2 + read-only + + + ADPS + ADC Prescaler Select Bits + [2:0] + + true + + + + VAL_0x00 + 2 + 0 + + + VAL_0x01 + 2 + 1 + + + VAL_0x02 + 4 + 2 + + + VAL_0x03 + 8 + 3 + + + VAL_0x04 + 16 + 4 + + + VAL_0x05 + 32 + 5 + + + VAL_0x06 + 64 + 6 + + + VAL_0x07 + 128 + 7 + + + + + ADIE + ADC Interrupt Enable + [3:3] + + + ADIF + ADC Interrupt Flag + [4:4] + + + ADATE + ADC Auto Trigger Enable + [5:5] + + + ADSC + ADC Start Conversion + [6:6] + + + ADEN + ADC Enable + [7:7] + + + + + ADCSRB + The ADC Control and Status register B + 0x3 + + + ADTS + ADC Auto Trigger Source bits + [2:0] + + true + + + + VAL_0x00 + Free Running mode + 0 + + + VAL_0x01 + Analog Comparator + 1 + + + VAL_0x02 + External Interrupt Request 0 + 2 + + + VAL_0x03 + Timer/Counter0 Compare Match A + 3 + + + VAL_0x04 + Timer/Counter0 Overflow + 4 + + + VAL_0x05 + Timer/Counter1 Compare Match B + 5 + + + VAL_0x06 + Timer/Counter1 Overflow + 6 + + + VAL_0x07 + Timer/Counter1 Capture Event + 7 + + + + + ACME + <TBD> + [6:6] + + + + + ADMUX + The ADC multiplexer Selection Register + 0x4 + + + MUX + Analog Channel Selection Bits + [3:0] + + true + + + + ADC0 + ADC Single Ended Input pin 0 + 0 + + + ADC1 + ADC Single Ended Input pin 1 + 1 + + + ADC2 + ADC Single Ended Input pin 2 + 2 + + + ADC3 + ADC Single Ended Input pin 3 + 3 + + + ADC4 + ADC Single Ended Input pin 4 + 4 + + + ADC5 + ADC Single Ended Input pin 5 + 5 + + + ADC6 + ADC Single Ended Input pin 6 + 6 + + + ADC7 + ADC Single Ended Input pin 7 + 7 + + + TEMPSENS + Temperature sensor + 8 + + + ADC_VBG + Internal Reference (VBG) + 14 + + + ADC_GND + 0V (GND) + 15 + + + + + ADLAR + Left Adjust Result + [5:5] + + + REFS + Reference Selection Bits + [7:6] + + true + + + + VAL_0x00 + AREF, Internal Vref turned off + 0 + + + VAL_0x01 + AVCC with external capacitor at AREF pin + 1 + + + VAL_0x02 + Reserved + 2 + + + VAL_0x03 + Internal 1.1V Voltage Reference with external capacitor at AREF pin + 3 + + + + + + + DIDR0 + Digital Input Disable Register + 0x6 + + + ADC0D + <TBD> + [0:0] + + + ADC1D + <TBD> + [1:1] + + + ADC2D + <TBD> + [2:2] + + + ADC3D + <TBD> + [3:3] + + + ADC4D + <TBD> + [4:4] + + + ADC5D + <TBD> + [5:5] + + + + + + + CPU + CPU Registers + 0x3E + + 0 + 0x100 + registers + + + + CLKPR + Clock Prescale Register + 0x23 + read-only + + + CLKPS + Clock Prescaler Select Bits + [3:0] + + true + + + + VAL_0x00 + 1 + 0 + + + VAL_0x01 + 2 + 1 + + + VAL_0x02 + 4 + 2 + + + VAL_0x03 + 8 + 3 + + + VAL_0x04 + 16 + 4 + + + VAL_0x05 + 32 + 5 + + + VAL_0x06 + 64 + 6 + + + VAL_0x07 + 128 + 7 + + + VAL_0x08 + 256 + 8 + + + + + CLKPCE + Clock Prescaler Change Enable + [7:7] + + + + + GPIOR0 + General Purpose I/O Register 0 + 0x0 + + + 0 + 255 + + + + + GPIOR1 + General Purpose I/O Register 1 + 0xC + + + 0 + 255 + + + + + GPIOR2 + General Purpose I/O Register 2 + 0xD + + + 0 + 255 + + + + + MCUCR + MCU Control Register + 0x17 + + + IVCE + <TBD> + [0:0] + + + IVSEL + <TBD> + [1:1] + + + PUD + <TBD> + [4:4] + + + BODSE + BOD Sleep Enable + [5:5] + + + BODS + BOD Sleep + [6:6] + + + + + MCUSR + MCU Status Register + 0x16 + + + PORF + Power-on reset flag + [0:0] + + + EXTRF + External Reset Flag + [1:1] + + + BORF + Brown-out Reset Flag + [2:2] + + + WDRF + Watchdog Reset Flag + [3:3] + + + + + OSCCAL + Oscillator Calibration Value + 0x28 + read-only + + + OSCCAL + Oscillator Calibration + [7:0] + + + 0 + 255 + + + + + + + PRR + Power Reduction Register + 0x26 + + 0 + 0x100 + registers + + read-only + + + PRADC + Power Reduction ADC + [0:0] + + + PRUSART0 + Power Reduction USART + [1:1] + + + PRSPI + Power Reduction Serial Peripheral Interface + [2:2] + + + PRTIM1 + Power Reduction Timer/Counter1 + [3:3] + + + PRTIM0 + Power Reduction Timer/Counter0 + [5:5] + + + PRTIM2 + Power Reduction Timer/Counter2 + [6:6] + + + PRTWI + Power Reduction TWI + [7:7] + + + + + SMCR + Sleep Mode Control Register + 0x15 + + + SE + Sleep Enable + [0:0] + + + SM + Sleep Mode Select Bits + [3:1] + + true + + + + IDLE + Idle + 0 + + + ADC + ADC Noise Reduction (If Available) + 1 + + + PDOWN + Power Down + 2 + + + PSAVE + Power Save + 3 + + + VAL_0x04 + Reserved + 4 + + + VAL_0x05 + Reserved + 5 + + + STDBY + Standby + 6 + + + ESTDBY + Extended Standby + 7 + + + + + + + SPMCSR + Store Program Memory Control and Status Register + 0x19 + + + SPMEN + Store Program Memory + [0:0] + + + PGERS + Page Erase + [1:1] + + + PGWRT + Page Write + [2:2] + + + BLBSET + Boot Lock Bit Set + [3:3] + + + RWWSRE + Read-While-Write section read enable + [4:4] + + + SIGRD + Signature Row Read + [5:5] + + + RWWSB + Read-While-Write Section Busy + [6:6] + + + SPMIE + SPM Interrupt Enable + [7:7] + + + + + + RESET + 0 + External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset + + + INT0 + 1 + External Interrupt Request 0 + + + INT1 + 2 + External Interrupt Request 1 + + + PCINT0 + 3 + Pin Change Interrupt Request 0 + + + PCINT1 + 4 + Pin Change Interrupt Request 1 + + + PCINT2 + 5 + Pin Change Interrupt Request 2 + + + WDT + 6 + Watchdog Time-out Interrupt + + + TIMER2_COMPA + 7 + Timer/Counter2 Compare Match A + + + TIMER2_COMPB + 8 + Timer/Counter2 Compare Match B + + + TIMER2_OVF + 9 + Timer/Counter2 Overflow + + + TIMER1_CAPT + 10 + Timer/Counter1 Capture Event + + + TIMER1_COMPA + 11 + Timer/Counter1 Compare Match A + + + TIMER1_COMPB + 12 + Timer/Counter1 Compare Match B + + + TIMER1_OVF + 13 + Timer/Counter1 Overflow + + + TIMER0_COMPA + 14 + TimerCounter0 Compare Match A + + + TIMER0_COMPB + 15 + TimerCounter0 Compare Match B + + + TIMER0_OVF + 16 + Timer/Couner0 Overflow + + + SPI_STC + 17 + SPI Serial Transfer Complete + + + USART_RX + 18 + USART Rx Complete + + + USART_UDRE + 19 + USART, Data Register Empty + + + USART_TX + 20 + USART Tx Complete + + + ADC + 21 + ADC Conversion Complete + + + EE_READY + 22 + EEPROM Ready + + + ANALOG_COMP + 23 + Analog Comparator + + + TWI + 24 + Two-wire Serial Interface + + + SPM_Ready + 25 + Store Program Memory Read + + + + EEPROM + EEPROM + 0x3F + + 0 + 0x100 + registers + + + + EEAR + EEPROM Address Register Bytes + 0x2 + 16 + + + 0 + 65535 + + + + + EECR + EEPROM Control Register + 0x0 + + + EERE + EEPROM Read Enable + [0:0] + + + EEPE + EEPROM Write Enable + [1:1] + + + EEMPE + EEPROM Master Write Enable + [2:2] + + + EERIE + EEPROM Ready Interrupt Enable + [3:3] + + + EEPM + EEPROM Programming Mode Bits + [5:4] + + true + + + + VAL_0x00 + Erase and Write in one operation + 0 + + + VAL_0x01 + Erase Only + 1 + + + VAL_0x02 + Write Only + 2 + + + + + + + EEDR + EEPROM Data Register + 0x1 + + + 0 + 255 + + + + + + + EXINT + External Interrupts + 0x3B + + 0 + 0x100 + registers + + + + EICRA + External Interrupt Control Register + 0x2E + + + ISC0 + External Interrupt Sense Control 0 Bits + [1:0] + + true + + + + VAL_0x00 + Low Level of INTX + 0 + + + VAL_0x01 + Any Logical Change of INTX + 1 + + + VAL_0x02 + Falling Edge of INTX + 2 + + + VAL_0x03 + Rising Edge of INTX + 3 + + + + + ISC1 + External Interrupt Sense Control 1 Bits + [3:2] + + true + + + + VAL_0x00 + Low Level of INTX + 0 + + + VAL_0x01 + Any Logical Change of INTX + 1 + + + VAL_0x02 + Falling Edge of INTX + 2 + + + VAL_0x03 + Rising Edge of INTX + 3 + + + + + + + EIFR + External Interrupt Flag Register + 0x1 + read-only + + + INTF + External Interrupt Flags + [1:0] + + + 0 + 3 + + + + + + + EIMSK + External Interrupt Mask Register + 0x2 + + + INT + External Interrupt Request 1 Enable + [1:0] + + + 0 + 3 + + + + + + + PCICR + Pin Change Interrupt Control Register + 0x2D + + + PCIE + Pin Change Interrupt Enables + [2:0] + + + 0 + 7 + + + + + + + PCIFR + Pin Change Interrupt Flag Register + 0x0 + read-only + + + PCIF + Pin Change Interrupt Flags + [2:0] + + + 0 + 7 + + + + + + + PCMSK0 + Pin Change Mask Register 0 + 0x30 + + + PCINT + Pin Change Enable Masks + [7:0] + + + 0 + 255 + + + + + + + PCMSK1 + Pin Change Mask Register 1 + 0x31 + + + PCINT + Pin Change Enable Masks + [6:0] + + + 0 + 127 + + + + + + + PCMSK2 + Pin Change Mask Register 2 + 0x32 + + + PCINT + Pin Change Enable Masks + [7:0] + + + 0 + 255 + + + + + + + + + FUSE + Fuses + 0x0 + + 0 + 0x100 + registers + + + + EXTENDED + <TBD> + 0x2 + + + BODLEVEL + Brown-out Detector trigger level + [2:0] + + true + + + + 4V3 + Brown-out detection at VCC=4.3 V + 4 + + + 2V7 + Brown-out detection at VCC=2.7 V + 5 + + + 1V8 + Brown-out detection at VCC=1.8 V + 6 + + + DISABLED + Brown-out detection disabled + 7 + + + + + + + HIGH + <TBD> + 0x1 + + + BOOTRST + Boot Reset vector Enabled + [0:0] + + + BOOTSZ + Select boot size + [2:1] + + true + + + + 2048W_3800 + Boot Flash size=2048 words start address=$3800 + 0 + + + 1024W_3C00 + Boot Flash size=1024 words start address=$3C00 + 1 + + + 512W_3E00 + Boot Flash size=512 words start address=$3E00 + 2 + + + 256W_3F00 + Boot Flash size=256 words start address=$3F00 + 3 + + + + + EESAVE + Preserve EEPROM through the Chip Erase cycle + [3:3] + + + WDTON + Watch-dog Timer always on + [4:4] + + + SPIEN + Serial program downloading (SPI) enabled + [5:5] + + + DWEN + Debug Wire enable + [6:6] + + + RSTDISBL + Reset Disabled (Enable PC6 as i/o pin) + [7:7] + + + + + LOW + <TBD> + 0x0 + + + SUT_CKSEL + Select Clock Source + [5:0] + + true + + + + EXTCLK_6CK_14CK_0MS + Ext. Clock; Start-up time PWRDWN/RESET: 6 CK/14 CK + 0 ms + 0 + + + INTRCOSC_8MHZ_6CK_14CK_0MS + Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 0 ms + 2 + + + INTRCOSC_128KHZ_6CK_14CK_0MS + Int. RC Osc. 128kHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 0 ms + 3 + + + EXTLOFXTAL_1KCK_14CK_0MS + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 1K CK/14 CK + 0 ms + 4 + + + EXTLOFXTAL_32KCK_14CK_0MS + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 32K CK/14 CK + 0 ms + 5 + + + EXTFSXTAL_258CK_14CK_4MS1 + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 258 CK/14 CK + 4.1 ms + 6 + + + EXTFSXTAL_1KCK_14CK_65MS + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 1K CK /14 CK + 65 ms + 7 + + + EXTXOSC_0MHZ4_0MHZ9_258CK_14CK_4MS1 + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 4.1 ms + 8 + + + EXTXOSC_0MHZ4_0MHZ9_1KCK_14CK_65MS + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 65 ms + 9 + + + EXTXOSC_0MHZ9_3MHZ_258CK_14CK_4MS1 + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 4.1 ms + 10 + + + EXTXOSC_0MHZ9_3MHZ_1KCK_14CK_65MS + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 65 ms + 11 + + + EXTXOSC_3MHZ_8MHZ_258CK_14CK_4MS1 + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 4.1 ms + 12 + + + EXTXOSC_3MHZ_8MHZ_1KCK_14CK_65MS + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 65 ms + 13 + + + EXTXOSC_8MHZ_XX_258CK_14CK_4MS1 + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 4.1 ms + 14 + + + EXTXOSC_8MHZ_XX_1KCK_14CK_65MS + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 65 ms + 15 + + + EXTCLK_6CK_14CK_4MS1 + Ext. Clock; Start-up time PWRDWN/RESET: 6 CK/14 CK + 4.1 ms + 16 + + + INTRCOSC_8MHZ_6CK_14CK_4MS1 + Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 4.1 ms + 18 + + + INTRCOSC_128KHZ_6CK_14CK_4MS1 + Int. RC Osc. 128kHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 4.1 ms + 19 + + + EXTLOFXTAL_1KCK_14CK_4MS1 + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 1K CK/14 CK + 4.1 ms + 20 + + + EXTLOFXTAL_32KCK_14CK_4MS1 + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 32K CK/14 CK + 4.1 ms + 21 + + + EXTFSXTAL_258CK_14CK_65MS + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 258 CK/14 CK + 65 ms + 22 + + + EXTFSXTAL_16KCK_14CK_0MS + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 16K CK/14 CK + 0 ms + 23 + + + EXTXOSC_0MHZ4_0MHZ9_258CK_14CK_65MS + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 65 ms + 24 + + + EXTXOSC_0MHZ4_0MHZ9_16KCK_14CK_0MS + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 0 ms + 25 + + + EXTXOSC_0MHZ9_3MHZ_258CK_14CK_65MS + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 65 ms + 26 + + + EXTXOSC_0MHZ9_3MHZ_16KCK_14CK_0MS + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 0 ms + 27 + + + EXTXOSC_3MHZ_8MHZ_258CK_14CK_65MS + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 65 ms + 28 + + + EXTXOSC_3MHZ_8MHZ_16KCK_14CK_0MS + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 0 ms + 29 + + + EXTXOSC_8MHZ_XX_258CK_14CK_65MS + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 65 ms + 30 + + + EXTXOSC_8MHZ_XX_16KCK_14CK_0MS + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 0 ms + 31 + + + EXTCLK_6CK_14CK_65MS + Ext. Clock; Start-up time PWRDWN/RESET: 6 CK/14 CK + 65 ms + 32 + + + INTRCOSC_8MHZ_6CK_14CK_65MS + Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 65 ms + 34 + + + INTRCOSC_128KHZ_6CK_14CK_65MS + Int. RC Osc. 128kHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 65 ms + 35 + + + EXTLOFXTAL_1KCK_14CK_65MS + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 1K CK/14 CK + 65 ms + 36 + + + EXTLOFXTAL_32KCK_14CK_65MS + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 32K CK/14 CK + 65 ms + 37 + + + EXTFSXTAL_1KCK_14CK_0MS + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 1K CK /14 CK + 0 ms + 38 + + + EXTFSXTAL_16KCK_14CK_4MS1 + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 16K CK/14 CK + 4.1 ms + 39 + + + EXTXOSC_0MHZ4_0MHZ9_1KCK_14CK_0MS + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 0 ms + 40 + + + EXTXOSC_0MHZ4_0MHZ9_16KCK_14CK_4MS1 + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 4.1 ms + 41 + + + EXTXOSC_0MHZ9_3MHZ_1KCK_14CK_0MS + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 0 ms + 42 + + + EXTXOSC_0MHZ9_3MHZ_16KCK_14CK_4MS1 + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 4.1 ms + 43 + + + EXTXOSC_3MHZ_8MHZ_1KCK_14CK_0MS + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 0 ms + 44 + + + EXTXOSC_3MHZ_8MHZ_16KCK_14CK_4MS1 + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 4.1 ms + 45 + + + EXTXOSC_8MHZ_XX_1KCK_14CK_0MS + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 0 ms + 46 + + + EXTXOSC_8MHZ_XX_16KCK_14CK_4MS1 + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 4.1 ms + 47 + + + EXTFSXTAL_1KCK_14CK_4MS1 + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 1K CK /14 CK + 4.1 ms + 54 + + + EXTFSXTAL_16KCK_14CK_65MS + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms + 55 + + + EXTXOSC_0MHZ4_0MHZ9_1KCK_14CK_4MS1 + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 4.1 ms + 56 + + + EXTXOSC_0MHZ4_0MHZ9_16KCK_14CK_65MS + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms + 57 + + + EXTXOSC_0MHZ9_3MHZ_1KCK_14CK_4MS1 + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 4.1 ms + 58 + + + EXTXOSC_0MHZ9_3MHZ_16KCK_14CK_65MS + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms + 59 + + + EXTXOSC_3MHZ_8MHZ_1KCK_14CK_4MS1 + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 4.1 ms + 60 + + + EXTXOSC_3MHZ_8MHZ_16KCK_14CK_65MS + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms + 61 + + + EXTXOSC_8MHZ_XX_1KCK_14CK_4MS1 + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 4.1 ms + 62 + + + EXTXOSC_8MHZ_XX_16KCK_14CK_65MS + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms + 63 + + + + + CKOUT + Clock output on PORTB0 + [6:6] + + + CKDIV8 + Divide clock by 8 internally + [7:7] + + + + + + + LOCKBIT + Lockbits + 0x0 + + 0 + 0x100 + registers + + + + LOCKBIT + <TBD> + 0x0 + + + LB + Memory Lock + [1:0] + + true + + + + PROG_VER_DISABLED + Further programming and verification disabled + 0 + + + PROG_DISABLED + Further programming disabled + 2 + + + NO_LOCK + No memory lock features enabled + 3 + + + + + BLB0 + Boot Loader Protection Mode + [3:2] + + true + + + + LPM_SPM_DISABLE + LPM and SPM prohibited in Application Section + 0 + + + LPM_DISABLE + LPM prohibited in Application Section + 1 + + + SPM_DISABLE + SPM prohibited in Application Section + 2 + + + NO_LOCK + No lock on SPM and LPM in Application Section + 3 + + + + + BLB1 + Boot Loader Protection Mode + [5:4] + + true + + + + LPM_SPM_DISABLE + LPM and SPM prohibited in Boot Section + 0 + + + LPM_DISABLE + LPM prohibited in Boot Section + 1 + + + SPM_DISABLE + SPM prohibited in Boot Section + 2 + + + NO_LOCK + No lock on SPM and LPM in Boot Section + 3 + + + + + + + + + PORTB + I/O Port + read-write + 8 + 0x23 + + 0 + 0x100 + registers + + + + DDRB + Port B Data Direction Register + 0x1 + + + PB0 + Pin B0 + [0:0] + + + PB1 + Pin B1 + [1:1] + + + PB2 + Pin B2 + [2:2] + + + PB3 + Pin B3 + [3:3] + + + PB4 + Pin B4 + [4:4] + + + PB5 + Pin B5 + [5:5] + + + PB6 + Pin B6 + [6:6] + + + PB7 + Pin B7 + [7:7] + + + + + PINB + Port B Input Pins + 0x0 + + + PB0 + Pin B0 + [0:0] + + + PB1 + Pin B1 + [1:1] + + + PB2 + Pin B2 + [2:2] + + + PB3 + Pin B3 + [3:3] + + + PB4 + Pin B4 + [4:4] + + + PB5 + Pin B5 + [5:5] + + + PB6 + Pin B6 + [6:6] + + + PB7 + Pin B7 + [7:7] + + + + + PORTB + Port B Data Register + 0x2 + + + PB0 + Pin B0 + [0:0] + + + PB1 + Pin B1 + [1:1] + + + PB2 + Pin B2 + [2:2] + + + PB3 + Pin B3 + [3:3] + + + PB4 + Pin B4 + [4:4] + + + PB5 + Pin B5 + [5:5] + + + PB6 + Pin B6 + [6:6] + + + PB7 + Pin B7 + [7:7] + + + + + + + PORTC + I/O Port + read-write + 8 + 0x26 + + 0 + 0x100 + registers + + + + DDRC + Port C Data Direction Register + 0x1 + + + PC0 + Pin C0 + [0:0] + + + PC1 + Pin C1 + [1:1] + + + PC2 + Pin C2 + [2:2] + + + PC3 + Pin C3 + [3:3] + + + PC4 + Pin C4 + [4:4] + + + PC5 + Pin C5 + [5:5] + + + PC6 + Pin C6 + [6:6] + + + + + PINC + Port C Input Pins + 0x0 + + + PC0 + Pin C0 + [0:0] + + + PC1 + Pin C1 + [1:1] + + + PC2 + Pin C2 + [2:2] + + + PC3 + Pin C3 + [3:3] + + + PC4 + Pin C4 + [4:4] + + + PC5 + Pin C5 + [5:5] + + + PC6 + Pin C6 + [6:6] + + + + + PORTC + Port C Data Register + 0x2 + + + PC0 + Pin C0 + [0:0] + + + PC1 + Pin C1 + [1:1] + + + PC2 + Pin C2 + [2:2] + + + PC3 + Pin C3 + [3:3] + + + PC4 + Pin C4 + [4:4] + + + PC5 + Pin C5 + [5:5] + + + PC6 + Pin C6 + [6:6] + + + + + + + PORTD + I/O Port + read-write + 8 + 0x29 + + 0 + 0x100 + registers + + + + DDRD + Port D Data Direction Register + 0x1 + + + PD0 + Pin D0 + [0:0] + + + PD1 + Pin D1 + [1:1] + + + PD2 + Pin D2 + [2:2] + + + PD3 + Pin D3 + [3:3] + + + PD4 + Pin D4 + [4:4] + + + PD5 + Pin D5 + [5:5] + + + PD6 + Pin D6 + [6:6] + + + PD7 + Pin D7 + [7:7] + + + + + PIND + Port D Input Pins + 0x0 + + + PD0 + Pin D0 + [0:0] + + + PD1 + Pin D1 + [1:1] + + + PD2 + Pin D2 + [2:2] + + + PD3 + Pin D3 + [3:3] + + + PD4 + Pin D4 + [4:4] + + + PD5 + Pin D5 + [5:5] + + + PD6 + Pin D6 + [6:6] + + + PD7 + Pin D7 + [7:7] + + + + + PORTD + Port D Data Register + 0x2 + + + PD0 + Pin D0 + [0:0] + + + PD1 + Pin D1 + [1:1] + + + PD2 + Pin D2 + [2:2] + + + PD3 + Pin D3 + [3:3] + + + PD4 + Pin D4 + [4:4] + + + PD5 + Pin D5 + [5:5] + + + PD6 + Pin D6 + [6:6] + + + PD7 + Pin D7 + [7:7] + + + + + + + SPI + Serial Peripheral Interface + 0x4C + + 0 + 0x100 + registers + + + + SPCR + SPI Control Register + 0x0 + + + SPR + SPI Clock Rate Selects + [1:0] + + true + + + + VAL_0x00 + fosc/4 + 0 + + + VAL_0x01 + fosc/16 + 1 + + + VAL_0x02 + fosc/64 + 2 + + + VAL_0x03 + fosc/128 + 3 + + + + + CPHA + Clock Phase + [2:2] + + + CPOL + Clock polarity + [3:3] + + + MSTR + Master/Slave Select + [4:4] + + + DORD + Data Order + [5:5] + + + SPE + SPI Enable + [6:6] + + + SPIE + SPI Interrupt Enable + [7:7] + + + + + SPDR + SPI Data Register + 0x2 + + + 0 + 255 + + + + + SPSR + SPI Status Register + 0x1 + read-only + + + SPI2X + Double SPI Speed Bit + [0:0] + + + WCOL + Write Collision Flag + [6:6] + + + SPIF + SPI Interrupt Flag + [7:7] + + + + + + + TC0 + Timer/Counter, 8-bit + 0x35 + + 0 + 0x100 + registers + + + + GTCCR + General Timer/Counter Control Register + 0xE + + + PSRSYNC + Prescaler Reset Timer/Counter1 and Timer/Counter0 + [0:0] + + + TSM + Timer/Counter Synchronization Mode + [7:7] + + + + + OCR0A + Timer/Counter0 Output Compare Register + 0x12 + + + 0 + 255 + + + + + OCR0B + Timer/Counter0 Output Compare Register + 0x13 + + + 0 + 255 + + + + + TCCR0A + Timer/Counter Control Register A + 0xF + + + WGM0 + Waveform Generation Mode + [1:0] + + + 0 + 3 + + + + + COM0B + Compare Output Mode, Fast PWm + [5:4] + + + 0 + 3 + + + + + COM0A + Compare Output Mode, Phase Correct PWM Mode + [7:6] + + + 0 + 3 + + + + + + + TCCR0B + Timer/Counter Control Register B + 0x10 + + + CS0 + Clock Select + [2:0] + + true + + + + VAL_0x00 + No Clock Source (Stopped) + 0 + + + VAL_0x01 + Running, No Prescaling + 1 + + + VAL_0x02 + Running, CLK/8 + 2 + + + VAL_0x03 + Running, CLK/64 + 3 + + + VAL_0x04 + Running, CLK/256 + 4 + + + VAL_0x05 + Running, CLK/1024 + 5 + + + VAL_0x06 + Running, ExtClk Tx Falling Edge + 6 + + + VAL_0x07 + Running, ExtClk Tx Rising Edge + 7 + + + + + WGM02 + <TBD> + [3:3] + + + FOC0B + Force Output Compare B + [6:6] + + + FOC0A + Force Output Compare A + [7:7] + + + + + TCNT0 + Timer/Counter0 + 0x11 + + + 0 + 255 + + + + + TIFR0 + Timer/Counter0 Interrupt Flag register + 0x0 + read-only + + + TOV0 + Timer/Counter0 Overflow Flag + [0:0] + + + OCF0A + Timer/Counter0 Output Compare Flag 0A + [1:1] + + + OCF0B + Timer/Counter0 Output Compare Flag 0B + [2:2] + + + + + TIMSK0 + Timer/Counter0 Interrupt Mask Register + 0x39 + + + TOIE0 + Timer/Counter0 Overflow Interrupt Enable + [0:0] + + + OCIE0A + Timer/Counter0 Output Compare Match A Interrupt Enable + [1:1] + + + OCIE0B + Timer/Counter0 Output Compare Match B Interrupt Enable + [2:2] + + + + + + + TC1 + Timer/Counter, 16-bit + 0x36 + + 0 + 0x100 + registers + + + + GTCCR + General Timer/Counter Control Register + 0xD + + + PSRSYNC + Prescaler Reset Timer/Counter1 and Timer/Counter0 + [0:0] + + + TSM + Timer/Counter Synchronization Mode + [7:7] + + + + + ICR1 + Timer/Counter1 Input Capture Register Bytes + 0x50 + 16 + + + 0 + 65535 + + + + + OCR1A + Timer/Counter1 Output Compare Register Bytes + 0x52 + 16 + + + 0 + 65535 + + + + + OCR1B + Timer/Counter1 Output Compare Register Bytes + 0x54 + 16 + + + 0 + 65535 + + + + + TCCR1A + Timer/Counter1 Control Register A + 0x4A + + + WGM1 + Waveform Generation Mode + [1:0] + + + 0 + 3 + + + + + COM1B + Compare Output Mode 1B, bits + [5:4] + + + 0 + 3 + + + + + COM1A + Compare Output Mode 1A, bits + [7:6] + + + 0 + 3 + + + + + + + TCCR1B + Timer/Counter1 Control Register B + 0x4B + + + CS1 + Prescaler source of Timer/Counter 1 + [2:0] + + true + + + + VAL_0x00 + No Clock Source (Stopped) + 0 + + + VAL_0x01 + Running, No Prescaling + 1 + + + VAL_0x02 + Running, CLK/8 + 2 + + + VAL_0x03 + Running, CLK/64 + 3 + + + VAL_0x04 + Running, CLK/256 + 4 + + + VAL_0x05 + Running, CLK/1024 + 5 + + + VAL_0x06 + Running, ExtClk Tx Falling Edge + 6 + + + VAL_0x07 + Running, ExtClk Tx Rising Edge + 7 + + + + + WGM1 + Waveform Generation Mode + [4:3] + + + 0 + 3 + + + + + ICES1 + Input Capture 1 Edge Select + [6:6] + + + ICNC1 + Input Capture 1 Noise Canceler + [7:7] + + + + + TCCR1C + Timer/Counter1 Control Register C + 0x4C + + + FOC1B + <TBD> + [6:6] + + + FOC1A + <TBD> + [7:7] + + + + + TCNT1 + Timer/Counter1 Bytes + 0x4E + 16 + + + 0 + 65535 + + + + + TIFR1 + Timer/Counter Interrupt Flag register + 0x0 + read-only + + + TOV1 + Timer/Counter1 Overflow Flag + [0:0] + + + OCF1A + Output Compare Flag 1A + [1:1] + + + OCF1B + Output Compare Flag 1B + [2:2] + + + ICF1 + Input Capture Flag 1 + [5:5] + + + + + TIMSK1 + Timer/Counter Interrupt Mask Register + 0x39 + + + TOIE1 + Timer/Counter1 Overflow Interrupt Enable + [0:0] + + + OCIE1A + Timer/Counter1 Output CompareA Match Interrupt Enable + [1:1] + + + OCIE1B + Timer/Counter1 Output CompareB Match Interrupt Enable + [2:2] + + + ICIE1 + Timer/Counter1 Input Capture Interrupt Enable + [5:5] + + + + + + + TC2 + Timer/Counter, 8-bit Async + 0x37 + + 0 + 0x100 + registers + + + + ASSR + Asynchronous Status Register + 0x7F + + + TCR2BUB + Timer/Counter Control Register2 Update Busy + [0:0] + + + TCR2AUB + Timer/Counter Control Register2 Update Busy + [1:1] + + + OCR2BUB + Output Compare Register 2 Update Busy + [2:2] + + + OCR2AUB + Output Compare Register2 Update Busy + [3:3] + + + TCN2UB + Timer/Counter2 Update Busy + [4:4] + + + AS2 + Asynchronous Timer/Counter2 + [5:5] + + + EXCLK + Enable External Clock Input + [6:6] + + + + + GTCCR + General Timer Counter Control register + 0xC + + + PSRASY + Prescaler Reset Timer/Counter2 + [1:1] + + + TSM + Timer/Counter Synchronization Mode + [7:7] + + + + + OCR2A + Timer/Counter2 Output Compare Register A + 0x7C + + + 0 + 255 + + + + + OCR2B + Timer/Counter2 Output Compare Register B + 0x7D + + + 0 + 255 + + + + + TCCR2A + Timer/Counter2 Control Register A + 0x79 + + + WGM2 + Waveform Genration Mode + [1:0] + + + 0 + 3 + + + + + COM2B + Compare Output Mode bits + [5:4] + + + 0 + 3 + + + + + COM2A + Compare Output Mode bits + [7:6] + + + 0 + 3 + + + + + + + TCCR2B + Timer/Counter2 Control Register B + 0x7A + + + CS2 + Clock Select bits + [2:0] + + true + + + + VAL_0x00 + No Clock Source (Stopped) + 0 + + + VAL_0x01 + Running, No Prescaling + 1 + + + VAL_0x02 + Running, CLK/8 + 2 + + + VAL_0x03 + Running, CLK/32 + 3 + + + VAL_0x04 + Running, CLK/64 + 4 + + + VAL_0x05 + Running, CLK/128 + 5 + + + VAL_0x06 + Running, CLK/256 + 6 + + + VAL_0x07 + Running, CLK/1024 + 7 + + + + + WGM22 + Waveform Generation Mode + [3:3] + + + FOC2B + Force Output Compare B + [6:6] + + + FOC2A + Force Output Compare A + [7:7] + + + + + TCNT2 + Timer/Counter2 + 0x7B + + + 0 + 255 + + + + + TIFR2 + Timer/Counter Interrupt Flag Register + 0x0 + read-only + + + TOV2 + Timer/Counter2 Overflow Flag + [0:0] + + + OCF2A + Output Compare Flag 2A + [1:1] + + + OCF2B + Output Compare Flag 2B + [2:2] + + + + + TIMSK2 + Timer/Counter Interrupt Mask register + 0x39 + + + TOIE2 + Timer/Counter2 Overflow Interrupt Enable + [0:0] + + + OCIE2A + Timer/Counter2 Output Compare Match A Interrupt Enable + [1:1] + + + OCIE2B + Timer/Counter2 Output Compare Match B Interrupt Enable + [2:2] + + + + + + + TWI + Two Wire Serial Interface + 0xB8 + + 0 + 0x100 + registers + + + + TWAMR + TWI (Slave) Address Mask Register + 0x5 + + + TWAM + <TBD> + [7:1] + + + 0 + 127 + + + + + + + TWAR + TWI (Slave) Address register + 0x2 + + + TWGCE + TWI General Call Recognition Enable Bit + [0:0] + + + TWA + TWI (Slave) Address register Bits + [7:1] + + + 0 + 127 + + + + + + + TWBR + TWI Bit Rate register + 0x0 + + + 0 + 255 + + + + + TWCR + TWI Control Register + 0x4 + read-only + + + TWIE + TWI Interrupt Enable + [0:0] + + + TWEN + TWI Enable Bit + [2:2] + + + TWWC + TWI Write Collition Flag + [3:3] + + + TWSTO + TWI Stop Condition Bit + [4:4] + + + TWSTA + TWI Start Condition Bit + [5:5] + + + TWEA + TWI Enable Acknowledge Bit + [6:6] + + + TWINT + TWI Interrupt Flag + [7:7] + + + + + TWDR + TWI Data register + 0x3 + + + 0 + 255 + + + + + TWSR + TWI Status Register + 0x1 + + + TWPS + TWI Prescaler + [1:0] + + true + + + + VAL_0x00 + 1 + 0 + + + VAL_0x01 + 4 + 1 + + + VAL_0x02 + 16 + 2 + + + VAL_0x03 + 64 + 3 + + + + + TWS + TWI Status + [7:3] + + + 0 + 31 + + + + + + + + + USART0 + USART + 0xC0 + + 0 + 0x100 + registers + + + + UBRR0 + USART Baud Rate Register Bytes + 0x4 + 16 + + + 0 + 65535 + + + + + UCSR0A + USART Control and Status Register A + 0x0 + read-only + + + MPCM0 + Multi-processor Communication Mode + [0:0] + + + U2X0 + Double the USART transmission speed + [1:1] + + + UPE0 + Parity Error + [2:2] + + + DOR0 + Data overRun + [3:3] + + + FE0 + Framing Error + [4:4] + + + UDRE0 + USART Data Register Empty + [5:5] + + + TXC0 + USART Transmitt Complete + [6:6] + + + RXC0 + USART Receive Complete + [7:7] + + + + + UCSR0B + USART Control and Status Register B + 0x1 + + + TXB80 + Transmit Data Bit 8 + [0:0] + + + RXB80 + Receive Data Bit 8 + [1:1] + + + UCSZ02 + Character Size + [2:2] + + + TXEN0 + Transmitter Enable + [3:3] + + + RXEN0 + Receiver Enable + [4:4] + + + UDRIE0 + USART Data register Empty Interrupt Enable + [5:5] + + + TXCIE0 + TX Complete Interrupt Enable + [6:6] + + + RXCIE0 + RX Complete Interrupt Enable + [7:7] + + + + + UCSR0C + USART Control and Status Register C + 0x2 + + + UCPOL0 + Clock Polarity + [0:0] + + + UCSZ0 + Character Size + [2:1] + + + 0 + 3 + + + + + USBS0 + Stop Bit Select + [3:3] + + true + + + + VAL_0x00 + 1-bit + 0 + + + VAL_0x01 + 2-bit + 1 + + + + + UPM0 + Parity Mode Bits + [5:4] + + true + + + + VAL_0x00 + Disabled + 0 + + + VAL_0x01 + Reserved + 1 + + + VAL_0x02 + Enabled, Even Parity + 2 + + + VAL_0x03 + Enabled, Odd Parity + 3 + + + + + UMSEL0 + USART Mode Select + [7:6] + + true + + + + VAL_0x00 + Asynchronous USART + 0 + + + VAL_0x01 + Synchronous USART + 1 + + + VAL_0x03 + Master SPI + 3 + + + + + + + UDR0 + USART I/O Data Register + 0x6 + + + 0 + 255 + + + + + + + WDT + Watchdog Timer + 0x60 + + 0 + 0x100 + registers + + + + WDTCSR + Watchdog Timer Control Register + 0x0 + read-only + + + WDP + Watchdog Timer Prescaler Bits + [5:0] + + true + + + + VAL_0x00 + Oscillator Cycles 2K + 0 + + + VAL_0x01 + Oscillator Cycles 4K + 1 + + + VAL_0x02 + Oscillator Cycles 8K + 2 + + + VAL_0x03 + Oscillator Cycles 16K + 3 + + + VAL_0x04 + Oscillator Cycles 32K + 4 + + + VAL_0x05 + Oscillator Cycles 64K + 5 + + + VAL_0x06 + Oscillator Cycles 128K + 6 + + + VAL_0x07 + Oscillator Cycles 256K + 7 + + + + + WDE + Watch Dog Enable + [3:3] + + + WDCE + Watchdog Change Enable + [4:4] + + + WDIE + Watchdog Timeout Interrupt Enable + [6:6] + + + WDIF + Watchdog Timeout Interrupt Flag + [7:7] + + + + + + + \ No newline at end of file diff --git a/lib/avr5.S b/lib/avr5.S new file mode 100644 index 0000000..fa07704 --- /dev/null +++ b/lib/avr5.S @@ -0,0 +1,1381 @@ +/* + * Code excerpt from libgcc + * vim: syntax=nasm + */ + +#define A0 26 +#define B0 18 +#define C0 22 + +#define A1 A0+1 + +#define B1 B0+1 +#define B2 B0+2 +#define B3 B0+3 + +#define C1 C0+1 +#define C2 C0+2 +#define C3 C0+3 + +#define __zero_reg__ r1 +#define __tmp_reg__ r0 + + +.macro DEFUN name +.global \name +#.func \name +\name: +.endm + + +.macro ENDF name +.size \name, .-\name +#.endfunc +.endm + +.macro mov_l r_dest, r_src +movw \r_dest, \r_src +.endm + +.macro mov_h r_dest, r_src +; empty +.endm + +.macro wmov r_dest, r_src + movw \r_dest, \r_src +.endm + + +;;; R25:R22 = (unsigned long) R27:R26 * (unsigned long) R19:R18 +;;; C3:C0 = (unsigned long) A1:A0 * (unsigned long) B1:B0 +;;; Clobbers: __tmp_reg__ +DEFUN __umulhisi3 + mul A0, B0 + movw C0, r0 + mul A1, B1 + movw C2, r0 + mul A0, B1 +;;#ifdef __AVR_HAVE_JMP_CALL__ + ;; This function is used by many other routines, often multiple times. + ;; Therefore, if the flash size is not too limited, avoid the RCALL + ;; and inverst 6 Bytes to speed things up. + add C1, r0 + adc C2, r1 + clr __zero_reg__ + adc C3, __zero_reg__ +;;#else +;; rcall 1f +;;#endif + mul A1, B0 +1: add C1, r0 + adc C2, r1 + clr __zero_reg__ + adc C3, __zero_reg__ + ret +ENDF __umulhisi3 + + +;;; R25:R22 = (unsigned long) R27:R26 * R21:R18 +;;; (C3:C0) = (unsigned long) A1:A0 * B3:B0 +;;; Clobbers: __tmp_reg__ +DEFUN __muluhisi3 + call __umulhisi3 + mul A0, B3 + add C3, r0 + mul A1, B2 + add C3, r0 + mul A0, B2 + add C2, r0 + adc C3, r1 + clr __zero_reg__ + ret +ENDF __muluhisi3 + +/******************************************************* + Multiplication 32 x 32 with MUL +*******************************************************/ + +;;; R25:R22 = R25:R22 * R21:R18 +;;; (C3:C0) = C3:C0 * B3:B0 +;;; Clobbers: R26, R27, __tmp_reg__ +DEFUN __mulsi3 + movw A0, C0 + push C2 + push C3 + call __muluhisi3 + pop A1 + pop A0 + ;; A1:A0 now contains the high word of A + mul A0, B0 + add C2, r0 + adc C3, r1 + mul A0, B1 + add C3, r0 + mul A1, B0 + add C3, r0 + clr __zero_reg__ + ret +ENDF __mulsi3 + +.macro NEG4 reg + com \reg+3 + com \reg+2 + com \reg+1 +.if \reg >= 16 + neg \reg + sbci \reg+1, -1 + sbci \reg+2, -1 + sbci \reg+3, -1 +.else + com \reg + adc \reg, __zero_reg__ + adc \reg+1, __zero_reg__ + adc \reg+2, __zero_reg__ + adc \reg+3, __zero_reg__ +.endif +.endm + +/******************************************************* + Division 32 / 32 => (result + remainder) +*******************************************************/ +#define r_remHH r31 /* remainder High */ +#define r_remHL r30 +#define r_remH r27 +#define r_remL r26 /* remainder Low */ + +/* return: remainder */ +#define r_arg1HH r25 /* dividend High */ +#define r_arg1HL r24 +#define r_arg1H r23 +#define r_arg1L r22 /* dividend Low */ + +/* return: quotient */ +#define r_arg2HH r21 /* divisor High */ +#define r_arg2HL r20 +#define r_arg2H r19 +#define r_arg2L r18 /* divisor Low */ + +#define r_cnt __zero_reg__ /* loop count (0 after the loop!) */ + + +/******************************************************* + Division 8 / 8 => (result + remainder) +*******************************************************/ +#define r_rem r25 /* remainder */ +#define r_arg1 r24 /* dividend, quotient */ +#define r_arg2 r22 /* divisor */ +#define r_ucnt r23 /* loop count */ + +DEFUN __udivmodqi4 + sub r_rem,r_rem ; clear remainder and carry + ldi r_ucnt,9 ; init loop counter + rjmp __udivmodqi4_ep ; jump to entry point +__udivmodqi4_loop: + rol r_rem ; shift dividend into remainder + cp r_rem,r_arg2 ; compare remainder & divisor + brcs __udivmodqi4_ep ; remainder <= divisor + sub r_rem,r_arg2 ; restore remainder +__udivmodqi4_ep: + rol r_arg1 ; shift dividend (with CARRY) + dec r_ucnt ; decrement loop counter + brne __udivmodqi4_loop + com r_arg1 ; complement result + ; because C flag was complemented in loop + ret +ENDF __udivmodqi4 + + +DEFUN __udivmodsi4 + ldi r_remL, 33 ; init loop counter + mov r_cnt, r_remL + sub r_remL,r_remL + sub r_remH,r_remH ; clear remainder and carry + mov_l r_remHL, r_remL + mov_h r_remHH, r_remH + rjmp __udivmodsi4_ep ; jump to entry point +__udivmodsi4_loop: + rol r_remL ; shift dividend into remainder + rol r_remH + rol r_remHL + rol r_remHH + cp r_remL,r_arg2L ; compare remainder & divisor + cpc r_remH,r_arg2H + cpc r_remHL,r_arg2HL + cpc r_remHH,r_arg2HH + brcs __udivmodsi4_ep ; remainder <= divisor + sub r_remL,r_arg2L ; restore remainder + sbc r_remH,r_arg2H + sbc r_remHL,r_arg2HL + sbc r_remHH,r_arg2HH +__udivmodsi4_ep: + rol r_arg1L ; shift dividend (with CARRY) + rol r_arg1H + rol r_arg1HL + rol r_arg1HH + dec r_cnt ; decrement loop counter + brne __udivmodsi4_loop + ; __zero_reg__ now restored (r_cnt == 0) + com r_arg1L + com r_arg1H + com r_arg1HL + com r_arg1HH +; div/mod results to return registers, as for the ldiv() function + mov_l r_arg2L, r_arg1L ; quotient + mov_h r_arg2H, r_arg1H + mov_l r_arg2HL, r_arg1HL + mov_h r_arg2HH, r_arg1HH + mov_l r_arg1L, r_remL ; remainder + mov_h r_arg1H, r_remH + mov_l r_arg1HL, r_remHL + mov_h r_arg1HH, r_remHH + ret +ENDF __udivmodsi4 + + +DEFUN __negsi2 + NEG4 22 + ret +ENDF __negsi2 + + +DEFUN __divmodsi4 + mov __tmp_reg__,r_arg2HH + bst r_arg1HH,7 ; store sign of dividend + brtc 0f + com __tmp_reg__ ; r0.7 is sign of result + call __negsi2 ; dividend negative: negate +0: + sbrc r_arg2HH,7 + rcall __divmodsi4_neg2 ; divisor negative: negate + call __udivmodsi4 ; do the unsigned div/mod + sbrc __tmp_reg__, 7 ; correct quotient sign + rcall __divmodsi4_neg2 + brtc __divmodsi4_exit ; correct remainder sign + jmp __negsi2 +__divmodsi4_neg2: + ;; correct divisor/quotient sign + com r_arg2HH + com r_arg2HL + com r_arg2H + neg r_arg2L + sbci r_arg2H,0xff + sbci r_arg2HL,0xff + sbci r_arg2HH,0xff +__divmodsi4_exit: + ret +ENDF __divmodsi4 + +#undef r_remHH +#undef r_remHL +#undef r_remH +#undef r_remL +#undef r_arg1HH +#undef r_arg1HL +#undef r_arg1H +#undef r_arg1L +#undef r_arg2HH +#undef r_arg2HL +#undef r_arg2H +#undef r_arg2L +#undef r_cnt + +/******************************************************* + Division 16 / 16 => (result + remainder) +*******************************************************/ +#define r_remL r26 /* remainder Low */ +#define r_remH r27 /* remainder High */ + +/* return: remainder */ +#define r_arg1L r24 /* dividend Low */ +#define r_arg1H r25 /* dividend High */ + +/* return: quotient */ +#define r_arg2L r22 /* divisor Low */ +#define r_arg2H r23 /* divisor High */ + +#define r_cnt r21 /* loop count */ + +DEFUN __udivmodhi4 + sub r_remL,r_remL + sub r_remH,r_remH ; clear remainder and carry + ldi r_cnt,17 ; init loop counter + rjmp __udivmodhi4_ep ; jump to entry point +__udivmodhi4_loop: + rol r_remL ; shift dividend into remainder + rol r_remH + cp r_remL,r_arg2L ; compare remainder & divisor + cpc r_remH,r_arg2H + brcs __udivmodhi4_ep ; remainder < divisor + sub r_remL,r_arg2L ; restore remainder + sbc r_remH,r_arg2H +__udivmodhi4_ep: + rol r_arg1L ; shift dividend (with CARRY) + rol r_arg1H + dec r_cnt ; decrement loop counter + brne __udivmodhi4_loop + com r_arg1L + com r_arg1H +; div/mod results to return registers, as for the div() function + mov_l r_arg2L, r_arg1L ; quotient + mov_h r_arg2H, r_arg1H + mov_l r_arg1L, r_remL ; remainder + mov_h r_arg1H, r_remH + ret +ENDF __udivmodhi4 + +DEFUN __divmodhi4 + .global _div +_div: + bst r_arg1H,7 ; store sign of dividend + mov __tmp_reg__,r_arg2H + brtc 0f + com __tmp_reg__ ; r0.7 is sign of result + rcall __divmodhi4_neg1 ; dividend negative: negate +0: + sbrc r_arg2H,7 + rcall __divmodhi4_neg2 ; divisor negative: negate + call __udivmodhi4 ; do the unsigned div/mod + sbrc __tmp_reg__,7 + rcall __divmodhi4_neg2 ; correct remainder sign + brtc __divmodhi4_exit +__divmodhi4_neg1: + ;; correct dividend/remainder sign + com r_arg1H + neg r_arg1L + sbci r_arg1H,0xff + ret +__divmodhi4_neg2: + ;; correct divisor/result sign + com r_arg2H + neg r_arg2L + sbci r_arg2H,0xff +__divmodhi4_exit: + ret +ENDF __divmodhi4 + + +/* memset function for avr, based on avr libc */ +#define dest_hi r25 +#define dest_lo r24 +#define val_lo r22 +#define len_hi r21 +#define len_lo r20 + +DEFUN memset + movw XL, dest_lo + sbrs len_lo, 0 + rjmp .L_memset_start + rjmp .L_memset_odd +.L_memset_loop: + st X+, val_lo +.L_memset_odd: + st X+, val_lo +.L_memset_start: + subi len_lo, lo8(2) + sbci len_hi, hi8(2) + brcc .L_memset_loop + ret +ENDF memset + +/* + * The assembly code below implements float32 functions and was slight + * adapted from avrlibc/libm (https://github.com/avrdudes/avr-libc) + * by thborges, 29-Sep-2024. + */ + +/* Copyright (c) 2002 Michael Stumpf + Copyright (c) 2006 Dmitry Xmelkov + 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 copyright holders nor the names of + 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. */ + +#define rB0 r18 +#define rB1 r19 +#define rB2 r20 +#define rB3 r21 +#define rA0 r22 +#define rA1 r23 +#define rA2 r24 +#define rA3 r25 +#define rBE r26 +#define rAE r27 + + +DEFUN __subsf3 + subi rB3, 0x80 ; complement sign bit of B +DEFUN __addsf3 + clr rAE + clr rBE + rcall __addsf3x + rjmp __fp_round +ENDF __subsf3 + + + + +DEFUN __fp_pscA + clr r0 + dec r0 + cp r1, rA0 + cpc r1, rA1 + cpc r1, rA2 + cpc r0, rA3 + ret +ENDF __fp_pscA + + +DEFUN __fp_pscB + clr r0 + dec r0 + cp r1, rB0 + cpc r1, rB1 + cpc r1, rB2 + cpc r0, rB3 + ret +ENDF __fp_pscB + + +DEFUN __fp_nan + ldi rA3, 0xFF + ldi rA2, 0xC0 + ret +ENDF __fp_nan + + +DEFUN __fp_inf + bld rA3, 7 ; sign + ori rA3, 0x7f + ldi rA2, 0x80 + ldi rA1, 0 + ldi rA0, 0 + ret +ENDF __fp_inf + + +__addsf3xexit: + rcall __fp_pscA + brcs .L_nan + rcall __fp_pscB + brcs .L_nan + brne .L_inf ; B is finite --> return A + cpi rA3, 255 + brne .L_infB ; A is finite --> return B + brtc .L_inf ; Inf + Inf with the same sign +.L_nan: + rjmp __fp_nan +.L_infB: + brtc .L_inf + com ZL +.L_inf: + bst ZL, 7 + rjmp __fp_inf + +DEFUN __addsf3x + mov ZL, rA3 ; save sign of A + rcall __fp_split3 + brcs __addsf3xexit + ; compare A and B + cp rAE, rBE + cpc rA0, rB0 + cpc rA1, rB1 + cpc rA2, rB2 + cpc rA3, rB3 + brlo 2f ; fabs(A) < fabs(B) + brne 4f ; fabs(A) > fabs(B) + brtc .L_add + rjmp __fp_zero ; A + (-A) = +0.0 + ; swap A and B +2: brtc 3f + com ZL ; update sign +3: mov r0, rAE + mov rAE, rBE + mov rBE, r0 + movw r0, rA0 + movw rA0, rB0 + movw rB0, r0 + movw r0, rA2 + movw rA2, rB2 + movw rB2, r0 + clr r1 +4: clr ZH + sub rB3, rA3 +5: breq 7f ; shift is not needed + cpi rB3, -7 + brsh 6f + cpi rB3, -32 + brlo .L_ret + cp r1, rBE + sbci ZH, 0 + mov rBE, rB0 + mov rB0, rB1 + mov rB1, rB2 + clr rB2 + subi rB3, -8 + rjmp 5b + +6: lsr rB2 + ror rB1 + ror rB0 + ror rBE + sbci ZH, 0 + inc rB3 + brne 6b + +7: + ; direction ? + brtc .L_add + ; A -= B + cp r1, ZH + sbc rAE, rBE + sbc rA0, rB0 + sbc rA1, rB1 + sbc rA2, rB2 + brmi .L_ret +8: subi rA3, 1 + breq 9f + lsl ZH + rol rAE + rol rA0 + rol rA1 + rol rA2 + brpl 8b + rjmp .L_ret + +.L_add: + add rAE, rBE + adc rA0, rB0 + adc rA1, rB1 + adc rA2, rB2 + brcc .L_ret + ror rA2 + ror rA1 + ror rA0 + ror rAE + ror ZH + cpi rA3, 254 + brlo 9f + rjmp .L_inf +9: inc rA3 +.L_ret: + lsl rA2 + brcs 1f + clr rA3 +1: lsl ZL ; sign + ror rA3 + ror rA2 + ret +ENDF __addsf3x + + +DEFUN __fp_zero + clt +DEFUN __fp_szero + clr rAE + clr rA0 + clr rA1 + wmov rA2, rA0 + bld rA3, 7 + ret +ENDF __fp_szero + + +DEFUN __fp_split3 + ; rA3[7] := sign(A) ^ sign(B) + sbrc rB3, 7 + subi rA3, 0x80 + ; split B + lsl rB2 + rol rB3 ; exponent + breq 4f + cpi rB3, 0xff ; C = 1, if rB3 != 0xff + breq 5f +1: ror rB2 ; restore rB2 and (possible) hidden bit +; __fp_splitA (float A); +DEFUN __fp_splitA + lsl rA2 +2: bst rA3, 7 + rol rA3 + breq 6f + cpi rA3, 0xff + breq 7f +3: ror rA2 + ret + + ; B is zero or subnormal +4: cp r1, rB0 + cpc r1, rB1 + cpc r1, rB2 ; C = 1, if B is not a zero + rol rB3 ; C = 0 + rjmp 1b + ; B is not a finite +5: lsr rB2 + rcall __fp_splitA + rjmp 8f + + ; A is zero or subnormal +6: cp r1, rA0 + cpc r1, rA1 + cpc r1, rA2 + rol rA3 + rjmp 3b + ; A is not a finite +7: lsr rA2 ; C = 0 + cpc rA1, r1 + cpc rA0, r1 +8: sec + ret +ENDF __fp_split3 + + +DEFUN __fixsfsi + rcall __fixunssfsi + set + cpse rAE, r1 ; error flag + rjmp __fp_szero ; return 0x80000000 + ret +ENDF __fixsfsi + + +DEFUN __fixunssfsi + rcall __fp_splitA + brcs .L_err + ; A is finite + subi rA3, 127 ; exponent field of 1.0 + brlo .L_zr + ; fabs(A) >= 1.0 + mov rAE, rA3 + clr rA3 + subi rAE, 23 + brlo 4f ; shift to right + breq .L_sign ; no shift + ; fabs(A) >= 0x0.800000p+25 To reduce code size we will not check + ; number of shifts. Instead we will check a MSB of result. +1: lsl rA0 + rol rA1 + rol rA2 + rol rA3 + brmi 2f ; next shift is impossible: data lost + dec rAE + brne 1b + rjmp .L_sign + +2: cpi rAE, 1 + breq .L_sign ; rAE: overflow for 'signed long' usage + +.L_err: rcall __fp_zero + ldi rAE, 1 ; error flag + ret + +.L_zr: rjmp __fp_zero ; return 0x00000000, clear rAE + + ; fabs(A) <= 0x0.ffffffp+23 + ; Shift A to right by 1 (rA3==-1) .. 23 (rA3==-23) positions. + +3: mov rA0, rA1 + mov rA1, rA2 + clr rA2 + subi rAE, -8 + breq .L_sign + +4: cpi rAE, -7 + brlt 3b ; quick shift is possible + +5: lsr rA2 + ror rA1 + ror rA0 + inc rAE + brne 5b + + ; restore the sign and return +.L_sign: + brtc 6f + com rA3 + com rA2 + com rA1 + neg rA0 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 +6: ret + +ENDF __fixunssfsi + + +DEFUN __fp_round + ; is A finite ? + mov r0, rA3 + inc r0 + lsl r0 + brne 1f + tst rA2 + brmi 3f ; no, A is not a finite number + ; rounding +1: lsl rAE + brcc 3f + or rAE, ZH + brne 2f + sbrs rA0, 0 ; round to even + rjmp 3f +2: subi rA0, -1 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 + +3: ret +ENDF __fp_round + +#define ret_lo r24 +DEFUN __cmpsf2 +DEFUN __eqsf2 +DEFUN __nesf2 +DEFUN __ltsf2 +DEFUN __lesf2 + rcall __fp_cmp + brcc 1f + ldi ret_lo, 1 +1: ret +ENDF __cmpsf2 + +DEFUN __fp_cmp + lsl rA3 + sbc r0, r0 ; r0 = (A < 0) ? -1 : 0 + lsl rB3 + sbc rBE, rBE ; rBE = (B < 0) ? -1 : 0 + ; isnan(A) ? + ldi ZL, 0x80 ; NaN: 0x{f/7}f800001..0x{f/7}fffffff + ldi ZH, 0xfe + cp r1, rA0 + cpc r1, rA1 + cpc ZL, rA2 + cpc ZH, rA3 + brlo 9f ; branch, if C == 1 + ; isnan(B) ? + cp r1, rB0 + cpc r1, rB1 + cpc ZL, rB2 + cpc ZH, rB3 + brlo 9f ; branch, if C == 1 + ; compare + sub rA0, rB0 + sbc rA1, rB1 + sbc rA2, rB2 + sbc rA3, rB3 ; C is set, if A < B + brne 1f + ; absolute values are equal, check signs + eor r0, rBE + breq 9f ; if branch, rA2 = 0, C = 0 + ; force -0.0 == +0.0 + or rB0, rB1 + or rB0, rB2 + or rB0, rB3 + brne 2f ; evaluate sign(B) + ret + ; view argument signes +1: eor r0, rBE ; C is not changed + brne 2f ; signs are different + sbci rBE, 1 ; rBE[0] = (A < B && A > 0) ? 0 : 1 +2: lsr rBE ; C = above result OR sign(B) + ; build return value, C is set, if A > B + ldi rA2, -1 + adc rA2, r1 + adc rA2, r1 ; C = 0 at any case +9: ret +ENDF __fp_cmp + + +DEFUN __unordsf2 + rcall __fp_cmp ; return C=1, if any of args is NaN + sbc r24, r24 + sbc r25, r25 + ret +ENDF __unordsf2 + + +DEFUN __mulsf3 + rcall __mulsf3x + rjmp __fp_round +ENDF __mulsf3 + + +__mulsf3x_exit: +0: rcall __fp_pscA + brcs 1f + rcall __fp_pscB + brcs 1f + and rA3, rB3 ; one of args is 0xff + breq 1f + rjmp __fp_inf ; nonzero * Inf --> Inf +1: rjmp __fp_nan ; 0 * Inf --> NaN +2: clr r1 ; after 'mul rA3,rB3' + rjmp __fp_szero + +DEFUN __mulsf3x + rcall __fp_split3 + brcs 0b + +DEFUN __mulsf3_pse ; post split entry + ; check zero + mul rA3, rB3 ; r1 would be clean + breq 2b + ; rB3.rA3 := rA3 + rB3 + add rA3, rB3 + ldi rB3, 0 + adc rB3, rB3 + + ; multiplication: rA2.rA1.rA0 * rB2.rB1.rB0 --> rA2.rA1.rA0.rAE.ZH.ZL + + ; ZH.ZL = rA0 * rB0 + mul rA0, rB0 + movw ZL, r0 + ; rAE.ZH += rA1 * rB0 + mul rA1, rB0 + clr rAE + add ZH, r0 + adc rAE, r1 + ; rBE.rAE.ZH = rAE.ZH + rA0 * rB1 + mul rA0, rB1 + clr rBE + add ZH, r0 + adc rAE, r1 + adc rBE, rBE + ; rA0.rBE.rAE = rBE.rAE + rA0 * rB2 + mul rA0, rB2 + clr rA0 + add rAE, r0 + adc rBE, r1 + adc rA0, rA0 + ; rA0.rBE.rAE += rA2 * rB0 + mul rA2, rB0 + clr rB0 + add rAE, r0 + adc rBE, r1 + adc rA0, rB0 + ; rA0.rBE.rAE += rA1 * rB1 + mul rA1, rB1 + add rAE, r0 + adc rBE, r1 + adc rA0, rB0 ; rB0 == 0 + ; rB0.rA0.rBE = rA0.rBE + rA2 * rB1 + mul rA2, rB1 + add rBE, r0 + adc rA0, r1 + adc rB0, rB0 ; rB0 was 0 + ; rB0.rA0.rBE += rA1 * rB2 + mul rA1, rB2 + clr rB1 + add rBE, r0 + adc rA0, r1 + adc rB0, rB1 + ; rB0.rA0 += rA2 * rB2 + mul rA2, rB2 + add rA0, r0 + adc rB0, r1 + ; move result: rA2.rA1.rA0.rAE.ZH.ZL = rB0.rA0.rBE.rAE.ZH.ZL + mov rA2, rB0 + mov rA1, rA0 + mov rA0, rBE + ; __zero_reg__ + clr r1 + + ; exponent -= 127 (Why not 126? For compare convenience.) + subi rA3, 0x7F ;lo8(127) + sbci rB3, 0x00 ;hi8(127) + brmi 13f ; denormalization is needed + breq 15f ; normalization is impossible + ; result exponent > min ==> normalization is possible +10: tst rA2 + brmi 11f ; mantissa is normal + ; mantissa <<= 1 + lsl ZL + rol ZH + rol rAE + rol rA0 + rol rA1 + rol rA2 + ; exponent -= 1 + subi rA3, 0x01 ;lo8(1) + sbci rB3, 0x00 ;hi8(1) + brne 10b + ; check to overflow +11: cpi rA3, 254 + cpc rB3, r1 + brlo 15f + rjmp __fp_inf + ; check lowest value of exponent to avoid long operation +12: rjmp __fp_szero +13: cpi rB3, 0xFF ;hi8(-24) ; here rB3 < 0 + brlt 12b + cpi rA3, 0XE8 ;lo8(-24) + brlt 12b + ; mantissa >>= -rA3 +14: lsr rA2 + ror rA1 + ror rA0 + ror rAE + ror ZH + ror ZL + subi rA3, -1 + brne 14b + ; for rounding +15: or ZH, ZL + ; pack + lsl rA2 + adc rA3, r1 ; restore exponent for normal values + lsr rA3 + ror rA2 + bld rA3, 7 ; sign + ret +ENDF __mulsf3x + + +DEFUN __gesf2 +DEFUN __gtsf2 + rcall __fp_cmp + brcc 1f + ldi ret_lo, -1 +1: ret +ENDF __gesf2 + + +DEFUN __divsf3 + rcall __divsf3x + rjmp __fp_round +ENDF __divsf3 + + +__divsf3x_exit: +0: rcall __fp_pscB + brcs .L_nan_div + rcall __fp_pscA + brcs .L_nan_div + brne .L_zr_div ; finite / Inf --> 0 +.L_infA: + cpi rB3, 255 + breq .L_nan_div ; Inf / Inf --> NaN +.L_inf_div: + rjmp __fp_inf +1: + cpse rB3, r1 ; 0/finite --> 0, 0/0 --> NaN +.L_zr_div: rjmp __fp_szero +.L_nan_div: rjmp __fp_nan + +DEFUN __divsf3x + rcall __fp_split3 + brcs 0b + +DEFUN __divsf3_pse ; post split entry + tst rA3 + breq 1b + tst rB3 + breq .L_inf_div ; finite / 0.0 --> Inf + + sub rA3, rB3 + sbc rB3, rB3 + +/* Prepare to division: + A: rAE.rA2.rA1.rA0 0x00000001..0x00FFFFFF + B: rBE.rB2.rB1.rB0 0x00000002..0x01FFFFFE + A < B + */ + clr rAE + clr rBE +2: cp rA0, rB0 + cpc rA1, rB1 + cpc rA2, rB2 + brlo 3f + subi rA3, 0xFF ;lo8(-1) + sbci rB3, 0xFF ;hi8(-1) + lsl rB0 + rol rB1 + rol rB2 + rol rBE + breq 2b +3: + rcall .L_div + mov r0, ZL + brmi 5f ; N is result of 'com ZL' from .L_div + +4: ldi ZL, 0x80 + rcall .L_div1 + subi rA3, 0x01 ;lo8(1) + sbci rB3, 0x00 ;hi8(1) + lsr ZL + rol r0 + brpl 4b + +5: rcall .L_div + mov ZH, ZL + rcall .L_div + + lsl rA0 + rol rA1 + rol rA2 + rol rAE + cp rB0, rA0 + cpc rB1, rA1 + cpc rB2, rA2 + cpc rBE, rAE + ldi rAE, 0x80 + breq 4f + sbc rAE, rAE + +4: mov rA2, r0 + wmov rA0, ZL + clr ZH + + ; exponent += 125 + subi rA3, 0x83 ;lo8(-125) + sbci rB3, 0xFF ;hi8(-125) + brmi 13f ; denormalization is needed + ; check to overflow +11: cpi rA3, 254 + cpc rB3, r1 + brlo 15f + rjmp __fp_inf + ; check lowest value of exponent to avoid long operation +12: rjmp __fp_szero +13: cpi rB3, 0xFF ;hi8(-24) ; here rB3 < 0 + brlt 12b + cpi rA3, 0xE8 ;lo8(-24) + brlt 12b + ; mantissa >>= -rA3 +14: lsr rA2 + ror rA1 + ror rA0 + ror rAE + ror ZH + subi rA3, -1 + brne 14b + ; pack +15: lsl rA2 + adc rA3, r1 ; restore exponent for normal values + lsr rA3 + ror rA2 + bld rA3, 7 + ret + +.L_div: + ldi ZL, 1 +.L_div1: + lsl rA0 + rol rA1 + rol rA2 + rol rAE + cp rA0, rB0 + cpc rA1, rB1 + cpc rA2, rB2 + cpc rAE, rBE + brcs 2f + sub rA0, rB0 + sbc rA1, rB1 + sbc rA2, rB2 + sbc rAE, rBE +2: rol ZL + brcc .L_div1 + com ZL + ret +ENDF __divsf3x + + +DEFUN __floatdisf + bst rA3, 7 ; sign + brtc 1f + rcall __fp_negdi +1: rjmp __fp_di2sf +ENDF __floatdisf + + +DEFUN __fp_negdi + com rA3 + com rA2 + com rA1 + com rA0 + com rB3 + com rB2 + com rB1 + neg rB0 + sbci rB1, -1 + sbci rB2, -1 + sbci rB3, -1 + sbci rA0, -1 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 + ret +ENDF __fp_negdi + + +DEFUN __floatundisf + clt ; result sign + +DEFUN __fp_di2sf + mov ZH, rA3 + ldi rA3, 127 + 55 ; exponent for 00.80.00.00.00.00.00.00 + tst ZH + breq .L_tstA2 + +/* Shift to right is needed by 1..8 positions. + Optimization: accumulate an info about tail into rB2. */ + cp r1, rB0 + cpc r1, rB1 + cpc r1, rB2 + sbc rB2, rB2 + ; shift to right +1: inc rA3 ; exponent += 1 + lsr ZH + ror rA2 + ror rA1 + ror rA0 + ror rB3 + sbci rB2, 0 ; set rB2[7] if C was 1 + tst ZH + brne 1b + rjmp .L_round + + ; x == 0 +2: clr rA3 + ret + ; check: is fast shift possible? +.L_tstA2: + tst rA2 + brne 4f + ; fast shift to left +3: subi rA3, 8 + brpl 2b ; 127+55 - 7*8 --> 126 + or rA2, rA1 ; obtain Z flag + mov rA1, rA0 + mov rA0, rB3 + mov rB3, rB2 + mov rB2, rB1 + mov rB1, rB0 + ldi rB0, 0 + breq 3b ; Z is result of 'or rA2,rA1' + +/* rA2 is not 0. It is needed shift to left by 0..7 positions. + Optimization: rB2..rB0 are not shifted. Instead, save an info + about tail in rB2. */ +4: cp r1, rB0 + cpc r1, rB1 + cpc r1, rB2 + sbc rB2, rB2 + tst rA2 + brmi .L_round +5: dec rA3 ; exponent -= 1 + lsl rB2 + rol rB3 + rol rA0 + rol rA1 + rol rA2 + brpl 5b + +/* Round and pack. Now we have: + rA3 - mantissa + rA2.rA1.rA0.rB3 - fraction + rB2 - is negative if tail is not equal 0 */ +.L_round: + tst rB3 + brpl 7f + lsl rB2 + rol rB3 + brne 6f + sbrs rA0, 0 ; round to even + rjmp 7f +6: subi rA0, -1 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 + ; pack +7: lsl rA2 + lsr rA3 + ror rA2 + bld rA3, 7 ; sign + ret +ENDF __floatundisf + + +DEFUN __fixsfdi + ldi rAE, 62 + rcall .L_sf2di + brcc 1f + ldi rA3, 0x80 +1: ret + +DEFUN __fixunssfdi + ldi rAE, 63 + +.L_sf2di: + ; clear LSBytes + clr rB0 + clr rB1 + movw rB2, rB0 + ; split + rcall __fp_splitA + brcs .L_ovfl ; is not finite + + subi rA3, 127 ; 1.0 exponent field + brlo .L_zero ; too small + + cp rAE, rA3 + brlo .L_ovfl ; fabs(A) >= 2**64 (or 2**63) + ldi rAE, 63 + sub rAE, rA3 + /* Now rAE is, for example: + 63 - exponent was 127+0, shift >>55 is needed, + 0 - exponent was 127+63, shift <<8 is needed. */ + clr rA3 + subi rAE, 8 ; rAE= -8..+55 + brpl 3f + ; fabs(A) >= 1.0 * 2**56 Shift to left is needed. + /* Shift to 8 is not optimized specially as an exotic. */ +2: lsl rA0 + rol rA1 + rol rA2 + rol rA3 + inc rAE + brmi 2b + rjmp .L_sign2 + ; Shift to right is needed +3: /* Now rAE: + 55 - exponent was 127+0, shift >>55 is needed, + 1 - exponent was 127+54, shift >>1 is needed, + 0 - exponent was 127+55, no shift is needed. */ + subi rAE, 8 + brmi 5f + ; quick shift by 8 +4: mov rB0, rB1 + mov rB1, rB2 + mov rB2, rB3 + mov rB3, rA0 + mov rA0, rA1 + mov rA1, rA2 + clr rA2 + subi rAE, 8 + brpl 4b + +5: subi rAE, -8 ; rAE = 0..7 + breq .L_sign2 + ; shift to 1..7 positions +6: lsr rA2 + ror rA1 + ror rA0 + ror rB3 + ror rB2 + ror rB1 + ror rB0 + dec rAE + brne 6b +.L_sign2: + brtc 7f + rcall __fp_negdi +7: clc + ret + +.L_zero: + clc +.L_ovfl: ; overflow, C is set already + ldi rA0, 0 + ldi rA1, 0 + movw rA2, rA0 + ret +ENDF __fixsfdi + + +DEFUN __floatunsisf + clt + rjmp 1f + +DEFUN __floatsisf + bst rA3, 7 ; sign + brtc 1f + ; negate A + com rA3 + com rA2 + com rA1 + neg rA0 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 +1: + tst rA3 + breq 4f + ; shift to right + mov ZH, rA3 + ldi rA3, 127 + 23 ; exponent + clr rAE +2: inc rA3 + lsr ZH + ror rA2 + ror rA1 + ror rA0 + ror rAE + cpse ZH, r1 + rjmp 2b + ; rounding + brpl .L_pack ; flags from 'ror rAE' + lsl rAE + brne 3f + sbrs rA0, 0 ; round to even + rjmp .L_pack +3: subi rA0, -1 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 + rjmp .L_pack + +4: tst rA2 + breq 5f + ldi rA3, 127 + 23 + rjmp 8f + +5: tst rA1 + breq 6f + ldi rA3, 127 + 15 + mov rA2, rA1 + mov rA1, rA0 + rjmp 7f + +6: tst rA0 + breq 9f ; 0.0 + ldi rA3, 127 + 7 + mov rA2, rA0 + ldi rA1, 0 +7: + ldi rA0, 0 + brmi .L_pack ; flag from 'tst rA*' + ; shift to left by 1..7 positions +10: dec rA3 + lsl rA0 + rol rA1 + rol rA2 +8: brpl 10b + +.L_pack: + lsl rA2 + lsr rA3 + ror rA2 + bld rA3, 7 ; sign +9: ret +ENDF __floatunsisf diff --git a/lib/avr5.ld b/lib/avr5.ld new file mode 100644 index 0000000..af7cb1b --- /dev/null +++ b/lib/avr5.ld @@ -0,0 +1,87 @@ +/* + * RobCmp linker script for avr5 familly + */ + +OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") +OUTPUT_ARCH(avr:5) + +SECTIONS +{ + .text : { + _start = .; + *(__isr) + KEEP(*(__isr)) + . = ALIGN(2); + __text_start = .; + *(__irqs) + KEEP(*(__irqs)) + *(.progmem*) + . = ALIGN(2); + *(.text) + . = ALIGN(2); + *(.text.*) + . = ALIGN(2); + __text_end = . ; + } > text + + .data : { + __data_start = .; + *(.data) + *(.data.*) + KEEP(*(.rodata)) + KEEP(*(.rodata.*)) + __data_end = .; + } > data AT> text + + .bss ADDR(.data) + SIZEOF(.data) : AT (ADDR (.bss)) { + __bss_start = .; + *(.bss) + *(.bss.*) + *(COMMON) + __bss_end = .; + } > data + + __data_load_start = LOADADDR(.data); + + /* will robcmp emits .noinit data? i.e., global vars uninitialized. + this also provides __heap_start, for when we implement malloc. + */ + .noinit ADDR(.bss) + SIZEOF(.bss) : AT (ADDR (.noinit)) { + __noinit_start = .; + *(.noinit*) + __noinit_end = .; + __heap_start = .; + } > data + + /* Global data not cleared after reset. */ + .eeprom : { + KEEP(*(.eeprom*)) + __eeprom_end = . ; + } > eeprom + + .fuse : { + KEEP(*(.fuse)) + KEEP(*(.lfuse)) + KEEP(*(.hfuse)) + KEEP(*(.efuse)) + } > fuse + + .lock : { + KEEP(*(.lock*)) + } > lock + + .signature : { + KEEP(*(.signature*)) + } > signature + + .user_signatures : { + KEEP(*(.user_signatures*)) + } > user_signatures + + /* DWARF 3 */ + .debug_pubtypes 1 : { *(.debug_pubtypes) } + .debug_ranges 1 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 1 : { *(.debug_macro) } +} + diff --git a/lib/avr51.S b/lib/avr51.S new file mode 120000 index 0000000..79240b8 --- /dev/null +++ b/lib/avr51.S @@ -0,0 +1 @@ +avr5.S \ No newline at end of file diff --git a/lib/convert/atoi.rob b/lib/convert/atoi.rob new file mode 100644 index 0000000..62eadd7 --- /dev/null +++ b/lib/convert/atoi.rob @@ -0,0 +1,23 @@ + +int16 atoi(char[] str, int8 base) { + result = int16(0); + i = 0; + negativo = 0; + + while i < str.size and str[i] != 0 { + if str[i] == '-'{ + negativo = 1; + }else if str[i] >= '0' and str[i] <= '9' { + result = result * base + (str[i] - '0'); + } else { + return i; + } + i++; + } + + if negativo == 1{ + result = result * -1; + } + + return result; +} \ No newline at end of file diff --git a/lib/convert/itoa.rob b/lib/convert/itoa.rob new file mode 100644 index 0000000..6d63373 --- /dev/null +++ b/lib/convert/itoa.rob @@ -0,0 +1,51 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +use math.abs; + +const itoa_chars = "0123456789abcdef"; + +uint16 itoa(int16 value, int8 base, char[] result) { + if base < 2 or base > 16 { + result[0] = 0; + return 0; + } + + negative = value < 0; + value = abs16(value); + + i = 0; + if value == 0 { + result[i] = '0'; + i++; + } else { + while value != 0 { + temp = value; + value /= base; + result[i] = itoa_chars[temp - value * base]; + i++; + } + if negative { + result[i] = '-'; + i++; + } + } + + result[i] = 0; + ret = i; + + // reverse result + j = 0; + i--; + while j < i { + temp = result[j]; + result[j] = result[i]; + result[i] = temp; + j++; + i--; + } + + return ret; +} diff --git a/lib/display/ssd1306.rob b/lib/display/ssd1306.rob new file mode 100644 index 0000000..66bb88d --- /dev/null +++ b/lib/display/ssd1306.rob @@ -0,0 +1,258 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +use intfs.mcu; +use intfs.ports; +use intfs.databus; +use intfs.buffer8; +use intfs.display; + +use graphic.envelope; + +type ssd1306 implements display { + mmcu = mcu(); + + // ports used by the SPI display + datacmd = digitalport(); + reset = digitalport(); + select = digitalport(); + + // SPI or I2C bus + dbus = databus(); + + // display address for I2C + address = 0u; + + framebuffer implements buffer8 { + changes = envelope_u16(); + buff = {{0u:128}:8}; + + uint16 height() inline { return buff.rows; } + uint16 width() inline { return buff.cols; } + + void clear() { + row = 0u; + while row < buff.rows { + col = 0u; + while col < buff.cols { + buff[row][col] = 0; + col++; + } + row++; + } + } + + uint8 get(uint16 row, uint16 col) inline { + return buff[row][col]; + } + + void set(uint16 row, uint16 col, uint8 v) inline { + buff[row][col] = v; + changes.expand(col, row); + } + } + + enum powerstate { + SLEEP = 0xAE, + ON = 0xAF + } + + enum i2c_control { + CMD_STREAM = 0x0, + DATA_STREAM = 0x40 + } + + enum commands { + SET_DISP_START_LINE = 0x40, + SET_SEG_REMAP_0 = 0xA0, + SET_SEG_REMAP_127 = 0xA1, + SET_MULTIPLEX_RATIO = 0xA8, + SET_COM_SCAN_NORMAL = 0xC0, + SET_COM_SCAN_INVERTED = 0xC8, + SET_VERTICAL_OFFSET = 0xD3, + SET_WIRING_SCHEME = 0xDA, + SET_DISP_CLOCK = 0xD5, + SET_PRECHARGE_PERIOD = 0xD9, + SET_VCOM_DESELECT_LEVEL = 0xDB, + SET_CONTRAST = 0x81, + RESUME_TO_RAM_CONTENT = 0xA4, + DISPLAY_MODE_NORMAL = 0xA6, + DISPLAY_MODE_INVERTED = 0xA7, + MEM_ADDRESSING = 0x20, + SET_COLUMN_ADDRESS = 0x21, + CHARGE_PUMP_REGULATOR = 0x8D, + CHARGE_PUMP_ON = 0x14, + SET_PAGE_ADDR = 0x22, + SET_COL_LO_NIBBLE = 0x00, + SET_COL_HI_NIBBLE = 0x10, + DEACTIVATE_SCROLL = 0x2E, + NOP = 0xE3 + } + + uint16 rows() { + return framebuffer.height()*8; + } + + uint16 columns() { + return framebuffer.width(); + } + + void set_address(uint8 a) { + address = a; + } + + void init_display() { + datacmd.mode(port_mode.output); + reset.mode(port_mode.output); + select.mode(port_mode.output); + + reset_display(); + + init_commands = { + powerstate.SLEEP, + commands.SET_DISP_CLOCK, 0x80, + commands.SET_MULTIPLEX_RATIO, 0x3F, + commands.SET_VERTICAL_OFFSET, 0x00, + commands.SET_DISP_START_LINE, + commands.CHARGE_PUMP_REGULATOR, + commands.CHARGE_PUMP_ON, + commands.MEM_ADDRESSING, 0x00, // Horizontal memory addressing mode + commands.SET_SEG_REMAP_0, + commands.SET_COM_SCAN_INVERTED, + commands.SET_WIRING_SCHEME, 0x12, + commands.SET_CONTRAST, 0x8F, + commands.SET_PRECHARGE_PERIOD, 0xF1, + commands.SET_VCOM_DESELECT_LEVEL, 0x40, + commands.RESUME_TO_RAM_CONTENT, + commands.DISPLAY_MODE_NORMAL, + commands.DEACTIVATE_SCROLL, + powerstate.ON + }; + + write_commands(init_commands); + } + + void set_orientation(displayorientation o) { + cmds = {0:2}; + + if (o == displayorientation.NORMAL or + o == displayorientation.NORMAL_MIRRORED) { + cmds[0] = commands.SET_SEG_REMAP_0; + } else { + cmds[0] = commands.SET_SEG_REMAP_127; + } + + if (o == displayorientation.NORMAL_MIRRORED or + o == displayorientation.UPSIDE_DOWN) { + cmds[1] = commands.SET_COM_SCAN_INVERTED; + } else { + cmds[1] = commands.SET_COM_SCAN_NORMAL; + } + + write_commands(cmds); + } + + void set_display_mode(bool inverted) { + cmds = {0}; + if inverted { + cmds[0] = commands.DISPLAY_MODE_INVERTED; + } else { + cmds[0] = commands.DISPLAY_MODE_NORMAL; + } + write_commands(cmds); + } + + void set_contrast(uint8 c) { + cmds = {commands.SET_CONTRAST, int8(c)}; + write_commands(cmds); + } + + void reset_display() { + if (dbus.get_protocol() == databus_protocol.SPI) { + reset.set(true); + mmcu.wait_ms(10); + reset.set(false); + mmcu.wait_ms(10); + reset.set(true); + } + } + + void write_commands(int8[] cmds) { + datacmd.set(false); + select.set(false); + + dbus.start_transaction(address); + if (dbus.get_protocol() == databus_protocol.I2C) { + dbus.write(i2c_control.CMD_STREAM); + } + + dbus.write_array(cmds); + + dbus.end_transaction(); + select.set(true); + } + + void reset_cursor(uint16 lx, uint16 ly, uint16 ux, uint16 uy) { + cmds = { + // set page update range + commands.SET_PAGE_ADDR, int8(ly), int8(uy), + // set column update range + commands.SET_COLUMN_ADDRESS, int8(lx), int8(ux) + }; + write_commands(cmds); + } + + void clear() { + reset_cursor(0, 0, columns()-1, rows()-1); + + datacmd.set(true); + select.set(false); + zero_data = {0:128}; + + dbus.start_transaction(address); + if (dbus.get_protocol() == databus_protocol.I2C) { + dbus.write(i2c_control.DATA_STREAM); + } + + i = 0u; + while i < framebuffer.height() { + dbus.write_array(zero_data); + i++; + } + + dbus.end_transaction(); + select.set(true); + } + + void update_frame() { + ev = framebuffer.changes; + if ev.empty() { + return; + } + reset_cursor(ev.lx, ev.ly, ev.ux, ev.uy); + + datacmd.set(true); + select.set(false); + dbus.start_transaction(address); + if (dbus.get_protocol() == databus_protocol.I2C) { + dbus.write(i2c_control.DATA_STREAM); + } + + row = ev.ly; + while row <= ev.uy { + col = ev.lx; + while col <= ev.ux { + v = framebuffer.get(row, col); + dbus.write(v); + col++; + } + row++; + } + + dbus.end_transaction(); + select.set(true); + ev.clear(); + } +} diff --git a/lib/graphic/canvas8.rob b/lib/graphic/canvas8.rob new file mode 100644 index 0000000..dcc41e6 --- /dev/null +++ b/lib/graphic/canvas8.rob @@ -0,0 +1,71 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +use assert; +use intfs.buffer8; + +type canvas8 { + buffer = buffer8(); + + uint16 width() inline { + return buffer.width(); + } + + uint16 height() inline { + return buffer.height()*8; + } + + void clear() inline { + buffer.clear(); + } + + void set_pixel(uint16 row, uint16 col) { + rowb = row/8; + assert(col < buffer.width() and rowb < buffer.height(), "outside buffer bounds"); + v = buffer.get(rowb, col); + buffer.set(rowb, col, v | (1 << uint8(row & 7))); + } + + void clear_pixel(uint16 row, uint16 col) { + rowb = row/8; + assert(col < buffer.width() and rowb < buffer.height(), "outside buffer bounds"); + v = buffer.get(rowb, col); + buffer.set(rowb, col, v & ~(1 << uint8(row & 7))); + } + + void fill_rect(uint16 x1, uint16 y1, uint16 x2, uint16 y2, bool v) { + if x1 >= width() { return; } + if y1 >= height() { return; } + if x2 >= width() { x2 = width()-1; } + if y2 >= height() { y2 = height()-1; } + first_bank = y1 >> 3; + last_bank = y2 >> 3; + bank = first_bank; + while bank <= last_bank { + mask = 0xFF; + y1t = uint8(y1); + y2t = uint8(y2); + if first_bank == last_bank { // all bits in the same bank + mask = (mask >> ((y1t & 7) + 7 - (y2t & 7))) << (y1t & 7); + } else if bank == first_bank { + mask = (mask << (y1t & 7)); + } else if bank == last_bank { + mask = (mask >> (7 - (y2t & 7))); + } + b = x1; + while b <= x2 { + bv = buffer.get(bank, b); + bv &= ~mask; + if v { + bv |= mask; + } + buffer.set(bank, b, bv); + b++; + } + bank++; + } + } +} + diff --git a/lib/graphic/envelope.rob b/lib/graphic/envelope.rob new file mode 100644 index 0000000..a505914 --- /dev/null +++ b/lib/graphic/envelope.rob @@ -0,0 +1,40 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +use math.limits; + +type envelope_u16 { + + lx = uint16_max; + ly = uint16_max; + ux = uint16(0); + uy = uint16(0); + + void set(uint16 lxx, uint16 lyy, uint16 uxx, uint16 uyy) { + lx = lxx; + ly = lyy; + ux = uxx; + uy = uyy; + } + + bool empty() { + return ux < lx or uy < ly; + } + + void clear() { + lx = uint16_max; + ly = uint16_max; + ux = uint16(0); + uy = uint16(0); + } + + void expand(uint16 x, uint16 y) { + if lx > x { lx = x; } + if ux < x { ux = x; } + if ly > y { ly = y; } + if uy < y { uy = y; } + } + +} diff --git a/lib/intfs/buffer8.rob b/lib/intfs/buffer8.rob new file mode 100644 index 0000000..cbcaaa6 --- /dev/null +++ b/lib/intfs/buffer8.rob @@ -0,0 +1,12 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +interface buffer8 { + uint16 height(); + uint16 width(); + void clear(); + uint8 get(uint16 row, uint16 col); + void set(uint16 row, uint16 col, uint8 v); +} diff --git a/lib/intfs/databus.rob b/lib/intfs/databus.rob new file mode 100644 index 0000000..790087a --- /dev/null +++ b/lib/intfs/databus.rob @@ -0,0 +1,22 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +use interrupt; + +enum databus_protocol {SPI, I2C, UART, CAN} + +interface databus { + void setup(uint32 speed); + void enable(); + void disable(); + void write(uint8 b); + void write_array(int8[] data); + uint8 read(); + bool has_data(); + bool start_transaction(uint16 addr); + void end_transaction(); + databus_protocol get_protocol(); + void async_read_to(interrupt_i8 i); +} diff --git a/lib/intfs/display.rob b/lib/intfs/display.rob new file mode 100644 index 0000000..51ab678 --- /dev/null +++ b/lib/intfs/display.rob @@ -0,0 +1,17 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +enum displayorientation {NORMAL, NORMAL_MIRRORED, UPSIDE_DOWN, UPSIDE_DOWN_MIRRORED} + +interface display { + uint16 rows(); + uint16 columns(); + void init_display(); + void set_orientation(displayorientation o); + void set_contrast(uint8 c); + void update_frame(); + void clear(); + void set_address(uint8 a); +} diff --git a/lib/intfs/interrupt.rob b/lib/intfs/interrupt.rob new file mode 100644 index 0000000..ad95b8b --- /dev/null +++ b/lib/intfs/interrupt.rob @@ -0,0 +1,20 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +interface interrupt { + void handler(); +} + +interface interrupt_i8 { + void handler(uint8 i); +} + +type void_interrupt implements interrupt { + void handler() {} +} + +type void_interrupt_i8 implements interrupt_i8 { + void handler(uint8 i) {} +} diff --git a/lib/intfs/mcu.rob b/lib/intfs/mcu.rob new file mode 100644 index 0000000..0e2b1f4 --- /dev/null +++ b/lib/intfs/mcu.rob @@ -0,0 +1,11 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +interface mcu { + void wait_us(uint16 us); + void wait_ms(uint16 ms); + void set_interruptions(bool enabled); + uint32 clock(); +} diff --git a/lib/intfs/ports.rob b/lib/intfs/ports.rob new file mode 100644 index 0000000..5fd6e13 --- /dev/null +++ b/lib/intfs/ports.rob @@ -0,0 +1,30 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +enum port_mode { input = 0, output = 1} + +interface digitalport { + void mode(port_mode m); + void set(bool v); + bool get(); +} + +interface analogport { + void mode(port_mode m); + void set(uint16 v); + uint16 get(); +} + +type void_digitalport implements digitalport { + void mode(port_mode m) inline {} + void set(bool v) inline {} + bool get() inline { return false; } +} + +type void_analogport implements analogport { + void mode(port_mode m) inline {} + void set(uint16 v) inline {} + uint16 get() inline { return 0; } +} diff --git a/lib/intfs/stepper.rob b/lib/intfs/stepper.rob new file mode 100644 index 0000000..1b6cdb3 --- /dev/null +++ b/lib/intfs/stepper.rob @@ -0,0 +1,15 @@ + +enum stepper_mode {wave, fullstep, halfstep} +enum stepper_direction {clockwise, counterclockwise} + +interface stepper{ + void setup(stepper_mode mode); + + void enable(); + void disable(); + + void set_mode(stepper_mode mode); + void set_direction(stepper_direction direction); + + void step(); +} diff --git a/lib/lib b/lib/lib new file mode 120000 index 0000000..692df8b --- /dev/null +++ b/lib/lib @@ -0,0 +1 @@ +/home/rayssa/robcmp/lib \ No newline at end of file diff --git a/lib/math/abs.rob b/lib/math/abs.rob new file mode 100644 index 0000000..e27066f --- /dev/null +++ b/lib/math/abs.rob @@ -0,0 +1,30 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* Abs functions without branch */ + +int8 abs8(int8 value) inline { + mask = value >> 7; + value = (value ^ mask) - mask; + return value; +} + +int16 abs16(int16 value) inline { + mask = value >> 15; + value = (value ^ mask) - mask; + return value; +} + +int32 abs32(int32 value) inline { + mask = value >> 31; + value = (value ^ mask) - mask; + return value; +} + +int64 abs64(int64 value) inline { + mask = value >> 63; + value = (value ^ mask) - mask; + return value; +} diff --git a/lib/math/float.rob b/lib/math/float.rob new file mode 100644 index 0000000..41eec4d --- /dev/null +++ b/lib/math/float.rob @@ -0,0 +1,17 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +const NAN = 0.0 / 0.0; +const INFINITY = 1.0 / 0.0; + +bool isnan(float x) { + u = bitcast(x, uint32); + return (u & 0x7fffffff) > 0x7f800000; +} + +bool isinf(float x) { + u = bitcast(x, uint32); + return (u & 0x7fffffff) == 0x7f800000; +} diff --git a/lib/math/limits.rob b/lib/math/limits.rob new file mode 100644 index 0000000..4c93d77 --- /dev/null +++ b/lib/math/limits.rob @@ -0,0 +1,27 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +const char_max = 255u; + +const uint8_max = 255u; +const uint16_max = 65535u; +const uint32_max = 4294967295u; +const uint64_max = 18446744073709551615u; + +const int8_min = -128; +const int8_max = 127; +const int16_min = -32768; +const int16_max = 32767; +const int32_min = -2147483648; +const int32_max = 2147483647; +const int64_min = -9223372036854775808; +const int64_max = 9223372036854775807; + +const float_min = 1.175494351E-38; +const float_max = 3.402823466E+38; +const double_min = 2.2250738585072014E-308; +const double_max = 1.7976931348623158E+308; +const ldouble_min = 3.36210314311209350626267781732175260E-4932; +const ldouble_max = 6.47517511943802511092443895822764655E-4966; diff --git a/lib/math/random16.rob b/lib/math/random16.rob new file mode 100644 index 0000000..99a2077 --- /dev/null +++ b/lib/math/random16.rob @@ -0,0 +1,44 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* + * A simple 16 bit pseudo random number generator, based + * on wyhash: https://github.com/wangyi-fudan/wyhash and + * Daniel Lemire, "A fast 16-bit random number generator?", + * 2019, at https://lemire.me/blog/2019/07/03/a-fast-16-bit + */ + +use limits; + +random_seed16 = 0xE7A8; + +void srandom16(uint16 seed) { + random_seed16 = seed; +} + +uint16 random16() { + random_seed16 += 0xfc15; + n = uint32(random_seed16) * 0x2ab; + return uint16((n >> 16) ^ n); +} + +/* + * Based on the work: Fast Random Integer Generation in an Interval + * by Daniel Lemire, 2018. https://arxiv.org/abs/1805.10941. + */ +uint16 random16ub(uint16 upto) { + x = random16(); + m = uint32(x) * upto; + l = uint16(m); + if (l < upto) { + t = (uint16_max - upto + 1) % upto; + while (l < t) { + x = random16(); + m = uint32(x) * upto; + l = uint16(m); + } + } + return uint16(m >> 16); +} diff --git a/lib/math/random32.rob b/lib/math/random32.rob new file mode 100644 index 0000000..576dc27 --- /dev/null +++ b/lib/math/random32.rob @@ -0,0 +1,57 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* This is a pseudo random number generator based on the article + * "Random number generators: good ones are hard to find", by + * Park and Miller, Communications of the ACM, vol. 31, no. 10, + * October 1988, p. 1195. + */ + +use limits; + +const random_seed32_start = 0x262028EB; +const random_max32 = 0x7FFFFFFF; + +random_seed32 = uint32(random_seed32_start); + +void srandom32(uint32 seed) { + random_seed32 = seed; +} + +uint32 random32() { + x = random_seed32; + /* Can't be zero */ + if (x == 0) { + x = random_seed32_start; + } + hi = x / 127773; + lo = x % 127773; + x = 16807 * lo - 2836 * hi; + if (x < 0) { + x += random_max32; + } + random_seed32 = x; + return (random_seed32 % (random_max32 + 1u)); +} + +/* + * Based on the work: Fast Random Integer Generation in an Interval + * by Daniel Lemire, 2018. https://arxiv.org/abs/1805.10941. + */ +uint32 random32ub(uint32 upto) { + x = random32(); + m = uint64(x) * upto; + l = uint32(m); + if (l < upto) { + t = (uint32_max - upto + 1) % upto; + while (l < t) { + x = random32(); + m = uint64(x) * upto; + l = uint32(m); + } + } + return uint32(m >> 32); +} + diff --git a/lib/motor/stepper/uln2003.rob b/lib/motor/stepper/uln2003.rob new file mode 100644 index 0000000..9163717 --- /dev/null +++ b/lib/motor/stepper/uln2003.rob @@ -0,0 +1,117 @@ +use intfs.ports; +use intfs.stepper; + +type uln2003 implements stepper{ + current_step = 0u; + incrementer = 0; + mode = stepper_mode.wave; + + dp1 = digitalport(); + dp2 = digitalport(); + dp3 = digitalport(); + dp4 = digitalport(); + + void setup(stepper_mode selected_mode){ + mode = selected_mode; + + dp1.mode(port_mode.output); + dp2.mode(port_mode.output); + dp3.mode(port_mode.output); + dp4.mode(port_mode.output); + } + + void set_mode(stepper_mode mode){ + if mode == stepper_mode.wave{ + if current_step % 2 == 0{ //Tem que ser indice impar + current_step++; + } + incrementer = 2; + + }else if mode == stepper_mode.halfstep{ + incrementer = 1; + + }else if mode == stepper_mode.fullstep{ + if current_step % 2 != 0{ //Tem que ser indice par + current_step++; + } + incrementer = 2; + } + } + + void set_direction(stepper_direction direction){ + set_mode(mode); + + if direction == stepper_direction.counterclockwise{ + incrementer *= -1; + } + } + + void enable(){ + dp1.set(true); + dp2.set(true); + dp3.set(true); + dp4.set(true); + } + + void disable(){ + dp1.set(false); + dp2.set(false); + dp3.set(false); + dp4.set(false); + } + + void step(){ + if current_step == 0 { //1000 + dp1.set(true); + dp2.set(false); + dp3.set(false); + dp4.set(false); + }else if current_step == 1{ //1100 + dp1.set(true); + dp2.set(true); + dp3.set(false); + dp4.set(false); + }else if current_step == 2{ //0100 + dp1.set(false); + dp2.set(true); + dp3.set(false); + dp4.set(false); + }else if current_step == 3{ //0110 + dp1.set(false); + dp2.set(true); + dp3.set(true); + dp4.set(false); + }else if current_step == 4{ //0010 + dp1.set(false); + dp2.set(false); + dp3.set(true); + dp4.set(false); + }else if current_step == 5{ //0011 + dp1.set(false); + dp2.set(false); + dp3.set(true); + dp4.set(true); + }else if current_step == 6{ //0001 + dp1.set(false); + dp2.set(false); + dp3.set(false); + dp4.set(true); + }else if current_step == 7{ //1001 + dp1.set(true); + dp2.set(false); + dp3.set(false); + dp4.set(true); + } + + current_step = (current_step + incrementer + 8) % 8; + + /*current_step += incrementer; + + if current_step > 7{ + current_step = 0; + }else if current_step < 0{ + current_step = 7; + }*/ + } +} + diff --git a/lib/stm32f1.ld b/lib/stm32f1.ld new file mode 100644 index 0000000..8e4552c --- /dev/null +++ b/lib/stm32f1.ld @@ -0,0 +1,50 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +__reset_stack_pointer = ORIGIN(RAM) + LENGTH(RAM); + +SECTIONS +{ + .isr_vector : { + _start = .; + LONG(__reset_stack_pointer); + LONG(__isr_reset | 1); + LONG(__isr_nmi | 1); + /* The interrupt table is 332 bytes long. Advance to that position. */ + . = ORIGIN(FLASH) + 332; + } > FLASH + + .text : { + . = ALIGN(4); + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + . = ALIGN(4); + } > FLASH + + __data_init = LOADADDR(.data); + + .data : { + __data_start = .; + *(.data) + *(.data.*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH + + .bss : + { + __bss_start = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/lib/stm32f1.rob b/lib/stm32f1.rob new file mode 100644 index 0000000..e72dafc --- /dev/null +++ b/lib/stm32f1.rob @@ -0,0 +1,171 @@ +/* + * Robcmp interruptions vector for stm32f1 + */ + +use arch.stm32.stm32f1regs; +use math.limits; + +int8 main(); + +/*void __set_system_clock_to_72Mhz() { + // Necessary wait states for Flash for high speeds + FLASH->ACR = 0x12; + // Enable HSE + RCC->CR |= (1 << 16); + // Wait untill HSE settles down + while (!(RCC->CR & (1 << 17))); + // Set PREDIV2 division factor to 5 + RCC->CFGR2 |= (0b0100 << 4); + // Set PLL2 multiplication factor to 8 + RCC->CFGR2 |= (0b0110 << 8); + // Enable PLL2 + RCC->CR |= (1 << 26); + // Wait untill PLL2 settles down + while (!(RCC->CR & (1 << 27))); + // Set PLL2 as PREDIV1 clock source + RCC->CFGR2 |= (1 << 16); + // Set PREDIV1 division factor to 5 + RCC->CFGR2 |= (0b0100 << 0); + // Select Prediv1 as PLL source + RCC->CFGR |= (1 << 16); + // Set PLL1 multiplication factor to 9 + RCC->CFGR |= (0b0111 << 18); + // Set APB1 to 36MHz + RCC->CFGR |= 1 << 10; + // Enable PLL + RCC->CR |= (1 << 24); + // Wait untill PLL settles down + while (!(RCC->CR & (1 << 25))); + // Finally, choose PLL as the system clock + RCC->CFGR |= (0b10 << 0); +} +*/ + +//const HSE_Value = 25E6; // External oscillator in Hz +//const HSI_Value = 8E6; // Internal oscillator in Hz + +void __set_system_clock_to_25Mhz() { + // Enable HSE and waits it to settle down + RCC_CR.hse_on = true; + while !RCC_CR.hse_rdy; + // Set HSE as the system clock + RCC_CFGR.sw = uint2(0x01); +} + +void __system_clock_config() { + //__set_system_clock_to_25Mhz(); + SYSTICK_LOAD = 0xFFFFFF; //24 bits + SYSTICK_CTRL.enable = true; + SYSTICK_CTRL.clksource = true; // processor clock +} + +void __error_handler() { + loop { + asm "wfi"; + } +} + +void memset() noinline { +// reference signature: +// void *memset(void *dst, int val, size_t count) +// r0 ↑ r1 ↑ r2 ↑ +asm + "cmp r2, #0 + it eq + bxeq lr /* return if r2/count==0 */ + mov r12, r0 + tst r0, #3 /* is 4-bytes aligned? */ + beq __memset_aligned + + __memset_unaligned: + strb r1, [r12], #1 + subs r2, r2, #1 + it eq + bxeq lr /* return if r2/count==0 */ + tst r12, #13 /* is 4-bytes aligned now? */ + bne __memset_unaligned + + __memset_aligned: + bfi r1, r1, #8, #8 + bfi r1, r1, #16, #16 + mov r3, r1 + cmp r2, #16 + blo __memset_less16 + push {r4, lr} + mov r4, r1 + mov lr, r1 + cmp r2, #32 + blo __memset_less32 + + __memset_write32: + stmia r12!, {r1, r3, r4, lr} /* write 32 bytes */ + stmia r12!, {r1, r3, r4, lr} + subs r2, r2, #32 + it eq + popeq {r4, pc} + cmp r2, #32 + bhs __memset_write32 + + __memset_less32: + cmp r2, #16 + it hs + stmiahs r12!, {r1, r3, r4, lr} + it eq + popeq {r4, pc} + pop {r4, lr} + + __memset_less16: + lsls r2, r2, #29 + it cs + stmiacs r12!, {r1, r3} + it eq + bxeq lr + it mi + strmi r1, [r12], #4 + lsls r2, r2, #1 + it mi + strhmi r1, [r12], #2 + it ne + strbne r1, [r12] + "; +} + +void __do_copy_data() noinline { +asm + "movs r1, #0 + b __do_copy_data_start + __do_copy_data_loop: + ldr r3, =__data_init + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + __do_copy_data_start: + ldr r0, =__data_start + ldr r3, =__data_end + adds r2, r0, r1 + cmp r2, r3 + bcc __do_copy_data_loop + ldr r2, =__bss_start + ldr r3, =__bss_end + movs r1, #0 + b __do_clear_bss_start + __do_clear_bss_loop: + str r1, [r2], #4 + __do_clear_bss_start: + cmp r2, r3 + bcc __do_clear_bss_loop"; +} + +void __isr_reset() { + + __do_copy_data(); + __system_clock_config(); + + ret = main(); + + __error_handler(); +} + +void __isr_nmi() { + asm "nop"; +} diff --git a/macbuild b/macbuild new file mode 100755 index 0000000..374cb2c --- /dev/null +++ b/macbuild @@ -0,0 +1,6 @@ +CXX=/usr/local/opt/llvm/bin/clang++ +CC=/usr/local/opt/llvm/bin/clang +export CXX +export CC +cmake -DCMAKE_BUILD_TYPE="Debug" .. +#cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_BUILD_TYPE="Debug" .. diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 7cee12d..0000000 --- a/main.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "node.h" - -extern int yyparse(); -extern FILE *yyin; - -// Program main module -Module *mainmodule; - -// symbol table -map tabelasym; -map symexists; - -// file name -char *build_filename; - -// arduino functions -Function *analogWrite; -Function *analogRead; -Function *delay; -Function *delayMicroseconds; -Function *init; -Function *print; -Function *i16div; - - -int main(int argc, char *argv[]) { - - // Compila o arquivo passado como parâmetro - if (argc > 1) { - build_filename = argv[1]; - yyin = fopen(build_filename, "r"); - if (yyin == NULL) { - fprintf(stderr, "Could not open file %s.\n", build_filename); - exit(1); - } - } - yyparse(); - if (yyin) - fclose(yyin); - - llvm::legacy::PassManager pm; - - /*pm.add(createPromoteMemoryToRegisterPass()); - pm.add(createInstructionCombiningPass()); - pm.add(createReassociatePass()); - pm.add(createCFGSimplificationPass()); - pm.add(createLICMPass()); - pm.add(createGVNPass()); - pm.add(createSCCPPass()); - pm.add(createCFGSimplificationPass()); - pm.add(createAggressiveDCEPass()); - pm.add(createDeadStoreEliminationPass()); - pm.add(createCFGSimplificationPass());*/ - - // imprime o código intermediário gerado - pm.add(createPrintModulePass(outs())); - - pm.run(*mainmodule); - - return 0; -} - diff --git a/new_rob.txt b/new_rob.txt deleted file mode 100644 index 52b4ccd..0000000 --- a/new_rob.txt +++ /dev/null @@ -1,86 +0,0 @@ -/*void motor_shutdown() { - out PIN1 = 0.0; - out PIN2 = 0.0; - out PIN3 = 0.0; - out PIN4 = 0.0; -}*/ - -int read_ir(){ - return 1; -} - -void step_up_down(){ - print "oi"; -} - -void step_right_left(){ - print "oi"; -} - -void step_front_back(){ - print "oi"; -} - -void blink(float time) { - out13 = 255.0; - delay time; - out13 = 0.0; - delay time; -} - -curr_dir = 1.0; -blink(500.0); -blink(500.0); -PARA_FRENTE = 1.0; -PARA_TRAS = 1.0; - -void SERVO_POS_INC(){ - print "Abre"; -} - -void SERVO_POS_DEC(){ - print "Fecha"; -} - -void open_grip (bool open){ - if (open == true){ - SERVO_POS_INC(); - } - else{ - SERVO_POS_DEC(); - } -} - -while (true == true) { - F = read_ir(); - if (F == 3041526525.0) { // UP - SENTIDO = 1.0; - step_up_down(); - } - else if (F == 3041559165.0) { // DOWN - SENTIDO = -1.0; - step_up_down(); - } - else if (F == 3041542845.0) { // LEFT - SENTIDO = 1.0; - step_right_left(); - } - else if (F == 3041575485.0) { // RIGHT - SENTIDO = -1.0; - step_right_left(); - } - else if (F == 4111076595.0) { // AUDIO - SENTIDO = 1.0; - step_front_back(); - } - else if (F == 3041570895.0) { // RIGHT - SENTIDO = -1.0; - step_front_back(); - } - else if (F == 3041546415.0) { // OPEN GRIP - open_grip(true); - } - else if (F == 3041579055.0) { // CLOSE GRIP - open_grip(false); - } -} diff --git a/node.h b/node.h deleted file mode 100644 index fadc002..0000000 --- a/node.h +++ /dev/null @@ -1,553 +0,0 @@ -#ifndef NODE_H -#define NODE_H - -#define ENABLE_ARDUINO -#define ENABLE_PRINT - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace llvm; - -class Node; -class Stmts; -#include "bison.hpp" - -extern int yyerror(const char *s); -extern int yylex(); - -// Program main module -extern Module *mainmodule; -extern char* build_filename; -static LLVMContext global_context; - -// symbol table -extern map tabelasym; -extern map symexists; - -// arduino functions -extern Function *analogWrite; -extern Function *analogRead; -extern Function *delay; -extern Function *delayMicroseconds; - -extern Function *init; -extern Function *print; -extern Function *i16div; - -class Node { -public: - virtual Value *generate(Function *func, BasicBlock *block) = 0; - virtual ~Node() {} -}; - -class Int8: public Node { -private: - char number; -public: - Int8(char n): number(n) {} - Value *generate(Function *func, BasicBlock *block) { - return ConstantInt::get(Type::getInt8Ty(global_context), number); - } -}; - -class Int16: public Node { -private: - short number; -public: - Int16(short n): number(n) {} - Value *generate(Function *func, BasicBlock *block) { - return ConstantInt::get(Type::getInt16Ty(global_context), number); - } -}; - -class Int32: public Node { -private: - int number; -public: - Int32(int n): number(n) {} - Value *generate(Function *func, BasicBlock *block) { - return ConstantInt::get(Type::getInt32Ty(global_context), number); - } -}; - -class Float: public Node { -private: - float number; -public: - Float(float n): number(n) {} - Value *generate(Function *func, BasicBlock *block) { - return ConstantFP::get(Type::getFloatTy(global_context), number); - } -}; - -class String: public Node { -private: - string str; -public: - String(const char *s): str(s) {} - Value *generate(Function *func, BasicBlock *block) { - return ConstantDataArray::getString(global_context, str, true);; - } -}; - -class Load: public Node { -private: - string ident; -public: - Load(const char *i): ident(i) { - auto var = symexists.find(ident); - if (var == symexists.end()) - yyerror("Variable not declared:"); - } - - Value *generate(Function *func, BasicBlock *block) { - LoadInst *ret = new LoadInst(tabelasym[ident]->getAllocatedType(), tabelasym[ident], ident, false, block); - return ret; - } -}; - -class Variable: public Node { -private: - string name; - Node *expr; -public: - Variable(const char *n, Node *e) : name(n), expr(e) { - symexists[n] = 1; // variable exists! - } - - Value *generate(Function *func, BasicBlock *block) { - auto left = tabelasym.find(name); - Value *leftv; - Value *exprv = expr->generate(func, block); - if (left == tabelasym.end()) { - tabelasym[name] = new AllocaInst(exprv->getType(), 0, name, block); - leftv = tabelasym[name]; - } - else - leftv = left->second; - - StoreInst *ret = new StoreInst(exprv, leftv, false, block); - return ret; - - } -}; - -class InPort: public Node { -private: - string port; -public: - InPort(const char *p): port(p) {} - Value *generate(Function *func, BasicBlock *block) { - vector args; - - Int8 prt(atoi(port.c_str())); - args.push_back(prt.generate(func, block)); - - ArrayRef argsRef(args); - return CallInst::Create(analogRead, argsRef, "", block); - } -}; - -class OutPort: public Node { -private: - string port; - Node *expr; -public: - OutPort (const char *p, Node *e) : port(p), expr(e) {} - Value *generate(Function *func, BasicBlock *block) { - vector args; - - Int8 prt(atoi(port.c_str())); - args.push_back(prt.generate(func, block)); - - Value *value = expr->generate(func, block); - Value *nvalue = value; - if (value->getType()->isFloatTy()) - nvalue = new FPToSIInst(value, Type::getInt16Ty(global_context), "trunci", block); - - //args.push_back(nvalue); - Value *int8v = new TruncInst(value, Type::getInt8Ty(global_context), "", block); - args.push_back(int8v); - - ArrayRef argsRef(args); - return CallInst::Create(analogWrite, argsRef, "", block); - } -}; - -class Delay: public Node { -private: - Node *ms; -public: - Delay (Node *mseg) : ms(mseg) {} - Value *generate(Function *func, BasicBlock *block) { - Value *msv = ms->generate(func, block); - Value *msv32 = new SExtInst(msv, Type::getInt32Ty(global_context), "conv", block); - - vector args; - args.push_back(msv32); - ArrayRef argsRef(args); - return CallInst::Create(delay, argsRef, "", block); - } -}; - -class BinaryOp: public Node { -private: - char op; - Node *lhsn; - Node *rhsn; -public: - BinaryOp (Node *l, char op, Node *r) : lhsn(l), rhsn(r) { - this->op =op; - } - Instruction *binary_operator(enum Instruction::BinaryOps opint, - enum Instruction::BinaryOps opflt, Function *func, BasicBlock *block) { - - Value *lhs = lhsn->generate(func, block); - Value *rhs = rhsn->generate(func, block); - - Type *Ty1 = lhs->getType(); - Type *Ty2 = rhs->getType(); - - if (Ty1->isIntegerTy() && Ty2->isIntegerTy()) { - /*fallback SDiv disabled - if (opint == Instruction::SDiv) { - vector args; - args.push_back(lhs); - args.push_back(rhs); - ArrayRef argsRef(args); - return CallInst::Create(i16div, argsRef, "", block); - }*/ - return BinaryOperator::Create(opint, lhs, rhs, "", block); - } - else { - Value *flhs = lhs, *frhs = rhs; - if (Ty1->isIntegerTy()) - flhs = new SIToFPInst(lhs, Type::getFloatTy(global_context), "castitof", block); - if (Ty2->isIntegerTy()) - frhs = new SIToFPInst(rhs, Type::getFloatTy(global_context), "castitof", block); - return BinaryOperator::Create(opflt, flhs, frhs, "binop", block); - } - } - - Value *generate(Function *func, BasicBlock *block) { - switch (op) { - case '+' : return binary_operator(Instruction::Add, Instruction::FAdd, func, block); - case '-' : return binary_operator(Instruction::Sub, Instruction::FSub, func, block); - case '*' : return binary_operator(Instruction::Mul, Instruction::FMul, func, block); - case '/' : return binary_operator(Instruction::SDiv, Instruction::FDiv, func, block); - default: return NULL; - } - } -}; - -class CmpOp: public Node { -private: - Node *lexpn; - Node *rexpn; - int op; -public: - CmpOp (Node *l, int op, Node *r) : lexpn(l), rexpn(r) { - this->op = op; - } - Value *generate(Function *func, BasicBlock *block) { - CmpInst::Predicate predicate; - - Value *lexp = lexpn->generate(func, block); - Value *rexp = rexpn->generate(func, block); - - Type *Ty1 = lexp->getType(); - Type *Ty2 = rexp->getType(); - int isFCmp = !Ty1->isIntegerTy() || !Ty2->isIntegerTy(); - if (isFCmp) { - if (Ty1->isIntegerTy()) - lexp = new SIToFPInst(lexp, Type::getFloatTy(global_context), "", block); - if (Ty2->isIntegerTy()) - rexp = new SIToFPInst(rexp, Type::getFloatTy(global_context), "", block); - } - - if (op == EQ_OP) predicate = isFCmp ? FCmpInst::FCMP_OEQ : ICmpInst::ICMP_EQ; - else if (op == NE_OP) predicate = isFCmp ? FCmpInst::FCMP_UNE : ICmpInst::ICMP_NE; - else if (op == GE_OP) predicate = isFCmp ? FCmpInst::FCMP_OGE : ICmpInst::ICMP_SGE; - else if (op == LE_OP) predicate = isFCmp ? FCmpInst::FCMP_OLE : ICmpInst::ICMP_SLE; - else if (op == GT_OP) predicate = isFCmp ? FCmpInst::FCMP_OGT : ICmpInst::ICMP_SGT; - else if (op == LT_OP) predicate = isFCmp ? FCmpInst::FCMP_OLT : ICmpInst::ICMP_SLT; - else { - cerr << "Invalid logical operator" << op << endl; - return NULL; - } - - if (isFCmp) - return new FCmpInst(*block, predicate, lexp, rexp, "cmpf"); - else { - return new ICmpInst(*block, predicate, lexp, rexp, "cmpi"); - } - } -}; - -class Capsule: public Node { -private: - Node *node; -public: - Capsule (Node *n) : node(n) {} - Value *generate(Function *func, BasicBlock *block) { - return node->generate(func, block); - } -}; - -class If: public Node { -private: - Node *expr; - Node *thenst; - Node *elsest; -public: - If (Node *e, Node *tst, Node *est) : expr(e), thenst(tst), elsest(est) {} - Value *generate(Function *func, BasicBlock *block) { - Value *exprv = expr->generate(func, block); - - BasicBlock *thenb = BasicBlock::Create(global_context, "if_then", func, 0); - Value *thennewb = thenst->generate(func, thenb); - - Value *elsenewb = NULL; - BasicBlock *elseb = BasicBlock::Create(global_context, "if_else", func, 0); - if (elsest != 0) { - elsenewb = elsest->generate(func, elseb); - } - - BranchInst::Create(thenb, elseb, exprv, block); - - BasicBlock *mergb = BasicBlock::Create(global_context, "if_cont", func, 0); - - if (thennewb->getValueID() == Value::BasicBlockVal) - BranchInst::Create(mergb, (BasicBlock*)thennewb); - else - BranchInst::Create(mergb, thenb); - - if (elsenewb && elsenewb->getValueID() == Value::BasicBlockVal) - BranchInst::Create(mergb, (BasicBlock*)elsenewb); - else - BranchInst::Create(mergb, elseb); - - return mergb; - } -}; - -class While: public Node { -private: - Node *expr; - Node *stmts; -public: - While(Node *e, Node *stms) : expr(e), stmts(stms) {} - Value *generate(Function *func, BasicBlock *block) { - BasicBlock *condwhile = BasicBlock::Create(global_context, "while_cond", func, 0); - Value *exprv = expr->generate(func, condwhile); - - BasicBlock *bodywhile = BasicBlock::Create(global_context, "while_body", func, 0); - Value *newb = stmts->generate(func, bodywhile); - - BasicBlock *endwhile = BasicBlock::Create(global_context, "while_end", func, 0); - - BranchInst::Create(condwhile, block); - BranchInst::Create(bodywhile, endwhile, exprv, condwhile); - - if (newb->getValueID() == Value::BasicBlockVal) - BranchInst::Create(condwhile, (BasicBlock*)newb); - else - BranchInst::Create(condwhile, bodywhile); - - return endwhile; - } -}; - -class Stmts: public Node { -private: - std::vector stmts; -public: - Stmts(Node *s) { - this->stmts.push_back(s); - } - - void append(Node *s) { - stmts.push_back(s); - } - - Value *generate(Function *func, BasicBlock *block) { - for(Node *n: stmts) { - Value *b = n->generate(func, block); - if (b->getValueID() == Value::BasicBlockVal) - block = (BasicBlock*)b; - } - return block; - } -}; - -class Print: public Node { -private: - Node *expr; -public: - Print(Node *e) : expr(e) {} - Value *generate(Function *func, BasicBlock *block) { - vector args; - - Value *lexp = expr->generate(func, block); - Type *ty1 = lexp->getType(); - char cty1 = 0; - if (ty1->isIntegerTy()) - cty1 = 0; - else if (ty1->isFloatTy()) - cty1 = 1; - else if (ty1->isArrayTy()) - cty1 = 2; - else - yyerror("Type not supported by print."); - - Int8 prt(cty1); - args.push_back(prt.generate(func, block)); - - AllocaInst *ptr_aux = new AllocaInst(lexp->getType(), 0, "", block); - StoreInst *st = new StoreInst(lexp, ptr_aux, false, block); - CastInst *cinst = new BitCastInst(ptr_aux, PointerType::get(IntegerType::get(global_context, 8), 0), "", block); - args.push_back(cinst); - - ArrayRef argsRef(args); - return CallInst::Create(print, argsRef, "", block); - } -}; - -class Program { -public: - Program() {} - - void declara_auxiliary_c_funcs() { - std::vector arg_types; - FunctionType *ftype; - - #ifdef ENABLE_ARDUINO - // analogRead - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - ftype = FunctionType::get(Type::getInt16Ty(global_context), - ArrayRef(arg_types), false); - analogRead = Function::Create(ftype, Function::ExternalLinkage, "analogRead", mainmodule); - analogRead->setCallingConv(CallingConv::C); - - // analogWrite - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - //arg_types.push_back(Type::getInt16Ty(global_context)); - arg_types.push_back(Type::getInt8Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); -// analogWrite = Function::Create(ftype, Function::ExternalLinkage, "analogWrite", mainmodule); - analogWrite = Function::Create(ftype, Function::ExternalLinkage, "digitalWrite", mainmodule); - - analogWrite->setCallingConv(CallingConv::C); - - // delay - arg_types.clear(); - arg_types.push_back(Type::getInt32Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - delay = Function::Create(ftype, Function::ExternalLinkage, "delay", mainmodule); - delay->setCallingConv(CallingConv::C); - - - // delayMicroseconds - arg_types.clear(); - arg_types.push_back(Type::getInt32Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - delayMicroseconds = Function::Create(ftype, Function::ExternalLinkage, "delayMicroseconds", mainmodule); - delayMicroseconds->setCallingConv(CallingConv::C); - - // init - ftype = FunctionType::get(Type::getVoidTy(global_context), false); - init = Function::Create(ftype, Function::ExternalLinkage, "init", mainmodule); - init->setCallingConv(CallingConv::C); - #endif - - #ifdef ENABLE_PRINT - // print - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - arg_types.push_back(PointerType::get(IntegerType::get(global_context, 8), 0)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - print = Function::Create(ftype, Function::ExternalLinkage, "print", mainmodule); - print->setCallingConv(CallingConv::C); - #endif - - /* Not necessary anymore. Stay as an example - AttributeSet print_func_attrs; - print_func_attrs = - print_func_attrs.addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::NoUnwind) - .addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::StackProtect) - .addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::UWTable) - .addAttribute(global_context, 1, Attribute::ZExt); - print->setAttributes(print_func_attrs); */ - - // i16divse) - /*arg_types.clear(); - arg_types.push_back(Type::getInt16Ty(global_context)); - arg_types.push_back(Type::getInt16Ty(global_context)); - ftype = FunctionType::get(Type::getInt16Ty(global_context), - ArrayRef(arg_types), false); - i16div = Function::Create(ftype, Function::ExternalLinkage, "i16div", mainmodule); - i16div->setCallingConv(CallingConv::C);*/ - } - - void generate(Node *n) { - mainmodule = new Module(build_filename, global_context); - - FunctionType *ftype = FunctionType::get(Type::getInt16Ty(global_context), - ArrayRef(), false); - Function *mainfunc = Function::Create(ftype,GlobalValue::ExternalLinkage, "main", mainmodule); - - BasicBlock *mainblock = BasicBlock::Create(global_context, "entry", mainfunc, 0); - - declara_auxiliary_c_funcs(); - - // call Arduino init - #ifdef ENABLE_ARDUINO - std::vector args; - ArrayRef argsRef(args); - CallInst *call = CallInst::Create(init, argsRef, "", mainblock); - #endif - - // generate the program! - Value *b = n->generate(mainfunc, mainblock); - if (b->getValueID() == Value::BasicBlockVal) { - mainblock = (BasicBlock*)b; - } - - Int16 ret(0); - Value *retv = ret.generate(mainfunc, mainblock); - ReturnInst::Create(global_context, retv, mainblock); - } -}; - -/* -class _: public Node { -private: -public: - _ () {} - Value *generate(Function *func, BasicBlock *block) { - } -}; -*/ - -#endif - diff --git a/platformio/avr-gdb-build/build b/platformio/avr-gdb-build/build new file mode 100755 index 0000000..2ded647 --- /dev/null +++ b/platformio/avr-gdb-build/build @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +VERSION=14.2 + +wget -c https://ftp.mirrorservice.org/sites/sourceware.org/pub/gdb/releases/gdb-${VERSION}.tar.xz + +rm -Rf gdb-${VERSION} +tar xf gdb-${VERSION}.tar.xz + +cd gdb-${VERSION} +mkdir build +cd build + +CC=/usr/local/bin/gcc-14 +CXX=/usr/local/bin/g++-14 +GMP=/usr/local/opt/gmp +MPFR=/usr/local/opt/mpfr +CFLAGS="-I/usr/local/include" +CPPFLAGS="-I/usr/local/include" +export CFLAGS +export CPPFLAGS +export CC +export CXX +../configure --target=avr --with-texinfo=no --with-python=no --with-gmp=$GMP --with-mpfr=$MPFR +make -j8 +cp gdb/gdb ../../avr-gdb +echo "Build successfully... run ./avr-gdb to check functionality." diff --git a/platformio/samples/avr328p-blink/.gitignore b/platformio/examples/blink/.gitignore similarity index 100% rename from platformio/samples/avr328p-blink/.gitignore rename to platformio/examples/blink/.gitignore diff --git a/platformio/examples/blink/platformio.ini b/platformio/examples/blink/platformio.ini new file mode 100644 index 0000000..bc99b87 --- /dev/null +++ b/platformio/examples/blink/platformio.ini @@ -0,0 +1,29 @@ + +[avr] +platform = robcmp +board = atmega328p +upload_protocol = serial +board_hardware_spec = specs/avr.spec +debug_tool = robcmp-led + +[env:avr-release] +extends = avr +build_type = release + +[env:avr-debug] +extends = avr +build_type = debug + + +[stm32] +platform = robcmp +board = stm32f1 +upload_protocol = stlink +board_hardware_spec = specs/stm32.spec + +[env:stm32-release] +extends = stm32 + +[env:stm32-debug] +extends = stm32 +build_type = debug diff --git a/platformio/examples/blink/specs/avr.spec b/platformio/examples/blink/specs/avr.spec new file mode 100644 index 0000000..6d156a9 --- /dev/null +++ b/platformio/examples/blink/specs/avr.spec @@ -0,0 +1,5 @@ + +use arch.avr.avr5mcu; + +bind avr5mcu to mmcu singleton; +bind avr5mcu.b5 to led singleton; diff --git a/platformio/examples/blink/specs/stm32.spec b/platformio/examples/blink/specs/stm32.spec new file mode 100644 index 0000000..5303022 --- /dev/null +++ b/platformio/examples/blink/specs/stm32.spec @@ -0,0 +1,5 @@ + +use arch.stm32.stm32f1; + +bind stm32f1 to mmcu singleton; +bind stm32f1.c13 to led singleton; diff --git a/platformio/examples/blink/src/main.rob b/platformio/examples/blink/src/main.rob new file mode 100644 index 0000000..2a8df7e --- /dev/null +++ b/platformio/examples/blink/src/main.rob @@ -0,0 +1,21 @@ +/* + * Robcmp examples: Blink + * Blinks the board default led + */ + +use intfs.ports; + +mmcu = mcu(); +led = digitalport(); + +int16 main() { + + led.mode(port_mode.output); + + loop { + led.set(true); + mmcu.wait_ms(500); + led.set(false); + mmcu.wait_ms(500); + } +} diff --git a/platformio/samples/stm32f1-blink/.gitignore b/platformio/examples/breakout/.gitignore similarity index 100% rename from platformio/samples/stm32f1-blink/.gitignore rename to platformio/examples/breakout/.gitignore diff --git a/platformio/examples/breakout/breakout.code-workspace b/platformio/examples/breakout/breakout.code-workspace new file mode 100644 index 0000000..8dc689c --- /dev/null +++ b/platformio/examples/breakout/breakout.code-workspace @@ -0,0 +1,11 @@ +{ + "folders": [ + { + "path": "." + }, + { + "path": "../../../lib" + } + ], + "settings": {} +} \ No newline at end of file diff --git a/platformio/examples/breakout/platformio.ini b/platformio/examples/breakout/platformio.ini new file mode 100644 index 0000000..4751d49 --- /dev/null +++ b/platformio/examples/breakout/platformio.ini @@ -0,0 +1,38 @@ + +[avr] +platform = robcmp +board = atmega328p +upload_protocol = serial +board_hardware_spec = specs/avr.spec +debug_svd_path = /Users/thborges/projects/robcmp/lib/atmega328p.svd +monitor_port = /tmp/simavr-uart0 +#monitor_port = /dev/cu.usbserial-0001 +monitor_speed = 115200 +debug_tool = robcmp-ssd1306 +#debug_tool = robcmp-led + +[env:avr-release] +extends = avr +build_type = release + +[env:avr-debug] +extends = avr +build_type = debug + + + +[stm32] +platform = robcmp +board = stm32f1 +upload_protocol = stlink +board_hardware_spec = specs/stm32.spec +monitor_speed = 9600 +monitor_port = /dev/cu.usbserial-0001 +debug_svd_path = /Users/thborges/projects/robcmp/lib/arch/stm32/stm32f103/stm32f103.svd + +[env:stm32-release] +extends = stm32 + +[env:stm32-debug] +extends = stm32 +build_type = debug diff --git a/platformio/examples/breakout/specs/avr.spec b/platformio/examples/breakout/specs/avr.spec new file mode 100644 index 0000000..689f52d --- /dev/null +++ b/platformio/examples/breakout/specs/avr.spec @@ -0,0 +1,19 @@ + +use arch.avr.avr5mcu; +use display.ssd1306; +use graphic.canvas8; + +bind avr5mcu to globals.mmcu singleton; +bind avr5mcu to ssd1306.mmcu singleton; + +bind avr5mcu.uart0 to globals.dbus_uart singleton; + +// SPI display +bind avr5mcu.b0 to ssd1306.reset singleton; +bind avr5mcu.b1 to ssd1306.datacmd singleton; +bind avr5mcu.b2 to ssd1306.select singleton; +bind avr5mcu.spi to globals.dbus_display singleton; +bind avr5mcu.spi to ssd1306.dbus singleton; + +bind ssd1306 to globals.oled singleton; +bind ssd1306.framebuffer to canvas8.buffer singleton; diff --git a/platformio/examples/breakout/specs/stm32.spec b/platformio/examples/breakout/specs/stm32.spec new file mode 100644 index 0000000..1678cfa --- /dev/null +++ b/platformio/examples/breakout/specs/stm32.spec @@ -0,0 +1,22 @@ +/* + * Injections for a SSD1306 I2C display + * and an stm32f103 mcu + */ + +use arch.stm32.stm32f1; +use display.ssd1306; +use graphic.canvas8; + +bind stm32f1 to globals.mmcu singleton; +bind stm32f1 to ssd1306.mmcu singleton; +bind stm32f1.uart2 to globals.dbus_uart singleton; + +// I2C display +bind void_digitalport to ssd1306.reset singleton; +bind void_digitalport to ssd1306.datacmd singleton; +bind void_digitalport to ssd1306.select singleton; +bind stm32f1.i2c1 to globals.dbus_display singleton; +bind stm32f1.i2c1 to ssd1306.dbus singleton; + +bind ssd1306 to globals.oled singleton; +bind ssd1306.framebuffer to canvas8.buffer singleton; diff --git a/platformio/examples/breakout/src/example.c b/platformio/examples/breakout/src/example.c new file mode 100644 index 0000000..2fefc4c --- /dev/null +++ b/platformio/examples/breakout/src/example.c @@ -0,0 +1,403 @@ +/* 2014 + * Breakout game by Ilya Titov. Find building instructions on http://webboggles.com/ + * The code that does not fall under the licenses of sources listed below can be used non commercially with attribution. + * + * If you have problems uploading this sketch, this is probably due to sketch size - you need to update ld.exe in arduino\hardware\tools\avr\avr\bin + * https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC + * + * This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project + * Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled + * + * Sleep code is based on this blog post by Matthew Little: + * http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85 +*/ +#include +#include "font6x8.h" +#include +#include // needed for the additional interrupt + +volatile byte player = 0; //0 to 128-platformWidth - this is the position of the bounce platform +byte platformWidth = 16; +byte ballx = 62; // coordinate of the ball +byte bally = 50; // coordinate of the ball +int vdir = -1; // vertical direction and step distance +int hdir = -1; // horizontal direction and step distance +long lastFrame = 0; // time since the screen was updated last +boolean row1[16]; // on-off array of blocks +boolean row2[16]; +boolean row3[16]; +int score = 0; // score - counts the number of blocks hit and resets the array above when devisible by 48(total blocks) +ISR(PCINT0_vect){ // PB0 pin button interrupt + if (player >0){player--;} + return; +} +void playerInc(){ // PB2 pin button interrupt + if (player <128-platformWidth){player++;} +} + +void setup() { + resetGame(); + DDRB = 0b00000010; // set PB1 as output (for the speaker) + PCMSK = 0b00000001; // pin change mask: listen to portb bit 1 + GIMSK |= 0b00100000; // enable PCINT interrupt + sei(); // enable all interrupts + attachInterrupt(0,playerInc,CHANGE); + lastFrame = millis(); +} +void loop() { + delay(40); + noInterrupts(); + ssd1306_init(); + ssd1306_fillscreen(0x00); + ssd1306_char_f6x8(16, 4, "B R E A K O U T"); + ssd1306_char_f6x8(20, 6, "webboggles.com"); + beep(200,600); beep(300,200); beep(400,300); + delay(2000); + while (1==1) { + // continue moving after the interrupt + if (digitalRead(2)==1){if (player <128-platformWidth){player++;} if (player <128-platformWidth){player++;} if (player <128-platformWidth){player++;}} if (digitalRead(0)==1){if (player >0){player--;} if (player >0){player--;} if (player >0){player--;}} + + // bounce off the sides of the screen + if ((bally+vdir<54&&vdir==1)||(bally-vdir>1&&vdir==-1)){bally+=vdir;}else {vdir = vdir*-1;} + if ((ballx+hdir<127&&hdir==1)||(ballx-hdir>1&&hdir==-1)){ballx+=hdir;}else {hdir = hdir*-1;} + + // frame actions + if (lastFrame+1010&&bally+vdir>=54&&(ballxplayer+platformWidth)){ // game over if the ball misses the platform + int topScore = EEPROM.read(0); + topScore = topScore << 8; topScore = topScore | EEPROM.read(1); if (score>topScore){topScore = score; EEPROM.write(1,topScore & 0xFF); EEPROM.write(0,(topScore>>8) & 0xFF); } + ssd1306_fillscreen(0x00); + ssd1306_char_f6x8(32, 3, "Game Over"); + ssd1306_char_f6x8(32, 5, "score:"); + char temp[4] = {0,0,0,0}; + itoa(score,temp,10); + ssd1306_char_f6x8(70, 5, temp); + ssd1306_char_f6x8(32, 6, "top score:"); + itoa(topScore,temp,10); + ssd1306_char_f6x8(90, 6, temp); + for (int i = 0; i<1000; i++){ + beep(1,random(0,i*2)); + } + delay(1000); + system_sleep(); + resetGame(); + }else if (ballx10&&bally+vdir>=54){ // if the ball hits left of the platform bounce left + hdir=-1; beep(20,600); + }else if (ballx>player+platformWidth/2&&bally>10&&bally+vdir>=54){ // if the ball hits right of the platform bounce right + hdir=1; beep(20,600); + }else if (bally+vdir>=54){ + hdir=1; beep(20,600); + } + + collisionCheck: // go back to here if a collision was detected to prevent flying through a rigid + if (floor((bally+vdir)/8)==2){ + if (row3[ballx/8]==1){row3[ballx/8]=0; score++; + collision(); goto collisionCheck; // check collision for the new direction to prevent flying through a rigid + } + }else if (floor((bally+vdir)/8)==1){ + if (row2[ballx/8]==1){row2[ballx/8]=0; score++; + collision(); goto collisionCheck; + } + }else if (floor((bally+vdir)/8)==0){ + if (row1[ballx/8]==1){row1[ballx/8]=0; score++; + collision(); goto collisionCheck; + } + } + + // reset blocks if all have been hit + if (score%48==0){ + for (byte i =0; i<16;i++){ + row1[i]=1; row2[i]=1; row3[i]=1; + } + } + } + + // update whats on the screen + noInterrupts(); + + // blocks + ssd1306_setpos(0,0); + ssd1306_send_data_start(); + for (int bl = 0; bl <16; bl++){ + if(row1[bl]==1){ + sendBlock(1); + }else { + sendBlock(0); + } + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,1); + ssd1306_send_data_start(); + for (int bl = 0; bl <16; bl++){ + if(row2[bl]==1){ + sendBlock(1); + }else { + sendBlock(0); + } + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,2); + ssd1306_send_data_start(); + for (int bl = 0; bl <16; bl++){ + if(row3[bl]==1){ + sendBlock(1); + }else { + sendBlock(0); + } + } + ssd1306_send_data_stop(); + + // clear area below the blocks + ssd1306_setpos(0,3); + ssd1306_send_data_start(); + for (byte i =0; i<128; i++){ + ssd1306_send_byte(B00000000); + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,4); + ssd1306_send_data_start(); + for (byte i =0; i<128; i++){ + ssd1306_send_byte(B00000000); + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,5); + ssd1306_send_data_start(); + for (byte i =0; i<128; i++){ + ssd1306_send_byte(B00000000); + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,6); + ssd1306_send_data_start(); + for (byte i =0; i<128; i++){ + ssd1306_send_byte(B00000000); + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,7); + ssd1306_send_data_start(); + for (byte i =0; i<128; i++){ + ssd1306_send_byte(B00000000); + } + ssd1306_send_data_stop(); + + // draw ball + ssd1306_setpos(ballx,bally/8); + uint8_t temp = B00000001; + ssd1306_send_data_start(); + temp = temp << bally%8+1; + ssd1306_send_byte(temp); + ssd1306_send_data_stop(); + + drawPlatform(); + interrupts(); + // + + } +} +void resetGame(){ + ssd1306_char_f6x8(16, 4, "B R E A K O U T"); + ssd1306_char_f6x8(20, 6, "webboggles.com"); + beep(200,600); beep(300,200); beep(400,300); + delay(2000); + for (byte i =0; i<16;i++){ // reset blocks + row1[i]=1; row2[i]=1; row3[i]=1; + } + platformWidth = 16; + ballx = 64; + bally = 50; + hdir = -1; + vdir = -1; + score = 0; + player = random(0,128-platformWidth); + ballx = player+platformWidth/2; +} + +void collision(){ // the collsision check is actually done befor this is called, this code works out where the ball will bounce + if ((bally+vdir)%8==7&&(ballx+hdir)%8==7){ // bottom right corner + if (vdir==1){hdir=1;}else if(vdir==-1&&hdir==1){vdir=1;}else {hdir=1;vdir=1;} + }else if ((bally+vdir)%8==7&&(ballx+hdir)%8==0){ // bottom left corner + if (vdir==1){hdir=-1;}else if(vdir==-1&&hdir==-1){vdir=1;}else {hdir=-1;vdir=1;} + }else if ((bally+vdir)%8==0&&(ballx+hdir)%8==0){ // top left corner + if (vdir==-1){hdir=-1;}else if(vdir==1&&hdir==-1){vdir=-1;}else {hdir=-1;vdir=-1;} + }else if ((bally+vdir)%8==0&&(ballx+hdir)%8==7){ // top right corner + if (vdir==-1){hdir=1;}else if(vdir==1&&hdir==1){vdir=-1;}else {hdir=1;vdir=-1;} + }else if ((bally+vdir)%8==7){ // bottom side + vdir = 1; + }else if ((bally+vdir)%8==0){ // top side + vdir = -1; + }else if ((ballx+hdir)%8==7){ // right side + hdir = 1; + }else if ((ballx+hdir)%8==0){ // left side + hdir = -1; + }else { + hdir = hdir*-1; vdir = vdir*-1; + } + + beep(30,300); + +} +void drawPlatform(){ + noInterrupts(); + ssd1306_setpos(player,7); + ssd1306_send_data_start(); + for (byte pw = 1; pw >4)|0x10); // |0x10 + ssd1306_send_byte((x&0x0f)|0x01); // |0x01 + + ssd1306_xfer_stop(); +} + +void ssd1306_fillscreen(uint8_t fill_Data){ + uint8_t m,n; + for(m=0;m<8;m++) + { + ssd1306_send_command(0xb0+m); //page0-page1 + ssd1306_send_command(0x00); //low column start address + ssd1306_send_command(0x10); //high column start address + ssd1306_send_data_start(); + for(n=0;n<128;n++) { ssd1306_send_byte(fill_Data); } ssd1306_send_data_stop(); } } void ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]){ uint8_t c,i,j=0; while(ch[j] != '\0') { c = ch[j] - 32; if(x>126) + { + x=0; + y++; + } + ssd1306_setpos(x,y); + ssd1306_send_data_start(); + for(i=0;i<6;i++) + { + ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i])); + } + ssd1306_send_data_stop(); + x += 6; + j++; + } +} + +// Routines to set and clear bits (used in the sleep code) +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +void system_sleep() { + ssd1306_fillscreen(0x00); + ssd1306_send_command(0xAE); + cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF + set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here + sleep_enable(); + sleep_mode(); // System actually sleeps here + sleep_disable(); // System continues execution here when watchdog timed out + sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON + ssd1306_send_command(0xAF); +} \ No newline at end of file diff --git a/platformio/examples/breakout/src/game.rob b/platformio/examples/breakout/src/game.rob new file mode 100644 index 0000000..caeb387 --- /dev/null +++ b/platformio/examples/breakout/src/game.rob @@ -0,0 +1,241 @@ +/* + * Robcmp examples: Breakout game on a SSD1306 display + */ + +use math.random16; +use graphic.canvas8; +use math.abs; +use intfs.mcu; +use intfs.display; + + +type game { + + // Bar related vars + bar_middle = 0u; + bar_width = 30u; + bar_next_move = 0; + + // Ball related vars + ball_dir_x = 1; + ball_dir_y = 1; + ball_pos_x = 0u; + ball_pos_y = 0u; + + // Game status + paused = false; + gameover = false; + level = 0; + rem_blocks = 0u; + + // Blocks const and vars + start_y = 0u; + const bottom_margin = 4; + + /* The size and position of game elements + blocks = 129/(width+1) + use block width = 5, 21 blocks */ + const block_size = 4; + const block_sizesp = 4+1; + const right_margin = 25 * block_sizesp - 1; + blocks = {{true:25}:5}; + + void move_bar(canvas8 canvas) { + if bar_next_move == 0 { + return; + } + pixels = bar_next_move; + bar_next_move = 0; + + left_limit = bar_width/2 - 1; + right_limit = right_margin - bar_width/2; + + if bar_middle + pixels < left_limit { + pixels = left_limit - bar_middle + 1; + } else if bar_middle + pixels > right_limit { + pixels = right_limit - bar_middle; + } + + if pixels == 0 { + return; + } + + move = abs8(pixels); + bar_middle += pixels; + start = bar_middle - bar_width/2; + end = start + bar_width - 1; + set = pixels > 0; + if pixels < 0 { + canvas.fill_rect(start, bottom_margin-4, start+move-1, bottom_margin-2, true); + canvas.fill_rect(end+1, bottom_margin-4, end+move, bottom_margin-2, false); + } else { + canvas.fill_rect(start-move, bottom_margin-4, start-1, bottom_margin-2, false); + canvas.fill_rect(end-move+1, bottom_margin-4, end, bottom_margin-2, true); + } + + if paused { + // when paused, set ball direction according + // to the first movement + if pixels > 0 { + ball_dir_x = 1; + } else { + ball_dir_x = -1; + } + } + } + + void update_block(canvas8 canvas, uint8 row, uint8 col) { + c = col * (block_size+1); + r = start_y + row * (block_size+1); + status = blocks[row][col]; + canvas.fill_rect(c, r, c+block_size-1, r+block_size-1, status); + } + + void draw_blocks(canvas8 canvas, display oled, mcu mmcu) { + // update blocks according to the level + if level > 1 { + i = 0u; + while i < level*10 { + arow = random16() % blocks.rows; + acol = random16() % blocks.cols; + blocks[arow][acol] = true; + i++; + } + } + + // draw blocks + row = 0u; + while row < blocks.rows { + col = 0u; + while col < blocks.cols { + if level > 1 { + v = !blocks[row][col]; + blocks[row][col] = v; + } + update_block(canvas, row, col); + if blocks[row][col] { + rem_blocks++; + } + col++; + } + row++; + mmcu.wait_ms(100); // animation effect + oled.update_frame(); + } + oled.update_frame(); + } + + void init_level(canvas8 canvas, display oled, mcu mmcu) { + start_y = canvas.height() - blocks.rows * block_sizesp; + + draw_blocks(canvas, oled, mmcu); + + // hide current bar + start = bar_middle - bar_width/2; + canvas.fill_rect(start, bottom_margin-4, start + bar_width-1, bottom_margin-2, false); + bar_width = 30 - level; + if bar_width < 10 { + bar_width = 10; + } + // draw new bar + bar_middle = uint8(right_margin/2); + start = bar_middle - bar_width/2; + canvas.fill_rect(start, bottom_margin-4, start + bar_width-1, bottom_margin-2, true); + + // set ball initial pos + ball_dir_x = 1; + ball_dir_y = 1; + ball_pos_x = bar_middle; + ball_pos_y = bottom_margin; + canvas.fill_rect(ball_pos_x - 1, ball_pos_y - 1, ball_pos_x, ball_pos_y, true); + } + + void move_ball(canvas8 canvas) { + canvas.fill_rect(ball_pos_x - 1, ball_pos_y - 1, ball_pos_x, ball_pos_y, false); + + // ball_pos_{x,y} represents the top right pixel of the ball + + if ball_pos_y >= start_y - 1 { + ball_edge_x = ball_pos_x; + if ball_dir_x == -1 { + ball_edge_x--; + } + bcol = ball_edge_x / block_sizesp; + + brow = (ball_pos_y + 1 - start_y) / block_sizesp; + if ball_dir_y == -1 { + brow = (ball_pos_y - start_y) / block_sizesp; + } + + if (brow < blocks.rows and + bcol < blocks.cols and + blocks[brow][bcol]) { + + blocks[brow][bcol] = false; + rem_blocks--; + update_block(canvas, brow, bcol); + + hit_y = (ball_pos_y + 1 - start_y) % block_sizesp == 0; + hit_x = ball_pos_x % block_sizesp == 0; + + if hit_y { + ball_dir_y *= -1; + } else if hit_x { + ball_dir_x *= -1; + } + } + } + + if (ball_dir_x == -1 and ball_pos_x - 1 == 0) or // hit left margin + (ball_dir_x == 1 and ball_pos_x + 1 == right_margin) { // hit right margin + ball_dir_x *= -1; + } + + if ball_dir_y == 1 and ball_pos_y == canvas.height() - 1 { + // hit top + ball_dir_y *= -1; + + } else if ball_dir_y == -1 and ball_pos_y - 1 == bottom_margin { + // hit bottom + ball_dir_y *= -1; + mwidth = bar_width/2; + if ball_pos_x < bar_middle - mwidth or + ball_pos_x > bar_middle + mwidth { + //gameover = true; + } + } + + ball_pos_x += ball_dir_x; + ball_pos_y += ball_dir_y; + + if rem_blocks > 0 { + canvas.fill_rect(ball_pos_x - 1, ball_pos_y - 1, ball_pos_x, ball_pos_y, true); + } + } + + void check_level_done(canvas8 canvas, display oled, mcu mmcu) { + if rem_blocks == 0 { + //set_level_debug(); + level = (level+1) % 30; + init_level(canvas, oled, mmcu); + //paused = true; + } + } + + key_press implements interrupt_i8 { + void handler(uint8 key) { + if gameover { + gameover = false; + level = 0; + } else { + if key == 'C' {// right + bar_next_move += 10; + } else if key == 'D' { + bar_next_move -= 10; + } + } + paused = false; + } + } + +} diff --git a/platformio/examples/breakout/src/main.rob b/platformio/examples/breakout/src/main.rob new file mode 100644 index 0000000..bf966c0 --- /dev/null +++ b/platformio/examples/breakout/src/main.rob @@ -0,0 +1,68 @@ +/* + * Robcmp examples: Breakout game on a SSD1306 display + */ + +use intfs.ports; +use intfs.mcu; +use intfs.display; +use intfs.databus; + +use graphic.canvas8; +use game; + +type globals { + mmcu = mcu(); + oled = display(); + dbus_display = databus(); + dbus_uart = databus(); +} + +void setup_hardware(globals gg) { + // dbus_serial setup + dbus_uart = gg.dbus_uart; + dbus_uart.setup(115200); + dbus_uart.enable(); + dbus_uart.write_array("Robcmp Breakout Game for SSD1306 肖\n"); + dbus_uart.write_array("Use left/right arrows to move and space to pause.\n"); + + // dbus_display setup + dbus_display = gg.dbus_display; + dbus_display.setup(0); + dbus_display.enable(); + + // init display + oled = gg.oled; + oled.set_address(0x78); + oled.init_display(); + //oled.clear(); + + // enable interruptions + mmcu = gg.mmcu; + mmcu.set_interruptions(true); +} + +int8 main() { + gg = globals(); + setup_hardware(gg); + + dbus_uart = gg.dbus_uart; + mmcu = gg.mmcu; + oled = gg.oled; + + gm = game(); + k = gm.key_press; + dbus_uart.async_read_to(k); + canvas = canvas8(); + + loop { + gm.move_bar(canvas); + + if !gm.paused and !gm.gameover { + mmcu.wait_ms(20); + gm.move_ball(canvas); + } + + gm.check_level_done(canvas, oled, mmcu); + oled.update_frame(); + } +} diff --git a/platformio/examples/old/avr328p-blink/.gitignore b/platformio/examples/old/avr328p-blink/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/platformio/examples/old/avr328p-blink/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/platformio/examples/old/avr328p-blink/platformio.ini b/platformio/examples/old/avr328p-blink/platformio.ini new file mode 100644 index 0000000..e306673 --- /dev/null +++ b/platformio/examples/old/avr328p-blink/platformio.ini @@ -0,0 +1,12 @@ + +[env] +platform = robcmp +board = atmega328p +upload_protocol = serial + +[env:release] +build_type = release + +[env:debug] +build_type = debug +debug_tool = robcmp diff --git a/platformio/examples/old/avr328p-blink/src/main.rob b/platformio/examples/old/avr328p-blink/src/main.rob new file mode 100644 index 0000000..055fe7b --- /dev/null +++ b/platformio/examples/old/avr328p-blink/src/main.rob @@ -0,0 +1,46 @@ +/* + * Robcmp examples: Blink + * Blinks the led on PIN13 + */ + +use wait; + +type PORTB { + pin8 = false; + pin9 = false; + pin10 = false; + pin11 = false; + pin12 = false; + pin13 = false; +} + +register PORTB portb at 0x25; + +type DDRB { + pin8 = false; + pin9 = false; + pin10 = false; + pin11 = false; + pin12 = false; + pin13 = false; +} + +register PORTB ddrb at 0x24; + +int16 main() { + /* pin 13 is controlled by bit 5 of DDRB and PORTB registers + * - bit 5 of DDRB indicates if the pin is input (0) or output (1) + * - bit 5 of PORTB toggles pin HIGH or LOW + */ + + // set pin 13 as output + ddrb.pin13 = true; + + loop { + portb.pin13 = true; + wait(100000); + + portb.pin13 = false; + wait(100000); + } +} diff --git a/platformio/examples/old/avr328p-blink/src/wait.rob b/platformio/examples/old/avr328p-blink/src/wait.rob new file mode 100644 index 0000000..c55893f --- /dev/null +++ b/platformio/examples/old/avr328p-blink/src/wait.rob @@ -0,0 +1,7 @@ + +void wait(int32 q) { + volatile i = q; + while (i > 0) { + i--; + } +} diff --git a/platformio/examples/old/avr328p-ssd1306/.gitignore b/platformio/examples/old/avr328p-ssd1306/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/platformio/examples/old/avr328p-ssd1306/platformio.ini b/platformio/examples/old/avr328p-ssd1306/platformio.ini new file mode 100644 index 0000000..2d81cd4 --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/platformio.ini @@ -0,0 +1,39 @@ + +[atmega328p] +platform = robcmp +board = atmega328p +upload_protocol = serial + +[env:atmega328p_release_spi] +extends = atmega328p +build_type = release +debug_tool = robcmp-ssd1306 +board_hardware_spec = specs/avr-spi.spec + +[env:atmega328p_release_i2c] +extends = atmega328p +build_type = release +debug_tool = robcmp-led +board_hardware_spec = specs/avr-i2c.spec + +[env:atmega328p_debug_spi] +extends = atmega328p +build_type = debug +debug_tool = robcmp-ssd1306 +board_hardware_spec = specs/avr-spi.spec + +[env:atmega328p_debug_i2c] +extends = atmega328p +build_type = debug +debug_tool = robcmp-led +board_hardware_spec = specs/avr-i2c.spec + +[stm32f1] +platform = robcmp +board = stm32f1 +upload_protocol = stlink + +[env:stm32f1_debug_i2c] +extends = stm32f1 +build_type = debug +board_hardware_spec = specs/stm32f1-i2c.spec diff --git a/platformio/examples/old/avr328p-ssd1306/specs/avr-i2c.spec b/platformio/examples/old/avr328p-ssd1306/specs/avr-i2c.spec new file mode 100644 index 0000000..10f03a2 --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/specs/avr-i2c.spec @@ -0,0 +1,18 @@ +/* + * Injections for a SSD1306 I2C display + * and an Atmega328p mcu + */ + +bind avr5mcu to global_instances.mmcu singleton; +bind avr5mcu to ssd1306.mmcu singleton; +bind avr5mcu.b5 to global_instances.led singleton; + +// I2C display +bind null_digitalport to ssd1306.reset singleton; +bind null_digitalport to ssd1306.datacmd singleton; +bind null_digitalport to ssd1306.select singleton; +bind avr5mcu.i2c to global_instances.dbus singleton; +bind avr5mcu.i2c to ssd1306.dbus singleton; + +bind ssd1306 to global_instances.oled singleton; +bind ssd1306.framebuffer to canvas8.buffer singleton; diff --git a/platformio/examples/old/avr328p-ssd1306/specs/avr-spi.spec b/platformio/examples/old/avr328p-ssd1306/specs/avr-spi.spec new file mode 100644 index 0000000..688319e --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/specs/avr-spi.spec @@ -0,0 +1,18 @@ +/* + * Injections for a SSD1306 SPI display + * and an Atmega328p mcu + */ + +bind avr5mcu to global_instances.mmcu singleton; +bind avr5mcu to ssd1306.mmcu singleton; +bind avr5mcu.b5 to global_instances.led singleton; + +// SPI display +bind avr5mcu.b0 to ssd1306.reset singleton; +bind avr5mcu.b1 to ssd1306.datacmd singleton; +bind avr5mcu.b2 to ssd1306.select singleton; +bind avr5mcu.spi to global_instances.dbus singleton; +bind avr5mcu.spi to ssd1306.dbus singleton; + +bind ssd1306 to global_instances.oled singleton; +bind ssd1306.framebuffer to canvas8.buffer singleton; \ No newline at end of file diff --git a/platformio/examples/old/avr328p-ssd1306/specs/stm32f1-i2c.spec b/platformio/examples/old/avr328p-ssd1306/specs/stm32f1-i2c.spec new file mode 100644 index 0000000..9e02845 --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/specs/stm32f1-i2c.spec @@ -0,0 +1,19 @@ +/* + * Injections for a SSD1306 I2C display + * and an stm32f103 mcu + */ + + bind stm32f1 to global_instances.mmcu singleton; + bind stm32f1 to ssd1306.mmcu singleton; + bind stm32f1.c13 to global_instances.led singleton; + + // I2C display + bind null_digitalport to ssd1306.reset singleton; + bind null_digitalport to ssd1306.datacmd singleton; + bind null_digitalport to ssd1306.select singleton; + bind stm32f1.i2c1 to global_instances.dbus singleton; + bind stm32f1.i2c1 to ssd1306.dbus singleton; + + bind ssd1306 to global_instances.oled singleton; + bind ssd1306.framebuffer to canvas8.buffer singleton; + \ No newline at end of file diff --git a/platformio/examples/old/avr328p-ssd1306/src/main.rob b/platformio/examples/old/avr328p-ssd1306/src/main.rob new file mode 100644 index 0000000..b09d34d --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/src/main.rob @@ -0,0 +1,113 @@ +/* + * Robcmp examples: SSD1306 + */ + +//TODO: Move to .spec +//use arch.avr.avr5mcu; +use arch.stm32.stm32f1; +use display.ssd1306; + +use graphic.canvas8; +use math.random16; +use math.random32; +use intfs.mcu; +use intfs.display; +use intfs.databus; + +// for now, the binding only works inside a type +type global_instances { + mmcu = mcu(); + dbus = databus(); + oled = display(); + led = digitalport(); +} + +int16 main() { + gi = global_instances(); + mmcu = gi.mmcu; + dbus = gi.dbus; + canvas = canvas8(); + + // blink start + led = gi.led; + led.mode(port_mode.output); + led.set(true); + mmcu.wait_ms(500); + led.set(false); + mmcu.wait_ms(500); + led.set(true); + mmcu.wait_ms(500); + + if (dbus.get_protocol() == databus_protocol.I2C) { + dbus.setup(400E3); //400khz + } else { // SPI + dbus.setup(4E6); + } + dbus.enable(); + + oled = gi.oled; + oled.set_address(0x78); + oled.init_display(); + + symbol = {0b00000000, + 0b11111110, + 0b11000011, + 0b11000011, + 0b11111110, + 0b11000110, + 0b11000011, + 0b11000011}; + + col = 0u; + row = 0u; + + count = 1000; + while count > 0 { + col = random16()%(canvas.width()-1); + row = random16()%(canvas.height()-1); + canvas.set_pixel(row, col); + oled.update_frame(); + count--; + } + + loop { + // clear last draw + byte = 0u; + while byte < symbol.size { + symbolcol = 0u; + while symbolcol < 8 { + canvas.clear_pixel(row + byte, col + symbolcol); + symbolcol++; + } + byte++; + } + + col++; + row++; + + if col == canvas.width()-1 or + row == canvas.height()-1 { + //col = uint8(random16ub(canvas.width()-1)); + //row = uint8(random16ub(canvas.height()-1)); + col = random16()%(canvas.width()-1); + row = random16()%(canvas.height()-1); + } + + // clear last draw ball + byte = 0u; + while byte < symbol.size { + symbolcol = 0u; + while symbolcol < 8 { + if symbol[byte] & (1< 0 { + canvas.set_pixel(row + byte, col + (7-symbolcol)); + } + symbolcol++; + } + byte++; + } + + oled.update_frame(); + } + + return 0; +} diff --git a/platformio/examples/old/stm32f1-blink/.gitignore b/platformio/examples/old/stm32f1-blink/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/platformio/examples/old/stm32f1-blink/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/platformio/examples/old/stm32f1-blink/platformio.ini b/platformio/examples/old/stm32f1-blink/platformio.ini new file mode 100644 index 0000000..1afa668 --- /dev/null +++ b/platformio/examples/old/stm32f1-blink/platformio.ini @@ -0,0 +1,7 @@ + +[env:bluepill] +platform = robcmp +build_type = debug +board = stm32f1 +upload_protocol = stlink +board_hardware_spec = src/hardware.spec \ No newline at end of file diff --git a/platformio/examples/old/stm32f1-blink/src/hardware.spec b/platformio/examples/old/stm32f1-blink/src/hardware.spec new file mode 100644 index 0000000..e69de29 diff --git a/platformio/examples/old/stm32f1-blink/src/main.rob b/platformio/examples/old/stm32f1-blink/src/main.rob new file mode 100644 index 0000000..c7b2ab1 --- /dev/null +++ b/platformio/examples/old/stm32f1-blink/src/main.rob @@ -0,0 +1,21 @@ + +/* + * Sample Blink Led on port 13 for STM32F1 + */ + +use arch.stm32.stm32f1; +use intfs.ports; + +int8 main() { + mmcu = stm32f1(); + + c13 = mmcu.c13; + c13.mode(port_mode.output); + + loop { + c13.set(true); + mmcu.wait_ms(500); + c13.set(false); + mmcu.wait_ms(500); + } +} diff --git a/platformio/examples/ssd1306/.gitignore b/platformio/examples/ssd1306/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/platformio/examples/ssd1306/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/platformio/examples/ssd1306/elf_reader.py b/platformio/examples/ssd1306/elf_reader.py new file mode 100755 index 0000000..70c61e7 --- /dev/null +++ b/platformio/examples/ssd1306/elf_reader.py @@ -0,0 +1,643 @@ +#!python3.9 +# -*- coding: utf-8 -*- + +# Description +# ----------- +# Print information about an ELF binary + +import os +import sys +import textwrap +import traceback + +import lief +from lief import ELF +import argparse + +terminal_rows, terminal_columns = 100, 110 +try: + terminal_rows, terminal_columns = os.popen('stty size', 'r').read().split() +except ValueError: + pass + +terminal_columns = int(terminal_columns) - 10 +terminal_rows = int(terminal_rows) + +class exceptions_handler(object): + func = None + + def __init__(self, exceptions, on_except_callback=None): + self.exceptions = exceptions + self.on_except_callback = on_except_callback + + def __call__(self, *args, **kwargs): + if self.func is None: + self.func = args[0] + return self + try: + return self.func(*args, **kwargs) + except self.exceptions as e: + if self.on_except_callback is not None: + self.on_except_callback(e) + else: + print("-" * 60) + print("Exception in {}: {}".format(self.func.__name__, e)) + exc_type, exc_value, exc_traceback = sys.exc_info() + traceback.print_tb(exc_traceback) + print("-" * 60) + + +@exceptions_handler(Exception) +def print_header(binary): + header = binary.header + identity = header.identity + + + print("== Header ==\n") + format_str = "{:<30} {:<30}" + format_hex = "{:<30} 0x{:<13x}" + format_dec = "{:<30} {:<30d}" + format_ide = "{:<30} {:<02x} {:<02x} {:<02x} {:<02x}" + + eflags_str = "" + if header.machine_type == lief.ELF.ARCH.ARM: + eflags_str = " - ".join([str(s).split(".")[-1] for s in header.arm_flags_list]) + + if header.machine_type in [lief.ELF.ARCH.MIPS, lief.ELF.ARCH.MIPS_RS3_LE, lief.ELF.ARCH.MIPS_X]: + eflags_str = " - ".join([str(s).split(".")[-1] for s in header.mips_flags_list]) + + if header.machine_type == lief.ELF.ARCH.PPC64: + eflags_str = " - ".join([str(s).split(".")[-1] for s in header.ppc64_flags_list]) + + if header.machine_type == lief.ELF.ARCH.HEXAGON: + eflags_str = " - ".join([str(s).split(".")[-1] for s in header.hexagon_flags_list]) + print(identity) + print(format_ide.format("Magic:", identity[0], identity[1], identity[2], identity[3])) + print(format_str.format("Class:", str(header.identity_class).split(".")[-1])) + print(format_str.format("Endianness:", str(header.identity_data).split(".")[-1])) + print(format_str.format("Version:", str(header.identity_version).split(".")[-1])) + print(format_str.format("OS/ABI:", str(header.identity_os_abi).split(".")[-1])) + print(format_dec.format("ABI Version:", header.identity_abi_version)) + print(format_str.format("File Type:", str(header.file_type).split(".")[-1])) + print(format_str.format("Machine Type:", str(header.machine_type).split(".")[-1])) + print(format_str.format("Object File Version:", str(header.object_file_version).split(".")[-1])) + print(format_hex.format("Entry Point:", header.entrypoint)) + print(format_hex.format("Program Header Offset:", header.program_header_offset)) + print(format_hex.format("Section Header Offset:", header.section_header_offset)) + print(format_hex.format("Processor flags:", header.processor_flag) + eflags_str) + print(format_dec.format("Header Size:", header.header_size)) + print(format_dec.format("Program Header Size:", header.program_header_size)) + print(format_dec.format("Section Header Size:", header.section_header_size)) + print(format_dec.format("Number of segments:", header.numberof_segments)) + print(format_dec.format("Number of sections:", header.numberof_sections)) + print("") + + +@exceptions_handler(Exception) +def print_sections(binary): + sections = binary.sections + if len(sections) > 0: + print("== Sections ==\n") + f_title = "|{:<30} | {:<12}| {:<17}| {:<12}| {:<10}| {:<8}| {:<8}|" + f_value = "|{:<30} | {:<12}| 0x{:<14x} | 0x{:<10x}| 0x{:<8x}| {:<8.2f}| {:<10}" + print(f_title.format("Name", "Type", "Virtual address", "File offset", "Size", "Entropy", "Segment(s)")) + + for section in sections: + segments_str = " - ".join([str(s.type).split(".")[-1] for s in section.segments]) + print(f_value.format( + section.name, + str(section.type).split(".")[-1], + section.virtual_address, + section.file_offset, + section.size, + abs(section.entropy), + segments_str)) + print("") + else: + print("No sections") + +@exceptions_handler(Exception) +def print_segments(binary): + segments = binary.segments + # Segments + if len(segments) > 0: + print("== Segments ==\n") + f_title = "|{:<30} | {:<10}| {:<18}| {:<17}| {:<17}| {:<17}| {:<19}|" + f_value = "|{:<30} | {:<10}| 0x{:<16x}| 0x{:<15x}| 0x{:<15x}| 0x{:<15x}| {}" + print(f_title.format("Type", + "Flags", "File offset", "Virtual Address", "Virtual Size", "Size", "Sections")) + + for segment in segments: + sections = segment.sections + s = ", ".join([section.name for section in sections]) + flags_str = ["-"] * 3 + if ELF.SEGMENT_FLAGS.R in segment: + flags_str[0] = "r" + + if ELF.SEGMENT_FLAGS.W in segment: + flags_str[1] = "w" + + if ELF.SEGMENT_FLAGS.X in segment: + flags_str[2] = "x" + flags_str = "".join(flags_str) + + print(f_value.format( + str(segment.type).split(".")[-1], + flags_str, + segment.file_offset, + segment.virtual_address, + segment.virtual_size, + segment.physical_size, s)) + print("") + else: + print("No segments") + +@exceptions_handler(Exception) +def print_dynamic_entries(binary): + dynamic_entries = binary.dynamic_entries + # Dynamic entries + if len(dynamic_entries) == 0: + return + + print("== Dynamic entries ==\n") + f_title = "|{:<16} | {:<10}| {:<20}|" + f_value = "|{:<16} | 0x{:<8x}| {:<20}|" + print(f_title.format("Tag", "Value", "Info")) + for entry in dynamic_entries: + if entry.tag == ELF.DYNAMIC_TAGS.NULL: + continue + + if entry.tag in [ELF.DYNAMIC_TAGS.SONAME, ELF.DYNAMIC_TAGS.NEEDED, ELF.DYNAMIC_TAGS.RUNPATH, ELF.DYNAMIC_TAGS.RPATH]: + print(f_value.format(str(entry.tag).split(".")[-1], entry.value, entry.name)) + elif type(entry) is ELF.DynamicEntryArray: # [ELF.DYNAMIC_TAGS.INIT_ARRAY,ELF.DYNAMIC_TAGS.FINI_ARRAY]: + print(f_value.format(str(entry.tag).split(".")[-1], entry.value, ", ".join(map(hex, entry.array)))) + elif entry.tag == ELF.DYNAMIC_TAGS.FLAGS: + flags_str = " - ".join([str(ELF.DYNAMIC_FLAGS(s)).split(".")[-1] for s in entry.flags]) + print(f_value.format(str(entry.tag).split(".")[-1], entry.value, flags_str)) + elif entry.tag == ELF.DYNAMIC_TAGS.FLAGS_1: + flags_str = " - ".join([str(ELF.DYNAMIC_FLAGS_1(s)).split(".")[-1] for s in entry.flags]) + print(f_value.format(str(entry.tag).split(".")[-1], entry.value, flags_str)) + else: + print(f_value.format(str(entry.tag).split(".")[-1], entry.value, "")) + + print("") + + +@exceptions_handler(Exception) +def print_symbols(symbols, no_trunc): + can_demangle = len(symbols) > 0 and len(symbols[0].demangled_name) > 0 + if can_demangle: + maxsize = max([len(symbol.demangled_name) for symbol in symbols]) + else: + maxsize = max([len(symbol.name) for symbol in symbols]) + + SIZE = 70 + maxsize = min(maxsize, terminal_columns - SIZE) if terminal_columns > SIZE else terminal_columns + + f_title = "|{:<" + str(maxsize) + "} | {:<7}| {:<8}| {:<10}| {:<8}| {:<4}| {:<14}|" + f_value = "|{:<" + str(maxsize) + "} | {:<7}| {:<8x}| {:<10}| {:<8}| {:<4}| {:<14}|" + + print(f_title.format("Name", "Type", "Value", "Visibility", "Binding", "I/E", "Version")) + + for symbol in symbols: + symbol_version = symbol.symbol_version if symbol.has_version else "" + + import_export = "" + if symbol.imported: + import_export = "I" + + if symbol.exported: + import_export = "E" + + symbol_name = symbol.demangled_name + if len(symbol_name) == 0: + symbol_name = symbol.name + + wrapped = textwrap.wrap(symbol_name, maxsize) + + if len(wrapped) <= 1 or no_trunc: + symbol_name = symbol_name + else: + symbol_name = wrapped[0][:-3] + "..." + + print(f_value.format( + symbol_name, + str(symbol.type).split(".")[-1], + symbol.value, + str(symbol.visibility).split(".")[-1], + str(symbol.binding).split(".")[-1], + import_export, + str(symbol_version) + )) + +@exceptions_handler(Exception) +def print_dynamic_symbols(binary, args): + print("== Dynamic symbols ==\n") + print_symbols(binary.dynamic_symbols, args.no_trunc) + + +@exceptions_handler(Exception) +def print_static_symbols(binary, args): + print("== Static symbols ==\n") + print_symbols(binary.static_symbols, args.no_trunc) + +@exceptions_handler(Exception) +def print_relocations(binary, relocations): + f_title = "|{:<10} | {:<10}| {:<8}| {:<8}| {:<8}| {:<15}| {:<30} |" + f_value = "|0x{:<8x} | {:<10}| {:<8d}| {:<8d}| {:<8x}| {:<15}| {:<30} |" + + print(f_title.format("Address", "Type", "Info", "Size", "Addend", "Purpose", "Symbol")) + + for relocation in relocations: + type = str(relocation.type) + if binary.header.machine_type == ELF.ARCH.x86_64: + type = str(ELF.RELOCATION_X86_64(relocation.type)) + elif binary.header.machine_type == ELF.ARCH.i386: + type = str(ELF.RELOCATION_i386(relocation.type)) + elif binary.header.machine_type == ELF.ARCH.ARM: + type = str(ELF.RELOCATION_ARM(relocation.type)) + elif binary.header.machine_type == ELF.ARCH.AARCH64: + type = str(ELF.RELOCATION_AARCH64(relocation.type)) + + symbol_name = "" + if relocation.has_symbol: + symbol: lief.ELF.Symbol = relocation.symbol + if len(symbol.name) > 0: + symbol_name = symbol.name + elif symbol.type == lief.ELF.SYMBOL_TYPES.SECTION: + shndx = symbol.shndx + sections = binary.sections + if 0 < shndx and shndx < len(sections): + symbol_name = sections[shndx].name + " + " + hex(relocation.addend) + else: + symbol_name = "
".format(shndx) + + + print(f_value.format( + relocation.address, + type.split(".")[-1], + relocation.info, + relocation.size, + relocation.addend, + str(relocation.purpose).split(".")[-1], + symbol_name)) + + +@exceptions_handler(Exception) +def print_all_relocations(binary): + dynamicrelocations = binary.dynamic_relocations + pltgot_relocations = binary.pltgot_relocations + object_relocations = binary.object_relocations + + if len(dynamicrelocations) > 0: + print("== Dynamic Relocations ==\n") + print_relocations(binary, dynamicrelocations) + + + if len(pltgot_relocations) > 0: + print("== PLT/GOT Relocations ==\n") + print_relocations(binary, pltgot_relocations) + + if len(object_relocations) > 0: + print("== Object Relocations ==\n") + print_relocations(binary, object_relocations) + +@exceptions_handler(Exception) +def print_exported_symbols(binary, args): + symbols = binary.exported_symbols + + print("== Exported symbols ==\n") + if len(symbols) == 0: + print("No exports!") + return + print_symbols(symbols, args.no_trunc) + +@exceptions_handler(Exception) +def print_imported_symbols(binary, args): + symbols = binary.imported_symbols + print("== Imported symbols ==\n") + + if len(symbols) == 0: + print("No imports!") + return + print_symbols(symbols, args.no_trunc) + +@exceptions_handler(Exception) +def print_information(binary): + print("== Information ==\n") + format_str = "{:<30} {:<30}" + format_hex = "{:<30} 0x{:<28x}" + format_dec = "{:<30} {:<30d}" + print(format_str.format("Name:", binary.name)) + print(format_hex.format("Address base:", binary.imagebase)) + print(format_hex.format("Virtual size:", binary.virtual_size)) + print(format_str.format("PIE:", str(binary.is_pie))) + print(format_str.format("NX:", str(binary.has_nx))) + +@exceptions_handler(Exception) +def print_gnu_hash(binary): + print("== GNU Hash ==\n") + + if not binary.use_gnu_hash: + return + + gnu_hash = binary.gnu_hash + + format_str = "{:<30} {}" + format_hex = "{:<30} 0x{:<28x}" + format_dec = "{:<30} {:<30d}" + + print(format_dec.format("Number of buckets:", gnu_hash.nb_buckets)) + print(format_dec.format("First symbol index:", gnu_hash.symbol_index)) + print(format_hex.format("Shift Count:", gnu_hash.shift2)) + print(format_str.format("Bloom filters:", gnu_hash.bloom_filters)) + print(format_str.format("Buckets:", gnu_hash.buckets)) + print(format_str.format("Hash values:", gnu_hash.hash_values)) + + +@exceptions_handler(Exception) +def print_sysv_hash(binary): + print("== SYSV Hash ==\n") + + if not binary.use_sysv_hash: + return + + sysv_hash = binary.sysv_hash + + format_str = "{:<30} {}" + format_hex = "{:<30} 0x{:<28x}" + format_dec = "{:<30} {:<30d}" + + print(format_dec.format("Number of buckets:", sysv_hash.nbucket)) + print(format_dec.format("Number of chains:", sysv_hash.nchain)) + print(format_str.format("Buckets:", sysv_hash.buckets)) + print(format_str.format("Chains:", sysv_hash.chains)) + + +@exceptions_handler(Exception) +def print_notes(binary): + print("== Notes ==\n") + + format_str = "{:<19} {}" + format_hex = "{:<19} 0x{:<28x}" + format_dec = "{:<19} {:<30d}" + + notes = binary.notes + for idx, note in enumerate(notes): + description = note.description + description_str = " ".join(map(lambda e : "{:02x}".format(e), description[:16])) + if len(description) > 16: + description_str += " ..." + + print("Note #{:d}".format(idx)) + + type_str = note.type_core if note.is_core else note.type + type_str = str(type_str).split(".")[-1] + + print(format_str.format("Name:", note.name)) + print(format_str.format("Type:", type_str)) + print(format_str.format("Description:", description_str)) + + note_details = note.details + + if type(note_details) == lief.ELF.AndroidNote: + print(format_dec.format("SDK Version:", note_details.sdk_version)) + print(format_str.format("NDK Version:", note_details.ndk_version)) + print(format_str.format("NDK build number:", note_details.ndk_build_number)) + + if type(note_details) == lief.ELF.NoteAbi: + version = note_details.version + version_str = "{:d}.{:d}.{:d}".format(version[0], version[1], version[2]) + + print(format_str.format("ABI:", note_details.abi)) + print(format_str.format("Version:", version_str)) + + if ELF.NOTE_TYPES(note.type) == ELF.NOTE_TYPES.GOLD_VERSION: + print(format_str.format("Version:", "".join(map(chr, note.description)))) + + if note.is_core: + print(note_details) + + + print("\n") + + +@exceptions_handler(Exception) +def print_ctor(binary): + print("== Constructors ==\n") + + print("Functions: ({:d})".format(len(binary.ctor_functions))) + for idx, f in enumerate(binary.ctor_functions): + print(" [{:d}] {}: 0x{:x}".format(idx, f.name, f.address)) + +@exceptions_handler(Exception) +def print_strings(binary): + print("== Strings ==\n") + + + strings = binary.strings + print("Strings: ({:d})".format(len(binary.strings))) + for s in strings: + print(" {}".format(s)) + + +@exceptions_handler(Exception) +def print_functions(binary): + print("== Functions ==\n") + + functions = binary.functions + print("Functions: ({:d})".format(len(functions))) + for idx, f in enumerate(functions): + print(" [{:d}] {}: 0x{:x}".format(idx, f.name, f.address)) + + +def main(): + parser = argparse.ArgumentParser(add_help=False, prog=sys.argv[0]) + parser.add_argument("elf_file") + + parser.add_argument('-a', '--all', + action='store_true', dest='show_all', + help='Equivalent to: -h -l -S -s -r -d -V') + + parser.add_argument('-d', '--dynamic', + action='store_true', dest='show_dynamic_tags', + help='Display the dynamic section') + + parser.add_argument('-H', '--help', + action='help', dest='help', + help='Display this information') + + parser.add_argument('-h', '--file-header', + action='store_true', dest='show_file_header', + help='Display the ELF file header') + + parser.add_argument('-i', '--imported', + action='store_true', dest='show_imported_symbols', + help='Display imported symbols') + + parser.add_argument('-l', '--program-headers', '--segments', + action='store_true', dest='show_program_header', + help='Display the program headers') + + parser.add_argument('-S', '--section-headers', '--sections', + action='store_true', dest='show_section_header', + help="Display the sections' headers") + + parser.add_argument('-e', '--headers', + action='store_true', dest='show_all_headers', + help='Equivalent to: -h -l -S') + + parser.add_argument('-s', '--symbols', '--syms', + action='store_true', dest='show_symbols', + help='Display the symbol table') + + parser.add_argument('--dynamic-symbols', '--dsyms', + action='store_true', dest='show_dynamic_symbols', + help='Display the dynamic symbols') + + parser.add_argument('--static-symbols', '--ssyms', + action='store_true', dest='show_static_symbols', + help='Display the static symbols') + + parser.add_argument('-r', '--relocs', + action='store_true', dest='show_relocs', + help='Display the relocations (if present)') + + parser.add_argument('-V', '--version-info', + action='store_true', dest='show_version_info', + help='Display the version sections (if present)') + + parser.add_argument('-x', '--exported', + action='store_true', dest='show_exported_symbols', + help='Display exported symbols') + + parser.add_argument('--gnu-hash', + action='store_true', dest='show_gnu_hash', + help='Display GNU Hash') + + parser.add_argument('--sysv-hash', + action='store_true', dest='show_sysv_hash', + help='Display SYSV Hash') + + parser.add_argument('-n', '--notes', + action='store_true', dest='show_notes', + help='Display Notes') + + parser.add_argument('--no-trunc', + action='store_true', dest='no_trunc', + default=False, + help='Do not trunc symbol names ...') + + parser.add_argument('--ctor', + action='store_true', dest='show_ctor', + help='Constructor functions') + + parser.add_argument('--strings', + action='store_true', dest='show_strings', + help='Strings present in the current ELF') + + parser.add_argument('--functions', + action='store_true', dest='show_functions', + help='List all function addresses found') + + # Logging setup + logger_group = parser.add_argument_group('Logger') + verbosity = logger_group.add_mutually_exclusive_group() + + verbosity.add_argument('--debug', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.DEBUG) + + verbosity.add_argument('--trace', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.TRACE) + + verbosity.add_argument('--info', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.INFO) + + verbosity.add_argument('--warn', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.WARNING) + + verbosity.add_argument('--err', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.ERROR) + + verbosity.add_argument('--critical', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.CRITICAL) + + parser.set_defaults(main_verbosity=lief.logging.LOGGING_LEVEL.WARNING) + + args = parser.parse_args() + + lief.logging.set_level(args.main_verbosity) + binary = ELF.parse(args.elf_file) + print_information(binary) + if args.show_all: + do_file_header = do_section_header = do_program_header = True + + if args.show_all_headers: + do_file_header = do_section_header = do_program_header = True + else: + do_file_header = args.show_file_header + do_section_header = args.show_section_header + do_program_header = args.show_program_header + + if do_file_header or args.show_all: + print_header(binary) + + if do_section_header or args.show_all: + print_sections(binary) + + if do_program_header or args.show_all: + print_segments(binary) + + if args.show_dynamic_tags or args.show_all: + print_dynamic_entries(binary) + + if (args.show_symbols or args.show_all or args.show_dynamic_symbols) and len(binary.dynamic_symbols) > 0: + print_dynamic_symbols(binary, args) + + if (args.show_symbols or args.show_all or args.show_static_symbols) and len(binary.static_symbols) > 0: + print_static_symbols(binary, args) + + if args.show_relocs or args.show_all: + print_all_relocations(binary) + + if args.show_imported_symbols or args.show_all: + print_imported_symbols(binary, args) + + if args.show_exported_symbols or args.show_all: + print_exported_symbols(binary, args) + + if (args.show_gnu_hash or args.show_all) and binary.use_gnu_hash: + print_gnu_hash(binary) + + if (args.show_sysv_hash or args.show_all) and binary.use_sysv_hash: + print_sysv_hash(binary) + + if args.show_notes or args.show_all: + print_notes(binary) + + if args.show_ctor or args.show_all: + print_ctor(binary) + + if args.show_strings or args.show_all: + print_strings(binary) + + if args.show_functions: + print_functions(binary) + + + + +if __name__ == "__main__": + main() diff --git a/platformio/examples/ssd1306/platformio.ini b/platformio/examples/ssd1306/platformio.ini new file mode 100644 index 0000000..79e06f0 --- /dev/null +++ b/platformio/examples/ssd1306/platformio.ini @@ -0,0 +1,30 @@ + +[avr] +platform = robcmp +board = atmega328p +upload_protocol = serial +board_hardware_spec = specs/avr.spec + +[env:avr-release] +extends = avr +build_type = release + +[env:avr-debug] +extends = avr +build_type = debug +debug_tool = robcmp-ssd1306 + + + +[stm32] +platform = robcmp +board = stm32f1 +upload_protocol = stlink +board_hardware_spec = specs/stm32.spec + +[env:stm32-release] +extends = stm32 + +[env:stm32-debug] +extends = stm32 +build_type = debug diff --git a/platformio/examples/ssd1306/sections.txt b/platformio/examples/ssd1306/sections.txt new file mode 100644 index 0000000..de96037 --- /dev/null +++ b/platformio/examples/ssd1306/sections.txt @@ -0,0 +1,31 @@ +== Information == + +Name: .pio/build/stm32-debug/firmware.elf +Address base: 0x7ff0000 +Virtual size: 0x18011000 +PIE: False +NX: True +== Sections == + +|Name | Type | Virtual address | File offset | Size | Entropy | Segment(s)| +| | NULL | 0x0 | 0x0 | 0x0 | 0.00 | +|.isr_vector | PROGBITS | 0x8000000 | 0x10000 | 0x14c | 0.25 | LOAD +|.text | PROGBITS | 0x800014c | 0x1014c | 0x26c | 5.94 | LOAD +|.ARM.exidx | ARM_EXIDX | 0x80003b8 | 0x103b8 | 0x10 | 2.98 | LOAD - ARM_UNWIND +|.data | PROGBITS | 0x20000000 | 0x103c8 | 0x0 | 0.00 | LOAD +|.bss | NOBITS | 0x20000000 | 0x20000 | 0x24 | 0.00 | LOAD +|.got | PROGBITS | 0x20000024 | 0x20024 | 0x4 | 0.81 | LOAD - GNU_RELRO +|.ARM.attributes | ARM_ATTRIBUTES| 0x0 | 0x20028 | 0x3f | 4.82 | +|.debug_abbrev | PROGBITS | 0x0 | 0x20067 | 0x1bb | 4.55 | +|.debug_info | PROGBITS | 0x0 | 0x20222 | 0x1e5c | 4.39 | +|.debug_ranges | PROGBITS | 0x0 | 0x2207e | 0x2c0 | 1.81 | +|.debug_str | PROGBITS | 0x0 | 0x2233e | 0xf39 | 4.94 | +|.debug_pubnames | PROGBITS | 0x0 | 0x23277 | 0x92d | 5.17 | +|.debug_pubtypes | PROGBITS | 0x0 | 0x23ba4 | 0x2ca | 5.02 | +|.debug_frame | PROGBITS | 0x0 | 0x23e70 | 0x79c | 2.27 | +|.debug_line | PROGBITS | 0x0 | 0x2460c | 0xc6f | 4.87 | +|.comment | PROGBITS | 0x0 | 0x2527b | 0x1c | 4.08 | +|.symtab | SYMTAB | 0x0 | 0x25298 | 0x360 | 2.76 | +|.shstrtab | STRTAB | 0x0 | 0x255f8 | 0xcd | 4.28 | +|.strtab | STRTAB | 0x0 | 0x256c5 | 0x280 | 4.64 | + diff --git a/platformio/examples/ssd1306/specs/avr.spec b/platformio/examples/ssd1306/specs/avr.spec new file mode 100644 index 0000000..c7a9c79 --- /dev/null +++ b/platformio/examples/ssd1306/specs/avr.spec @@ -0,0 +1,23 @@ +/* + * Injections for a SSD1306 I2C display + * and an atmega328p mcu + */ + +use arch.avr.avr5mcu; +use display.ssd1306; +use graphic.canvas8; + +bind avr5mcu to globals.mmcu singleton; +bind avr5mcu to ssd1306.mmcu singleton; +bind avr5mcu.b5 to globals.led singleton; + +// SPI display +bind avr5mcu.b0 to ssd1306.reset singleton; +bind avr5mcu.b1 to ssd1306.datacmd singleton; +bind avr5mcu.b2 to ssd1306.select singleton; +bind avr5mcu.spi to globals.dbus singleton; +bind avr5mcu.spi to ssd1306.dbus singleton; + +bind ssd1306 to globals.oled singleton; +bind ssd1306.framebuffer to canvas8.buffer singleton; + \ No newline at end of file diff --git a/platformio/examples/ssd1306/specs/stm32.spec b/platformio/examples/ssd1306/specs/stm32.spec new file mode 100644 index 0000000..c8a70e6 --- /dev/null +++ b/platformio/examples/ssd1306/specs/stm32.spec @@ -0,0 +1,23 @@ +/* + * Injections for a SSD1306 I2C display + * and an stm32f103 mcu + */ + + use arch.stm32.stm32f1; + use display.ssd1306; + use graphic.canvas8; + + bind stm32f1 to globals.mmcu singleton; + bind stm32f1 to ssd1306.mmcu singleton; + bind stm32f1.c13 to globals.led singleton; + + // I2C display + bind null_digitalport to ssd1306.reset singleton; + bind null_digitalport to ssd1306.datacmd singleton; + bind null_digitalport to ssd1306.select singleton; + bind stm32f1.i2c1 to globals.dbus singleton; + bind stm32f1.i2c1 to ssd1306.dbus singleton; + + bind ssd1306 to globals.oled singleton; + bind ssd1306.framebuffer to canvas8.buffer singleton; + \ No newline at end of file diff --git a/platformio/examples/ssd1306/src/main.rob b/platformio/examples/ssd1306/src/main.rob new file mode 100644 index 0000000..b604820 --- /dev/null +++ b/platformio/examples/ssd1306/src/main.rob @@ -0,0 +1,72 @@ +/* + * Robcmp examples: Blink + * Blinks the board default led + */ + +use intfs.ports; +use intfs.mcu; +use intfs.display; +use intfs.databus; + +use math.random16; + +use graphic.canvas8; + +type globals { + mmcu = mcu(); + led = digitalport(); + oled = display(); + dbus = databus(); +} + +int16 main() { + gg = globals(); + mmcu = gg.mmcu; + led = gg.led; + + // blink led 10 times + led.mode(port_mode.output); + count = int16(10); + while count > 0 { + led.set(true); + mmcu.wait_ms(50); + led.set(false); + mmcu.wait_ms(50); + count--; + } + + // setup data bus + dbus = gg.dbus; + dbus.setup(0); + dbus.enable(); + + // init display + oled = gg.oled; + oled.set_address(0x78); + oled.init_display(); + oled.clear(); + + // This canvas will write in the display buffer. + // That is done through injection (see specs folder) + canvas = canvas8(); + + col = 0u; + row = 0u; + count = 1000; + loop { + // set a random pixel + col = uint8(random16()%(canvas.width()-1)); + row = uint8(random16()%(canvas.height()-1)); + canvas.set_pixel(row, col); + + // update display + oled.update_frame(); + + // clear the screen sometimes + count--; + if count == 0 { + canvas.clear(); + count = 1000; + } + } +} diff --git a/platformio/examples/ssd1306/teste b/platformio/examples/ssd1306/teste new file mode 100644 index 0000000..a08bf9d Binary files /dev/null and b/platformio/examples/ssd1306/teste differ diff --git a/platformio/install b/platformio/install index fa6c492..6162cd1 100755 --- a/platformio/install +++ b/platformio/install @@ -3,9 +3,10 @@ cd toolchain-robcmp && tar xfz ../toolchain-robcmp-*.tar.gz cd .. mkdir -p ~/.platformio/platforms mkdir -p ~/.platformio/packages -ln -sf `realpath platform` ~/.platformio/platforms/robcmp -ln -sf `realpath toolchain-robcmp` ~/.platformio/packages/toolchain-robcmp +mkdir -p ~/.platformio/platforms/robcmp +cp -r platform/* ~/.platformio/platforms/robcmp +cp -r toolchain-robcmp ~/.platformio/packages/ code --install-extension vscode-syntax/robcmpsyntax-0.0.1.vsix -echo "Open the samples folder and try to build and upload!" -echo " code samples/avr328p" -echo " code samples/stm32f1" +echo "Open the examples folder and try to build and upload!" +echo " code examples/atmega328p-blink" +echo " code examples/stm32f1" diff --git a/platformio/integrate2vc b/platformio/integrate2vc new file mode 100755 index 0000000..e387cef --- /dev/null +++ b/platformio/integrate2vc @@ -0,0 +1,12 @@ +mkdir -p toolchain-robcmp +cd toolchain-robcmp && make +cd .. +cd ../lib && make +cd .. +mkdir -p ~/.platformio/platforms +mkdir -p ~/.platformio/packages +ln -sf `realpath lib` platformio/toolchain-robcmp/stdlib +ln -sf `realpath platformio/platform` ~/.platformio/platforms/robcmp +ln -sf `realpath platformio/toolchain-robcmp` ~/.platformio/packages/toolchain-robcmp +code --install-extension platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix +echo "Open the examples folder and try to build and upload!" diff --git a/platformio/pkg b/platformio/pkg index 6a4b8c2..a59ed82 100755 --- a/platformio/pkg +++ b/platformio/pkg @@ -1,4 +1,4 @@ PATH=~/.platformio/packages/toolchain-atmelavr/bin/:$PATH cd toolchain-robcmp && make clean && make cd .. -tar cfz robcmp-`uname -s`-`uname -m`-`cat toolchain-robcmp/version`.tar.gz platform samples vscode-syntax/robcmpsyntax-0.0.1.vsix toolchain*.tar.gz install +tar cfz robcmp-`uname -s`-`uname -m`-`cat toolchain-robcmp/version`.tar.gz platform examples vscode-syntax/robcmpsyntax-0.0.1.vsix toolchain*`cat toolchain-robcmp/version`.tar.gz install diff --git a/platformio/platform/__pycache__/platform.cpython-312.pyc b/platformio/platform/__pycache__/platform.cpython-312.pyc new file mode 100644 index 0000000..e1a3f67 Binary files /dev/null and b/platformio/platform/__pycache__/platform.cpython-312.pyc differ diff --git a/platformio/platform/boards/atmega328p.json b/platformio/platform/boards/atmega328p.json new file mode 100644 index 0000000..2475f76 --- /dev/null +++ b/platformio/platform/boards/atmega328p.json @@ -0,0 +1,55 @@ +{ + "build": { + "f_cpu": "16000000L", + "mcu": "atmega328p", + "variant": "standard" + }, + "debug": { + "target_mcu": "atmega328p", + "tools": { + "robcmp-led": { + "init_cmds": [ + "target remote $DEBUG_PORT", + "$LOAD_CMDS" + ], + "port": ":1234", + "server": { + "package": "toolchain-robcmp", + "executable": "bin/robcmp-simavr-debug" + } + }, + "robcmp-ssd1306": { + "init_cmds": [ + "target remote $DEBUG_PORT", + "$LOAD_CMDS" + ], + "port": ":1234", + "server": { + "package": "toolchain-robcmp", + "executable": "bin/robcmp-simavr-debug" + } + }, + "robcmp-hd44780": { + "init_cmds": [ + "target remote $DEBUG_PORT", + "$LOAD_CMDS" + ], + "port": ":1234", + "server": { + "package": "toolchain-robcmp", + "executable": "bin/robcmp-simavr-debug" + } + } + } + }, + "name": "ATmega328P/PA", + "upload": { + "maximum_ram_size": 2048, + "maximum_size": 32768, + "protocol": "arduino", + "require_upload_port": true, + "speed": 115200 + }, + "url": "https://www.microchip.com/wwwproducts/en/ATmega328P", + "vendor": "Microchip" +} diff --git a/platformio/platform/boards/native.json b/platformio/platform/boards/native.json new file mode 100644 index 0000000..61a593a --- /dev/null +++ b/platformio/platform/boards/native.json @@ -0,0 +1,16 @@ +{ + "build": { + "mcu": "native" + }, + "debug": { + "target_mcu": "native", + "tools": {} + }, + "name": "Native", + "url": "", + "vendor": "native", + "upload": { + "protocol": "none" + } + } + \ No newline at end of file diff --git a/platformio/platform/boards/stm32f1.json b/platformio/platform/boards/stm32f1.json new file mode 100644 index 0000000..36e00db --- /dev/null +++ b/platformio/platform/boards/stm32f1.json @@ -0,0 +1,46 @@ +{ + "build": { + "core": "stm32", + "cpu": "cortex-m3", + "f_cpu": "72000000L", + "hwids": [ + [ + "0x1EAF", + "0x0003" + ], + [ + "0x1EAF", + "0x0004" + ] + ], + "mcu": "stm32f103cbt6", + "product_line": "STM32F103xB", + "variant": "PILL_F103XX" + }, + "debug": { + "default_tools": [ + "stlink" + ], + "jlink_device": "STM32F103C8", + "openocd_extra_args": [ + "-c", + "reset_config none" + ], + "openocd_target": "stm32f1x", + "svd_path": "STM32F103xx.svd" + }, + "frameworks": [], + "name": "BluePill F103C8 (128k)", + "upload": { + "maximum_ram_size": 20480, + "maximum_size": 131072, + "protocol": "stlink", + "protocols": [ + "jlink", + "stlink", + "serial" + ] + }, + "url": "http://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32f1-series/stm32f103/stm32f103c8.html", + "vendor": "Generic" +} \ No newline at end of file diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 71202ad..4e605f1 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -2,25 +2,108 @@ Build script for robcmp platform """ +import os import sys from os.path import join from SCons.Script import AlwaysBuild, Builder, Default, DefaultEnvironment, Glob +from platformio.util import get_serial_ports + + +def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 + env.AutodetectUploadPort() + upload_options = {} + if "BOARD" in env: + upload_options = env.BoardConfig().get("upload", {}) + + env = DefaultEnvironment() platform = env.PioPlatform() -ldscripts_folder = platform.get_package_dir("toolchain-robcmp") - -mcu = env.GetProjectOption("custom_mcu") -if mcu == "stm32f1": - ld = "ld.lld" - ldflags = ["-nostdlib", "-entry=main", "-T" + ldscripts_folder + "/share/stm32f1.lld.ld", "-Bstatic"] -elif mcu == "avr328p": - ld = "avr-ld" - ldflags = ["--gc-sections", "-Tdata=0x800100"] +ldscripts_folder = join(platform.get_package_dir("toolchain-robcmp"), "lib") +stdlib_folder = join(platform.get_package_dir("toolchain-robcmp"), "stdlib") + +os.environ['LD_LIBRARY_PATH'] = ldscripts_folder + +# Needed by debug +env.Replace( + PROGNAME="firmware.elf" +) + +sources = [] +auxsources = [] + +board = env.subst("$BOARD") +mcu = env.subst("$BOARD_MCU") +try: + hardware_spec = env.GetProjectOption("board_hardware_spec") +except: + hardware_spec = None + pass + +try: + upload_speed = env.GetProjectOption("upload_speed") +except: + if mcu.startswith("stm32"): + upload_speed = 115200 + else: + upload_speed = 57600 + pass + +if mcu == "native": + ldflags = [] +else: + ldflags = ["-L", stdlib_folder] + ldflags.append("-nostdlib") + ldflags.append("-Bstatic") + ldflags.append("--gc-sections") + ldflags.append("--lto=thin") + +if mcu.startswith("stm32f1"): + ldflags.append("-Tstm32f1.ld") + ldflags.append(join(stdlib_folder, "arm-eabi-libgcc.a")) + ldflags.append(join(stdlib_folder, "cortex-m3-arm-missing.o")) + auxsources += Glob(join(stdlib_folder, "stm32f1.rob")) +elif mcu == "atmega328p": + ldflags.append("-Tatmega328p.ld") + ldflags.append(join(stdlib_folder, "avr5.o")) + auxsources += Glob(join(stdlib_folder, "atmega328p.rob")) +elif mcu == "native": + pass else: sys.stderr.write("The requested mcu is not supported.\n") env.Exit(1) +build_type = env.GetProjectOption("build_type") +robcmp_args = ["robcmp", "-a", board, "-o", "$TARGET"] + +if build_type == "debug": + robcmp_args.append("-g") + robcmp_args.append("-O0") +elif build_type == "release": + robcmp_args.append("-Oz") + +hardware_spec_args = [] +if hardware_spec: + hardware_spec_args = ["-s", hardware_spec] + +robcmp_args.append("-I") +robcmp_args.append(stdlib_folder) +robcmp_args.append("$SOURCE") + +if board.startswith("atmega") or board.startswith("attiny"): + avr_gdb = join(platform.get_package_dir("toolchain-robcmp"), "bin", "avr-gdb") + env.Replace( + GDB=avr_gdb + ) +else: + env.Replace( + GDB="gdb" + ) + + +linker = "ld.lld" +if mcu == "native": + linker = "clang -g -O0" # using clang to link on native platform env.Append( BUILDERS=dict( @@ -29,29 +112,38 @@ suffix=".bin" ), Linker=Builder( - action = ' '.join([ld, "$SOURCES", ' '.join(ldflags), "-o", "$TARGET"]), + action = ' '.join([linker, ' '.join(ldflags), "$SOURCES", "-o", "$TARGET"]), suffix=".elf" ), Rob=Builder( - action = ' '.join(["robcmp", "-a", mcu, "-o", "$TARGET", "$SOURCE"]), + action = ' '.join(robcmp_args), + suffix = '.o', + src_suffix = '.rob', + ), + RobDep=Builder( + action = ' '.join(robcmp_args + hardware_spec_args + ["-bdep"]), suffix = '.o', src_suffix = '.rob', ) ) ) -sources = Glob(env.subst(join("$PROJECT_DIR/src/", "*.rob"))) -#source_fnames = [join("$PROJECT_DIR/src/", f.name) for f in sources] +sources += Glob(env.subst(join("$PROJECT_DIR/src/", "main.rob"))) +#sources += Glob(env.subst(join("$PROJECT_DIR/src/**/", "*.rob"))) #print("SOURCES: ", source_fnames) target_objs = [] for f in sources: + robdep = env.RobDep(join("$BUILD_DIR", f.name + ".o"), f) + # Always building while not proper detect dependencies changes (use inside .rob) + AlwaysBuild(robdep) + target_objs += robdep +for f in auxsources: target_objs += env.Rob(join("$BUILD_DIR", f.name + ".o"), f) target_elf = env.Linker(join("$BUILD_DIR", "firmware"), target_objs) target_bin = env.ElfToBin(join("$BUILD_DIR", "firmware"), target_elf) - # UPLOAD upload_protocol = env.subst("$UPLOAD_PROTOCOL") upload_actions = [] @@ -59,49 +151,65 @@ if upload_protocol == "serial": upload_actions.append(env.VerboseAction(env.AutodetectUploadPort, "Looking for upload port...")) - if mcu == "stm32f1": + if mcu.startswith("stm32"): stm32flash_bin = join(platform.get_package_dir("tool-stm32duino"), "stm32flash") env.Replace( UPLOADER=join(stm32flash_bin, "stm32flash"), - UPLOADERFLAGS=["-g", "0x08000000", "-b", "115200", "-w"], + UPLOADERFLAGS=["-b", upload_speed, "-w"], UPLOADCMD='$UPLOADER $UPLOADERFLAGS "$SOURCE" $UPLOAD_PORT' ) - elif mcu == "avr328p": + elif mcu == "atmega328p": avrdude_bin = join(platform.get_package_dir("tool-avrdude"), "avrdude") avrdude_cfg = join(platform.get_package_dir("tool-avrdude"), "avrdude.conf") env.Replace( UPLOADER=avrdude_bin, - UPLOADERFLAGS=["-C", avrdude_cfg, "-v", "-V", "-c", "arduino", "-p", "m328p", "-U"], + UPLOADERFLAGS=["-C", avrdude_cfg, "-v", "-V", "-c", "arduino", "-p", "m328p", "-b", upload_speed, "-U"], UPLOADCMD='$UPLOADER $UPLOADERFLAGS flash:w:${SOURCE}:i -P $UPLOAD_PORT' ) - + else: sys.stderr.write("Upload protocol %s doesn't support mcu %s\n" % (upload_protocol, mcu)) env.Exit(1) elif upload_protocol == "stlink": - if mcu == "stm32f1": + if mcu.startswith("stm32f1"): openocd_folder = platform.get_package_dir("tool-openocd") env.Replace( UPLOADER=join(openocd_folder, "bin", "openocd"), UPLOADERFLAGS=["-f", join(openocd_folder, "scripts/interface/stlink.cfg"), "-f", join(openocd_folder, "scripts/target/stm32f1x.cfg"), - "-c", "program $SOURCE reset 0x08000000 exit"], + "-c", "program $SOURCE reset exit"], UPLOADCMD="$UPLOADER $UPLOADERFLAGS" ) - + else: sys.stderr.write("Upload protocol %s doesn't support mcu %s\n" % (upload_protocol, mcu)) env.Exit(1) +elif upload_protocol == "none": + pass else: sys.stderr.write("Unknown upload protocol %s\n" % upload_protocol) env.Exit(1) upload_actions.append(env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")) -upload = env.Alias(["upload"], target_bin, upload_actions) +upload = None +if mcu.startswith("stm32"): + upload = env.Alias(["upload"], target_elf, upload_actions) +else: + upload = env.Alias(["upload"], target_bin, upload_actions) AlwaysBuild(upload) -Default(target_bin) \ No newline at end of file +# SIZE +target_size = env.AddPlatformTarget( + "size", + target_elf, + env.VerboseAction("llvm-size -d $SOURCES", "Calculating size $SOURCE"), + "Program Size", + "Calculate program size", +) + +env.Depends(target_bin, "size") +Default(target_bin) diff --git a/platformio/platform/platform.py b/platformio/platform/platform.py index 6f7aa47..997a8a3 100644 --- a/platformio/platform/platform.py +++ b/platformio/platform/platform.py @@ -1,26 +1,99 @@ # # Robcmp compiler platform for platformio -# Require packages according to upload_protocol and custom_mcu +# Require packages according to upload_protocol and board # +import os from platformio.public import PlatformBase class RobcmpPlatform(PlatformBase): def configure_default_packages(self, variables, targets): upload_protocol = variables.get("upload_protocol", "") - custom_mcu = variables.get("custom_mcu") + board = variables.get("board") required_tool = None if upload_protocol == "serial": - if custom_mcu == "avr328p": + if board.startswith("atmega") or board.startswith("attiny"): required_tool = "tool-avrdude" - elif custom_mcu == "stm32f1": + elif board.startswith("stm32"): required_tool = "tool-stm32duino" elif upload_protocol == "stlink": - if custom_mcu == "stm32f1": + if board.startswith("stm32"): required_tool = "tool-openocd" if required_tool: self.packages[required_tool]['optional'] = False return super().configure_default_packages(variables, targets) + + def get_boards(self, id_=None): + result = super().get_boards(id_) + if not result: + return result + if id_: + return self._add_default_debug_tools(result) + else: + for key, value in result.items(): + result[key] = self._add_default_debug_tools(result[key]) + return result + + def _add_default_debug_tools(self, board): + debug = board.manifest.get("debug", {}) + if "tools" not in debug: + debug["tools"] = {} + + if debug.get("target_mcu", ""): + if "robcmp-led" in debug["tools"]: + debug["tools"]["robcmp-led"]["server"]["arguments"] = [ + "-f", "$PROG_PATH", + "-m", debug["target_mcu"], + "-hw", "led", + "-g" + ] + + if "robcmp-ssd1306" in debug["tools"]: + debug["tools"]["robcmp-ssd1306"]["server"]["arguments"] = [ + "-f", "$PROG_PATH", + "-m", debug["target_mcu"], + "-hw", "ssd1306", + "-g" + ] + + if "robcmp-hd44780" in debug["tools"]: + debug["tools"]["robcmp-hd44780"]["server"]["arguments"] = [ + "-f", "$PROG_PATH", + "-m", debug["target_mcu"], + "-hw", "hd44780", + "-g" + ] + + # J-Link, ST-Link + upload_protocols = board.manifest.get("upload", {}).get("protocols", []) + for link in ("jlink", "stlink"): + if link not in upload_protocols or link in debug["tools"]: + continue + + server_args = ["-s", "$PACKAGE_DIR/scripts"] + assert debug.get("openocd_target"), ( + "Missed target configuration for %s" % board.id) + server_args.extend([ + "-f", "interface/%s.cfg" % link, + "-c", "transport select %s" % ( + "hla_swd" if link == "stlink" else "swd"), + "-f", "target/%s.cfg" % debug.get("openocd_target") + ]) + server_args.extend(debug.get("openocd_extra_args", [])) + + debug["tools"][link] = { + "server": { + "package": "tool-openocd", + "executable": "bin/openocd", + "arguments": server_args + } + } + + debug["tools"][link]["onboard"] = link in debug.get("onboard_tools", []) + debug["tools"][link]["default"] = link in debug.get("default_tools", []) + + board.manifest["debug"] = debug + return board diff --git a/platformio/samples/avr328p-blink/platformio.ini b/platformio/samples/avr328p-blink/platformio.ini deleted file mode 100644 index 5c83071..0000000 --- a/platformio/samples/avr328p-blink/platformio.ini +++ /dev/null @@ -1,5 +0,0 @@ - -[env:arduino-pro-micro] -platform = robcmp -custom_mcu = avr328p -upload_protocol = serial diff --git a/platformio/samples/avr328p-blink/src/main.rob b/platformio/samples/avr328p-blink/src/main.rob deleted file mode 100644 index 13e94e9..0000000 --- a/platformio/samples/avr328p-blink/src/main.rob +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Robcmp examples: Blink - * Blinks the led on PIN13 - */ - -register int8 PORTB at 0x25; // pins 8-13 -register int8 DDRB at 0x24; -register int8 PINB at 0x23; - -void wait(); - -int16 main() { - - /* pin 13 is controlled by bit 5 of DDRB and PORTB registers - * - bit 5 of DDRB indicates if the pin is input (0) or output (1) - * - bit 5 of PORTB toggles pin HIGH or LOW - */ - - // set pin 13 as output - DDRB |= 0b00100000; - - loop { - // set bit 5 high - PORTB |= 0b00100000; - wait(); - // set bit 5 low - PORTB &= ~(0b00100000); - wait(); - } -} - diff --git a/platformio/samples/avr328p-blink/src/two.rob b/platformio/samples/avr328p-blink/src/two.rob deleted file mode 100644 index b7ceb5d..0000000 --- a/platformio/samples/avr328p-blink/src/two.rob +++ /dev/null @@ -1,7 +0,0 @@ - -void wait() { - volatile i = 50000; - while (i > 0) { - i--; - } -} diff --git a/platformio/samples/stm32f1-blink/platformio.ini b/platformio/samples/stm32f1-blink/platformio.ini deleted file mode 100644 index 1950f3a..0000000 --- a/platformio/samples/stm32f1-blink/platformio.ini +++ /dev/null @@ -1,5 +0,0 @@ - -[env:bluepill] -platform = robcmp -custom_mcu = stm32f1 -upload_protocol = stlink diff --git a/platformio/samples/stm32f1-blink/src/main.rob b/platformio/samples/stm32f1-blink/src/main.rob deleted file mode 100644 index 91e21d7..0000000 --- a/platformio/samples/stm32f1-blink/src/main.rob +++ /dev/null @@ -1,53 +0,0 @@ - -/* - * Sample Blink Led on port 13 for STM32F1 - */ - -// CLOCK GATES FOR IO -const RCC_BASE = 0x40021000; -register int32 RCC_APB2ENR at (RCC_BASE + 0x18); - -// PORTC is enabled by IO PC EN, the bit four in RCC_APB2ENR -const RCC_APB2ENR_IOP_C_EN = (1 << 4); - -// GPIO PORTC base address -const GPIO_PORTC_BASE = 0x40011000; -// PORTC registers -register int32 GPIOC_CRH at (GPIO_PORTC_BASE + 0x4); -register int32 GPIOC_ODR at (GPIO_PORTC_BASE + 0xC); - -const PIN_MODE_INPUT = 0x0; -const PIN_MODE_OUTPUT10MHz = 0x1; -const PIN_MODE_OUTPUT2MHz = 0x2; -const PIN_MODE_OUTPUT50MHz = 0x3; - -const INPUT_MODE_ANALOG = 0x0; -const INPUT_MODE_FLOATING = 0x1; -const INPUT_MODE_PULLUPDOWN = 0x2; - -const OUTPUT_MODE_PUSHPULL = 0x0; -const OUTPUT_MODE_OPENDRAIN = 0x1; -const OUTPUT_MODE_APUSH_PULL = 0x2; -const OUTPUT_MODE_AOPENDRAIN = 0x3; - -void wait(); - -void main() { - - // Enable port C clock gate. - RCC_APB2ENR |= RCC_APB2ENR_IOP_C_EN; - - // PORT C, PIN 13 as OUTPUT 50MHz - GPIOC_CRH &= ~(0x3 << ((13-8)*4)); - GPIOC_CRH |= PIN_MODE_OUTPUT50MHz << ((13-8)*4); - // PORT C, PIN13 as PUSHPULL - GPIOC_CRH &= ~(0x3 << ((13-8)*4+2)); - GPIOC_CRH |= OUTPUT_MODE_PUSHPULL << ((13-8)*4+2); - - loop { - GPIOC_ODR &= ~(1 << 13); - wait(); - GPIOC_ODR |= 1 << 13; - wait(); - } -} diff --git a/platformio/samples/stm32f1-blink/src/two.rob b/platformio/samples/stm32f1-blink/src/two.rob deleted file mode 100644 index 5b09d61..0000000 --- a/platformio/samples/stm32f1-blink/src/two.rob +++ /dev/null @@ -1,7 +0,0 @@ - -void wait() { - volatile i = 100000; - while (i > 0) { - i--; - } -} diff --git a/platformio/toolchain-robcmp/Makefile b/platformio/toolchain-robcmp/Makefile index 7cecedf..193a4e3 100644 --- a/platformio/toolchain-robcmp/Makefile +++ b/platformio/toolchain-robcmp/Makefile @@ -1,16 +1,16 @@ -LLVM_OBJCOPY=$(shell which llvm-objcopy-16) +LLVM_OBJCOPY=$(shell which llvm-objcopy-20) ifeq ($(LLVM_OBJCOPY),) LLVM_OBJCOPY=$(shell which llvm-objcopy) endif -LLVM_LD=$(shell which ld.lld-16) +LLVM_LD=$(shell which ld.lld-20) ifeq ($(LLVM_LD),) LLVM_LD=$(shell which ld.lld) endif -AVR_LD=$(shell which avr-ld) -ifeq ($(AVR_LD),) - $(error "Can't find avr-ld!") +LLVM_SIZE=$(shell which llvm-size-20) +ifeq ($(LLVM_SIZE),) + LLVM_SIZE=$(shell which llvm-size) endif ifeq ($(LLVM_LD),) @@ -21,7 +21,28 @@ ifeq ($(LLVM_OBJCOPY),) $(error "Can't find llvm-objcopy!") endif -TOOLS=$(LLVM_OBJCOPY) $(LLVM_LD) $(AVR_LD) ../../robcmp +ifeq ($(LLVM_SIZE),) + $(error "Can't find llvm-size!") +endif + +AVR_GDB=$(shell which avr-gdb) +ifeq ($(AVR_GDB),) + $(error "Can't find avr-gdb!") +endif + +AVR_OBJDUMP=$(shell which avr-objdump) +ifeq ($(AVR_OBJDUMP),) + $(error "Can't find avr-objdump!") +endif + + +TOOLS=$(LLVM_OBJCOPY) \ + $(LLVM_LD) \ + $(LLVM_SIZE) \ + $(AVR_GDB) \ + $(AVR_OBJDUMP) \ + $(abspath ../../build/robcmp) \ + $(abspath ../../build/robcmp-simavr-debug) ifeq ($(OS),Windows_NT) uname_S := Windows @@ -30,15 +51,18 @@ else endif ifeq ($(uname_S), Darwin) - suffix=darwin_x86_64 + suffix=darwin_$(shell uname -m) SED=gsed + LIBS=$(shell ./libllvmpathosx.sh ${LLVM_LD}) endif ifeq ($(uname_S), Linux) suffix=linux_x86_64 SED=sed - LIBS=$(shell ./libllvmpath ${LLVM_LD}) + LIBS=$(shell ./libllvmpath.sh ${LLVM_LD}) endif +#LIBS += ../../lib/*.ld ../../lib/*.o ../../lib/*.rob + version=$(shell cat version) all: bin lib ../toolchain-robcmp-${suffix}-${version}.tar.gz @@ -53,11 +77,11 @@ package.json: package-orig.json $(SED) s/sed_system_here/$(suffix)/ $< > $@ ../toolchain-robcmp-${suffix}-${version}.tar.gz: package.json - for f in $(TOOLS); do cp $$f bin; done; - for f in $(LIBS); do cp $$f lib; done; - if [ -f bin/ld.lld-16 ]; then cd bin && ln -s ld.lld-16 ld.lld; fi - if [ -f bin/llvm-objcopy-16 ]; then cd bin && ln -s llvm-objcopy-16 llvm-objcopy; fi - tar cfz $@ $^ bin lib share + ln -sf $(TOOLS) bin + ln -sf $(LIBS) lib + if [ -f bin/ld.lld-20 ]; then cd bin && ln -s ld.lld-20 ld.lld; fi + if [ -f bin/llvm-objcopy-20 ]; then cd bin && ln -s llvm-objcopy-20 llvm-objcopy; fi + tar chfz $@ $^ bin lib clean: rm -rf bin lib *.tar.gz package.json diff --git a/platformio/toolchain-robcmp/libllvmpath b/platformio/toolchain-robcmp/libllvmpath deleted file mode 100755 index 32bc7db..0000000 --- a/platformio/toolchain-robcmp/libllvmpath +++ /dev/null @@ -1 +0,0 @@ -ldd $1|grep libLLVM|sed "s/.*=> \([^( ]*\).*/\1/" diff --git a/platformio/toolchain-robcmp/libllvmpath.sh b/platformio/toolchain-robcmp/libllvmpath.sh new file mode 100755 index 0000000..ee1721c --- /dev/null +++ b/platformio/toolchain-robcmp/libllvmpath.sh @@ -0,0 +1,6 @@ +#find libLLVM and some of its dependencies +libLLVM=`ldd $1|grep libLLVM|sed "s/.*=> \([^( ]*\).*/\1/"` +libz3=`ldd $libLLVM|grep libz3|sed "s/.*=> \([^( ]*\).*/\1/"` +libedit=`ldd $libLLVM|grep libedit|sed "s/.*=> \([^( ]*\).*/\1/"` +libbsd=`ldd $libLLVM|grep libbsd|sed "s/.*=> \([^( ]*\).*/\1/"` +echo $libLLVM $libz3 $libedit $libbsd diff --git a/platformio/toolchain-robcmp/libllvmpathosx.sh b/platformio/toolchain-robcmp/libllvmpathosx.sh new file mode 100755 index 0000000..4673c10 --- /dev/null +++ b/platformio/toolchain-robcmp/libllvmpathosx.sh @@ -0,0 +1,5 @@ +#find libLLVM and some of its dependencies in OSX +libLLVM=`DYLD_PRINT_LIBRARIES=1 $1 -v 2>&1|grep libLLVM|sed "s/.*> //"` +libz3=`DYLD_PRINT_LIBRARIES=1 $1 -v 2>&1|grep libz3|sed "s/.*> //"` +libzstd=`DYLD_PRINT_LIBRARIES=1 $1 -v 2>&1|grep libzstd|sed "s/.*> //"` +echo $libLLVM $libz3 $libzstd diff --git a/platformio/toolchain-robcmp/package.json b/platformio/toolchain-robcmp/package.json new file mode 100644 index 0000000..a1b4da2 --- /dev/null +++ b/platformio/toolchain-robcmp/package.json @@ -0,0 +1,8 @@ +{ + "name": "toolchain-robcmp", + "version": "0.1", + "description": "Robcmp Toolchain", + "keywords": ["toolchain", "build tools", "compiler", "assembler", "linker", "preprocessor", "avr", "stm32"], + "homepage": "https://thborges.github.io/robcmp", "license": "GPL-2.0", + "system": ["linux_x86_64"] +} diff --git a/platformio/toolchain-robcmp/share/stm32f1.lld.ld b/platformio/toolchain-robcmp/share/stm32f1.lld.ld deleted file mode 100644 index 685dc93..0000000 --- a/platformio/toolchain-robcmp/share/stm32f1.lld.ld +++ /dev/null @@ -1,22 +0,0 @@ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K -} - -__reset_stack_pointer = ORIGIN(RAM) + LENGTH(RAM); - -SECTIONS -{ - .text 0x0 : { - . = 0; - /* Set the initial address to 0 */ - LONG(__reset_stack_pointer); - LONG(main | 1); - /* The whole interrupt table is 332 bytes long. Advance to that position. */ - . = 332; - /* And here comes the rest of the code */ - *(.text*) - } > FLASH /* Put this in the flash memory region */ -} - diff --git a/platformio/toolchain-robcmp/stdlib b/platformio/toolchain-robcmp/stdlib new file mode 120000 index 0000000..692df8b --- /dev/null +++ b/platformio/toolchain-robcmp/stdlib @@ -0,0 +1 @@ +/home/rayssa/robcmp/lib \ No newline at end of file diff --git a/platformio/toolchain-robcmp/toolchain-robcmp b/platformio/toolchain-robcmp/toolchain-robcmp new file mode 120000 index 0000000..9355f65 --- /dev/null +++ b/platformio/toolchain-robcmp/toolchain-robcmp @@ -0,0 +1 @@ +/home/rayssa/robcmp/platformio/toolchain-robcmp \ No newline at end of file diff --git a/platformio/toolchain-robcmp/version b/platformio/toolchain-robcmp/version index 49d5957..3b04cfb 100644 --- a/platformio/toolchain-robcmp/version +++ b/platformio/toolchain-robcmp/version @@ -1 +1 @@ -0.1 +0.2 diff --git a/platformio/vscode-syntax/Makefile b/platformio/vscode-syntax/Makefile new file mode 100644 index 0000000..f0211f4 --- /dev/null +++ b/platformio/vscode-syntax/Makefile @@ -0,0 +1,2 @@ +all: + vsce package diff --git a/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix b/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix index 8ad9bf3..d6afee5 100644 Binary files a/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix and b/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix differ diff --git a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json index 6859ef7..de70623 100644 --- a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json +++ b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json @@ -42,25 +42,47 @@ "keywords": { "patterns": [{ "name": "keyword.control.rob", - "match": "\\b(while|loop|if|delay|print|return|register|at|volatile|const)\\b" + "match": "\\b(while|loop|if|else|delay|print|return|register|at|volatile|const|asm|type|interface|implements|use|and|or|copy|bind|to|singleton|transient)\\b" }] }, "types": { "patterns": [{ "name": "storage.type.rob", - "match": "\\b(void|char|int8|int16|int32|int64|long|unsigned|float|double|bool)\\b" + "match": "\\b(void|char|int8|int16|int32|int64|uint8|uint16|uint32|uint64|float|double|ldouble|bool|enum)\\b" + }, + { + "match": "(\\w+)\\s+(\\w+)[\\(\\),]", + "captures": { + "1": { "name": "storage.type.rob" }, + "2": { "name": "variable.name.rob" } + } }] }, "numeric-consts": { "patterns": [{ "name": "constant.numeric.rob", - "match": "\\b(\\d+\\.\\d+L?D?|\\d+|0x[0-9a-fA-F]+|0b[0-1]+)\\b" + "match": "\\b\\d+\\.\\d+([Ee][+-]?[0-9]+)?L?D?\\b" + },{ + "name": "constant.numeric.rob", + "match": "\\b\\d+([Ee][+-]?[0-9]+)?[Uu]?\\b" + },{ + "name": "constant.numeric.rob", + "match": "\\b0x[0-9a-fA-F]+\\b" + },{ + "name": "constant.numeric.rob", + "match": "\\b0b[0-1]+\\b" + },{ + "name": "constant.numeric.rob", + "match": "'\\\\?.'" + },{ + "name": "constant.numeric.rob", + "match": "\\b(true|false)\\b" }] }, "functions": { "patterns": [{ "name": "support.function.rob", - "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*(?=\\())\\b" + "match": "\\b(\\w+(?=\\s*\\())\\b" }] }, "ident": { @@ -82,4 +104,4 @@ } }, "scopeName": "source.rob" -} \ No newline at end of file +} diff --git a/recursive.txt b/recursive.txt deleted file mode 100644 index 06c24f5..0000000 --- a/recursive.txt +++ /dev/null @@ -1,12 +0,0 @@ -int fibonacci (int a){ - if (a == 1){ - return 1; - } - else{ - a = a - 1; - c = fibonacci(a); - return c; - } -} - -b = fibonacci(9); diff --git a/rob.txt b/rob.txt deleted file mode 100644 index 809a8e6..0000000 --- a/rob.txt +++ /dev/null @@ -1,152 +0,0 @@ -PARA_FRENTE = 1.0; -PARA_TRAS = -1.0; -STEPS_PER_CLICK = 50; - -PIN1 = 0.0; -PIN2 = 0.0; -PIN3 = 0.0; -PIN4 = 0.0; -curr_step = 0.0; -CURR_DIR = PARA_FRENTE; - -void step_motor(float curr_step) { - if (curr_step == 0.0) { - OUTPIN1 = 255.0; - OUTPIN2 = 0.0; - OUTPIN3 = 255.0; - OUTPIN4 = 0.0; - } - else if (curr_step == 1.0) { - OUTPIN1 = 0.0; - OUTPIN2 = 255.0; - OUTPIN3 = 255.0; - OUTPIN4 = 0.0; - } - else if (curr_step == 2.0) { - OUTPIN1 = 0.0; - OUTPIN2 = 255.0; - OUTPIN3 = 0.0; - OUTPIN4 = 255.0; - } - else if (curr_step == 3.0) { - OUTPIN1 = 255.0; - OUTPIN2 = 0.0; - OUTPIN3 = 0.0; - OUTPIN4 = 255.0; - } - - RPM = (60.0 * 1000.0) / 4096.0 / 4.0; - DELAY RPM; - - curr_step = curr_step + curr_dir; - if (curr_step == 4.0) { - curr_step = 0.0; - } - else if (curr_step == -1.0) { - curr_step = 3.0; - } -} - -void MOTOR_SHUTDOWN() { - OUTPIN1 = 0.0; - OUTPIN2 = 0.0; - OUTPIN3 = 0.0; - OUTPIN4 = 0.0; -} - -void LOOP_STEPS() { - I = 0.0; - WHILE (I < STEPS_PER_CLICK) { - step_motor(curr_step); - I = I + 1.0; - } - MOTOR_SHUTDOWN(); -} - -STEP_DE = 0.0; -void STEP_RIGHT_LEFT() { - - CURR_STEP = STEP_DE; - PIN1 = 14.0; // A0 - PIN2 = 4.0; - PIN3 = 3.0; - PIN4 = 5.0; - - LOOP_STEPS(); - STEP_DE = CURR_STEP; -} - -STEP_UD = 0.0; -void STEP_UP_DOWN() { - - CURR_STEP = STEP_UD; - PIN1 = 10.0; - PIN2 = 12.0; - PIN3 = 11.0; - PIN4 = 13.0; - - LOOP_STEPS(); - STEP_UD = CURR_STEP; -} - -STEP_FB = 0.0; -void STEP_FRONT_BACK(float direcao) { - - direcao = STEP_FB; - PIN1 = 6.0; - PIN2 = 8.0; - PIN3 = 7.0; - PIN4 = 9.0; - - LOOP_STEPS(); - STEP_FB = direcao; -} - -void OPEN_GRIP() { - Z = SERVO_POS_INC(); -} - -void CLOSE_GRIP() { - Y = SERVO_POS_DEC(); -} - -void blink(float time){ - out 13 = 255.0; - delay time; - out 13 = 0.0; - delay time; -} - -// BLINK_FAST = blink(100.0); -// MAIN LOOP -blink(500.0); -blink(500.0); -var = 1.0; - -while (var >= 1.0) { - F = READ_IR(); - IF (F == 3041526525.0) { // UP - STEP_UP_DOWN(PARA_FRENTE); - } - ELSE IF (F == 3041559165.0) { // DOWN - STEP_UP_DOWN(PARA_TRAS); - } - ELSE IF (F == 3041542845.0) { // LEFT - STEP_RIGHT_LEFT(PARA_FRENTE); - } - ELSE IF (F == 3041575485.0) { // RIGHT - STEP_RIGHT_LEFT(PARA_TRAS); - } - ELSE IF (F == 4111076595.0) { // AUDIO - STEP_FRONT_BACK(PARA_FRENTE); - } - ELSE IF (F == 3041570895.0) { // RIGHT - STEP_FRONT_BACK(PARA_TRAS); - } - ELSE IF (F == 3041546415.0) { // OPEN GRIP - OPEN_GRIP(); - } - ELSE IF (F == 3041579055.0) { // CLOSE GRIP - CLOSE_GRIP(); - } -} diff --git a/rob.vim b/rob.vim index deff6d8..ca62365 100644 --- a/rob.vim +++ b/rob.vim @@ -1,28 +1,30 @@ " Vim syntax file " Language: Robcmp Small LLVM Arduino Frontend " Maintainer: Thiago Borges de Oliveira -" Latest Revision: 1 July 2023 +" Latest Revision: 4 Aug 2023 if exists("b:current_syntax") finish endif -syn keyword keywords while loop if delay print return register at volatile const -syn keyword typeKeywords void char int8 int16 int32 int64 long unsigned float double bool +syn keyword keywords while loop if else delay print return register at volatile const asm type interface implements use copy bind to singleton transient +syn keyword keywords naked weak section inline noinline +syn keyword typeKeywords void char int8 int16 int32 int64 uint8 uint16 uint32 uint64 long float double bool enum syn keyword operatorKeywords and or quando esta servo syn keyword booleanKeyword true false -syn match integerConstants "\<\d\+\>" +syn match integerConstants "\<\d\+\([Ee][=+]\?[0-9]\+\)\?[Uu]\?\>" syn match hexConstants "\<0x[0-9a-fA-F]\+\>" -syn match floatConstants "\<\d\+\.\d\+L\?D\?\>" +syn match floatConstants "\<\d\+\.\d\+\([Ee][-+]\?[0-9]\+\)\?L\?D\?\>" +syn match charConstants "'\\\?.'" syn match inPortKey "\" syn match outPortKey "\" syn match stringSpecial "\\." syn match commentLine "\/\/.*" -syn region commentBlock start="/\*" end="\*/" fold containedin=stmtBlock +syn region stmtBlock start="{" end="}" fold contains=ALL transparent syn region stringConstant start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=stringSpecial -syn region stmtBlock start="{" end="}" keepend transparent fold +syn region commentBlock start="/\*" end="\*/" fold contains=ALL let b:current_syntax = "rob" @@ -30,6 +32,7 @@ hi def link keywords Repeat hi def link integerConstants Constant hi def link hexConstants Constant hi def link floatConstants Constant +hi def link charConstants Constant hi def link stringConstant String hi def link stringSpecial Special hi def link inPortKey Identifier diff --git a/simavr b/simavr new file mode 160000 index 0000000..bf8937e --- /dev/null +++ b/simavr @@ -0,0 +1 @@ +Subproject commit bf8937edb1022bd3e0602e1da9ede3af549ff5a2 diff --git a/src/2018arm/AccelStepper.cpp b/src/2018arm/AccelStepper.cpp deleted file mode 100644 index 981d046..0000000 --- a/src/2018arm/AccelStepper.cpp +++ /dev/null @@ -1,652 +0,0 @@ -// AccelStepper.cpp -// -// Copyright (C) 2009-2013 Mike McCauley -// $Id: AccelStepper.cpp,v 1.23 2016/08/09 00:39:10 mikem Exp $ - -#include "AccelStepper.h" - -#if 0 -// Some debugging assistance -void dump(uint8_t* p, int l) -{ - int i; - - for (i = 0; i < l; i++) - { - Serial.print(p[i], HEX); - Serial.print(" "); - } - Serial.println(""); -} -#endif - -void AccelStepper::moveTo(long absolute) -{ - if (_targetPos != absolute) - { - _targetPos = absolute; - computeNewSpeed(); - // compute new n? - } -} - -void AccelStepper::move(long relative) -{ - moveTo(_currentPos + relative); -} - -// Implements steps according to the current step interval -// You must call this at least once per step -// returns true if a step occurred -boolean AccelStepper::runSpeed() -{ - // Dont do anything unless we actually have a step interval - if (!_stepInterval) - return false; - - unsigned long time = micros(); - if (time - _lastStepTime >= _stepInterval) - { - if (_direction == DIRECTION_CW) - { - // Clockwise - _currentPos += 1; - } - else - { - // Anticlockwise - _currentPos -= 1; - } - step(_currentPos); - - _lastStepTime = time; // Caution: does not account for costs in step() - - return true; - } - else - { - return false; - } -} - -long AccelStepper::distanceToGo() -{ - return _targetPos - _currentPos; -} - -long AccelStepper::targetPosition() -{ - return _targetPos; -} - -long AccelStepper::currentPosition() -{ - return _currentPos; -} - -// Useful during initialisations or after initial positioning -// Sets speed to 0 -void AccelStepper::setCurrentPosition(long position) -{ - _targetPos = _currentPos = position; - _n = 0; - _stepInterval = 0; - _speed = 0.0; -} - -void AccelStepper::computeNewSpeed() -{ - long distanceTo = distanceToGo(); // +ve is clockwise from curent location - - long stepsToStop = (long)((_speed * _speed) / (2.0 * _acceleration)); // Equation 16 - - if (distanceTo == 0 && stepsToStop <= 1) - { - // We are at the target and its time to stop - _stepInterval = 0; - _speed = 0.0; - _n = 0; - return; - } - - if (distanceTo > 0) - { - // We are anticlockwise from the target - // Need to go clockwise from here, maybe decelerate now - if (_n > 0) - { - // Currently accelerating, need to decel now? Or maybe going the wrong way? - if ((stepsToStop >= distanceTo) || _direction == DIRECTION_CCW) - _n = -stepsToStop; // Start deceleration - } - else if (_n < 0) - { - // Currently decelerating, need to accel again? - if ((stepsToStop < distanceTo) && _direction == DIRECTION_CW) - _n = -_n; // Start accceleration - } - } - else if (distanceTo < 0) - { - // We are clockwise from the target - // Need to go anticlockwise from here, maybe decelerate - if (_n > 0) - { - // Currently accelerating, need to decel now? Or maybe going the wrong way? - if ((stepsToStop >= -distanceTo) || _direction == DIRECTION_CW) - _n = -stepsToStop; // Start deceleration - } - else if (_n < 0) - { - // Currently decelerating, need to accel again? - if ((stepsToStop < -distanceTo) && _direction == DIRECTION_CCW) - _n = -_n; // Start accceleration - } - } - - // Need to accelerate or decelerate - if (_n == 0) - { - // First step from stopped - _cn = _c0; - _direction = (distanceTo > 0) ? DIRECTION_CW : DIRECTION_CCW; - } - else - { - // Subsequent step. Works for accel (n is +_ve) and decel (n is -ve). - _cn = _cn - ((2.0 * _cn) / ((4.0 * _n) + 1)); // Equation 13 - _cn = max(_cn, _cmin); - } - _n++; - _stepInterval = _cn; - _speed = 1000000.0 / _cn; - if (_direction == DIRECTION_CCW) - _speed = -_speed; - -#if 0 - Serial.println(_speed); - Serial.println(_acceleration); - Serial.println(_cn); - Serial.println(_c0); - Serial.println(_n); - Serial.println(_stepInterval); - Serial.println(distanceTo); - Serial.println(stepsToStop); - Serial.println("-----"); -#endif -} - -// Run the motor to implement speed and acceleration in order to proceed to the target position -// You must call this at least once per step, preferably in your main loop -// If the motor is in the desired position, the cost is very small -// returns true if the motor is still running to the target position. -boolean AccelStepper::run() -{ - if (runSpeed()) - computeNewSpeed(); - return _speed != 0.0 || distanceToGo() != 0; -} - -AccelStepper::AccelStepper(uint8_t interface, uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4, bool enable) -{ - _interface = interface; - _currentPos = 0; - _targetPos = 0; - _speed = 0.0; - _maxSpeed = 1.0; - _acceleration = 0.0; - _sqrt_twoa = 1.0; - _stepInterval = 0; - _minPulseWidth = 1; - _enablePin = 0xff; - _lastStepTime = 0; - _pin[0] = pin1; - _pin[1] = pin2; - _pin[2] = pin3; - _pin[3] = pin4; - _enableInverted = false; - - // NEW - _n = 0; - _c0 = 0.0; - _cn = 0.0; - _cmin = 1.0; - _direction = DIRECTION_CCW; - - int i; - for (i = 0; i < 4; i++) - _pinInverted[i] = 0; - if (enable) - enableOutputs(); - // Some reasonable default - setAcceleration(1); -} - -AccelStepper::AccelStepper(void (*forward)(), void (*backward)()) -{ - _interface = 0; - _currentPos = 0; - _targetPos = 0; - _speed = 0.0; - _maxSpeed = 1.0; - _acceleration = 0.0; - _sqrt_twoa = 1.0; - _stepInterval = 0; - _minPulseWidth = 1; - _enablePin = 0xff; - _lastStepTime = 0; - _pin[0] = 0; - _pin[1] = 0; - _pin[2] = 0; - _pin[3] = 0; - _forward = forward; - _backward = backward; - - // NEW - _n = 0; - _c0 = 0.0; - _cn = 0.0; - _cmin = 1.0; - _direction = DIRECTION_CCW; - - int i; - for (i = 0; i < 4; i++) - _pinInverted[i] = 0; - // Some reasonable default - setAcceleration(1); -} - -void AccelStepper::setMaxSpeed(float speed) -{ - if (speed < 0.0) - speed = -speed; - if (_maxSpeed != speed) - { - _maxSpeed = speed; - _cmin = 1000000.0 / speed; - // Recompute _n from current speed and adjust speed if accelerating or cruising - if (_n > 0) - { - _n = (long)((_speed * _speed) / (2.0 * _acceleration)); // Equation 16 - computeNewSpeed(); - } - } -} - -float AccelStepper::maxSpeed() -{ - return _maxSpeed; -} - -void AccelStepper::setAcceleration(float acceleration) -{ - if (acceleration == 0.0) - return; - if (acceleration < 0.0) - acceleration = -acceleration; - if (_acceleration != acceleration) - { - // Recompute _n per Equation 17 - _n = _n * (_acceleration / acceleration); - // New c0 per Equation 7, with correction per Equation 15 - _c0 = 0.676 * sqrt(2.0 / acceleration) * 1000000.0; // Equation 15 - _acceleration = acceleration; - computeNewSpeed(); - } -} - -void AccelStepper::setSpeed(float speed) -{ - if (speed == _speed) - return; - speed = constrain(speed, -_maxSpeed, _maxSpeed); - if (speed == 0.0) - _stepInterval = 0; - else - { - _stepInterval = fabs(1000000.0 / speed); - _direction = (speed > 0.0) ? DIRECTION_CW : DIRECTION_CCW; - } - _speed = speed; -} - -float AccelStepper::speed() -{ - return _speed; -} - -// Subclasses can override -void AccelStepper::step(long step) -{ - switch (_interface) - { - case FUNCTION: - step0(step); - break; - - case DRIVER: - step1(step); - break; - - case FULL2WIRE: - step2(step); - break; - - case FULL3WIRE: - step3(step); - break; - - case FULL4WIRE: - step4(step); - break; - - case HALF3WIRE: - step6(step); - break; - - case HALF4WIRE: - step8(step); - break; - } -} - -// You might want to override this to implement eg serial output -// bit 0 of the mask corresponds to _pin[0] -// bit 1 of the mask corresponds to _pin[1] -// .... -void AccelStepper::setOutputPins(uint8_t mask) -{ - uint8_t numpins = 2; - if (_interface == FULL4WIRE || _interface == HALF4WIRE) - numpins = 4; - else if (_interface == FULL3WIRE || _interface == HALF3WIRE) - numpins = 3; - uint8_t i; - for (i = 0; i < numpins; i++) - digitalWrite(_pin[i], (mask & (1 << i)) ? (HIGH ^ _pinInverted[i]) : (LOW ^ _pinInverted[i])); -} - -// 0 pin step function (ie for functional usage) -void AccelStepper::step0(long step) -{ - (void)(step); // Unused - if (_speed > 0) - _forward(); - else - _backward(); -} - -// 1 pin step function (ie for stepper drivers) -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step1(long step) -{ - (void)(step); // Unused - - // _pin[0] is step, _pin[1] is direction - setOutputPins(_direction ? 0b10 : 0b00); // Set direction first else get rogue pulses - setOutputPins(_direction ? 0b11 : 0b01); // step HIGH - // Caution 200ns setup time - // Delay the minimum allowed pulse width - delayMicroseconds(_minPulseWidth); - setOutputPins(_direction ? 0b10 : 0b00); // step LOW -} - - -// 2 pin step function -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step2(long step) -{ - switch (step & 0x3) - { - case 0: /* 01 */ - setOutputPins(0b10); - break; - - case 1: /* 11 */ - setOutputPins(0b11); - break; - - case 2: /* 10 */ - setOutputPins(0b01); - break; - - case 3: /* 00 */ - setOutputPins(0b00); - break; - } -} -// 3 pin step function -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step3(long step) -{ - switch (step % 3) - { - case 0: // 100 - setOutputPins(0b100); - break; - - case 1: // 001 - setOutputPins(0b001); - break; - - case 2: //010 - setOutputPins(0b010); - break; - - } -} - -// 4 pin step function for half stepper -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step4(long step) -{ - switch (step & 0x3) - { - case 0: // 1010 - setOutputPins(0b0101); - break; - - case 1: // 0110 - setOutputPins(0b0110); - break; - - case 2: //0101 - setOutputPins(0b1010); - break; - - case 3: //1001 - setOutputPins(0b1001); - break; - } -} - -// 3 pin half step function -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step6(long step) -{ - switch (step % 6) - { - case 0: // 100 - setOutputPins(0b100); - break; - - case 1: // 101 - setOutputPins(0b101); - break; - - case 2: // 001 - setOutputPins(0b001); - break; - - case 3: // 011 - setOutputPins(0b011); - break; - - case 4: // 010 - setOutputPins(0b010); - break; - - case 5: // 011 - setOutputPins(0b110); - break; - - } -} - -// 4 pin half step function -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step8(long step) -{ - switch (step & 0x7) - { - case 0: // 1000 - setOutputPins(0b0001); - break; - - case 1: // 1010 - setOutputPins(0b0101); - break; - - case 2: // 0010 - setOutputPins(0b0100); - break; - - case 3: // 0110 - setOutputPins(0b0110); - break; - - case 4: // 0100 - setOutputPins(0b0010); - break; - - case 5: //0101 - setOutputPins(0b1010); - break; - - case 6: // 0001 - setOutputPins(0b1000); - break; - - case 7: //1001 - setOutputPins(0b1001); - break; - } -} - -// Prevents power consumption on the outputs -void AccelStepper::disableOutputs() -{ - if (! _interface) return; - - setOutputPins(0); // Handles inversion automatically - if (_enablePin != 0xff) - { - pinMode(_enablePin, OUTPUT); - digitalWrite(_enablePin, LOW ^ _enableInverted); - } -} - -void AccelStepper::enableOutputs() -{ - if (! _interface) - return; - - pinMode(_pin[0], OUTPUT); - pinMode(_pin[1], OUTPUT); - if (_interface == FULL4WIRE || _interface == HALF4WIRE) - { - pinMode(_pin[2], OUTPUT); - pinMode(_pin[3], OUTPUT); - } - else if (_interface == FULL3WIRE || _interface == HALF3WIRE) - { - pinMode(_pin[2], OUTPUT); - } - - if (_enablePin != 0xff) - { - pinMode(_enablePin, OUTPUT); - digitalWrite(_enablePin, HIGH ^ _enableInverted); - } -} - -void AccelStepper::setMinPulseWidth(unsigned int minWidth) -{ - _minPulseWidth = minWidth; -} - -void AccelStepper::setEnablePin(uint8_t enablePin) -{ - _enablePin = enablePin; - - // This happens after construction, so init pin now. - if (_enablePin != 0xff) - { - pinMode(_enablePin, OUTPUT); - digitalWrite(_enablePin, HIGH ^ _enableInverted); - } -} - -void AccelStepper::setPinsInverted(bool directionInvert, bool stepInvert, bool enableInvert) -{ - _pinInverted[0] = stepInvert; - _pinInverted[1] = directionInvert; - _enableInverted = enableInvert; -} - -void AccelStepper::setPinsInverted(bool pin1Invert, bool pin2Invert, bool pin3Invert, bool pin4Invert, bool enableInvert) -{ - _pinInverted[0] = pin1Invert; - _pinInverted[1] = pin2Invert; - _pinInverted[2] = pin3Invert; - _pinInverted[3] = pin4Invert; - _enableInverted = enableInvert; -} - -// Blocks until the target position is reached and stopped -void AccelStepper::runToPosition() -{ - while (run()) - ; -} - -boolean AccelStepper::runSpeedToPosition() -{ - if (_targetPos == _currentPos) - return false; - if (_targetPos >_currentPos) - _direction = DIRECTION_CW; - else - _direction = DIRECTION_CCW; - return runSpeed(); -} - -// Blocks until the new target position is reached -void AccelStepper::runToNewPosition(long position) -{ - moveTo(position); - runToPosition(); -} - -void AccelStepper::stop() -{ - if (_speed != 0.0) - { - long stepsToStop = (long)((_speed * _speed) / (2.0 * _acceleration)) + 1; // Equation 16 (+integer rounding) - if (_speed > 0) - move(stepsToStop); - else - move(-stepsToStop); - } -} - -bool AccelStepper::isRunning() -{ - return !(_speed == 0.0 && _targetPos == _currentPos); -} diff --git a/src/2018arm/AccelStepper.h b/src/2018arm/AccelStepper.h deleted file mode 100644 index 84c738c..0000000 --- a/src/2018arm/AccelStepper.h +++ /dev/null @@ -1,730 +0,0 @@ -// AccelStepper.h -// -/// \mainpage AccelStepper library for Arduino -/// -/// This is the Arduino AccelStepper library. -/// It provides an object-oriented interface for 2, 3 or 4 pin stepper motors and motor drivers. -/// -/// The standard Arduino IDE includes the Stepper library -/// (http://arduino.cc/en/Reference/Stepper) for stepper motors. It is -/// perfectly adequate for simple, single motor applications. -/// -/// AccelStepper significantly improves on the standard Arduino Stepper library in several ways: -/// \li Supports acceleration and deceleration -/// \li Supports multiple simultaneous steppers, with independent concurrent stepping on each stepper -/// \li API functions never delay() or block -/// \li Supports 2, 3 and 4 wire steppers, plus 3 and 4 wire half steppers. -/// \li Supports alternate stepping functions to enable support of AFMotor (https://github.com/adafruit/Adafruit-Motor-Shield-library) -/// \li Supports stepper drivers such as the Sparkfun EasyDriver (based on 3967 driver chip) -/// \li Very slow speeds are supported -/// \li Extensive API -/// \li Subclass support -/// -/// The latest version of this documentation can be downloaded from -/// http://www.airspayce.com/mikem/arduino/AccelStepper -/// The version of the package that this documentation refers to can be downloaded -/// from http://www.airspayce.com/mikem/arduino/AccelStepper/AccelStepper-1.58.zip -/// -/// Example Arduino programs are included to show the main modes of use. -/// -/// You can also find online help and discussion at http://groups.google.com/group/accelstepper -/// Please use that group for all questions and discussions on this topic. -/// Do not contact the author directly, unless it is to discuss commercial licensing. -/// Before asking a question or reporting a bug, please read -/// - http://en.wikipedia.org/wiki/Wikipedia:Reference_desk/How_to_ask_a_software_question -/// - http://www.catb.org/esr/faqs/smart-questions.html -/// - http://www.chiark.greenend.org.uk/~shgtatham/bugs.html -/// -/// Tested on Arduino Diecimila and Mega with arduino-0018 & arduino-0021 -/// on OpenSuSE 11.1 and avr-libc-1.6.1-1.15, -/// cross-avr-binutils-2.19-9.1, cross-avr-gcc-4.1.3_20080612-26.5. -/// Tested on Teensy http://www.pjrc.com/teensy including Teensy 3.1 built using Arduino IDE 1.0.5 with -/// teensyduino addon 1.18 and later. -/// -/// \par Installation -/// -/// Install in the usual way: unzip the distribution zip file to the libraries -/// sub-folder of your sketchbook. -/// -/// \par Theory -/// -/// This code uses speed calculations as described in -/// "Generate stepper-motor speed profiles in real time" by David Austin -/// http://fab.cba.mit.edu/classes/MIT/961.09/projects/i0/Stepper_Motor_Speed_Profile.pdf or -/// http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time or -/// http://web.archive.org/web/20140705143928/http://fab.cba.mit.edu/classes/MIT/961.09/projects/i0/Stepper_Motor_Speed_Profile.pdf -/// with the exception that AccelStepper uses steps per second rather than radians per second -/// (because we dont know the step angle of the motor) -/// An initial step interval is calculated for the first step, based on the desired acceleration -/// On subsequent steps, shorter step intervals are calculated based -/// on the previous step until max speed is achieved. -/// -/// \par Adafruit Motor Shield V2 -/// -/// The included examples AFMotor_* are for Adafruit Motor Shield V1 and do not work with Adafruit Motor Shield V2. -/// See https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library for examples that work with Adafruit Motor Shield V2. -/// -/// \par Donations -/// -/// This library is offered under a free GPL license for those who want to use it that way. -/// We try hard to keep it up to date, fix bugs -/// and to provide free support. If this library has helped you save time or money, please consider donating at -/// http://www.airspayce.com or here: -/// -/// \htmlonly
\endhtmlonly -/// -/// \par Trademarks -/// -/// AccelStepper is a trademark of AirSpayce Pty Ltd. The AccelStepper mark was first used on April 26 2010 for -/// international trade, and is used only in relation to motor control hardware and software. -/// It is not to be confused with any other similar marks covering other goods and services. -/// -/// \par Copyright -/// -/// This software is Copyright (C) 2010 Mike McCauley. Use is subject to license -/// conditions. The main licensing options available are GPL V2 or Commercial: -/// -/// \par Open Source Licensing GPL V2 -/// This is the appropriate option if you want to share the source code of your -/// application with everyone you distribute it to, and you also want to give them -/// the right to share who uses it. If you wish to use this software under Open -/// Source Licensing, you must contribute all your source code to the open source -/// community in accordance with the GPL Version 2 when your application is -/// distributed. See https://www.gnu.org/licenses/gpl-2.0.html -/// -/// \par Commercial Licensing -/// This is the appropriate option if you are creating proprietary applications -/// and you are not prepared to distribute and share the source code of your -/// application. Purchase commercial licenses at http://airspayce.binpress.com/ -/// -/// \par Revision History -/// \version 1.0 Initial release -/// -/// \version 1.1 Added speed() function to get the current speed. -/// \version 1.2 Added runSpeedToPosition() submitted by Gunnar Arndt. -/// \version 1.3 Added support for stepper drivers (ie with Step and Direction inputs) with _pins == 1 -/// \version 1.4 Added functional contructor to support AFMotor, contributed by Limor, with example sketches. -/// \version 1.5 Improvements contributed by Peter Mousley: Use of microsecond steps and other speed improvements -/// to increase max stepping speed to about 4kHz. New option for user to set the min allowed pulse width. -/// Added checks for already running at max speed and skip further calcs if so. -/// \version 1.6 Fixed a problem with wrapping of microsecond stepping that could cause stepping to hang. -/// Reported by Sandy Noble. -/// Removed redundant _lastRunTime member. -/// \version 1.7 Fixed a bug where setCurrentPosition() did not always work as expected. -/// Reported by Peter Linhart. -/// \version 1.8 Added support for 4 pin half-steppers, requested by Harvey Moon -/// \version 1.9 setCurrentPosition() now also sets motor speed to 0. -/// \version 1.10 Builds on Arduino 1.0 -/// \version 1.11 Improvments from Michael Ellison: -/// Added optional enable line support for stepper drivers -/// Added inversion for step/direction/enable lines for stepper drivers -/// \version 1.12 Announce Google Group -/// \version 1.13 Improvements to speed calculation. Cost of calculation is now less in the worst case, -/// and more or less constant in all cases. This should result in slightly beter high speed performance, and -/// reduce anomalous speed glitches when other steppers are accelerating. -/// However, its hard to see how to replace the sqrt() required at the very first step from 0 speed. -/// \version 1.14 Fixed a problem with compiling under arduino 0021 reported by EmbeddedMan -/// \version 1.15 Fixed a problem with runSpeedToPosition which did not correctly handle -/// running backwards to a smaller target position. Added examples -/// \version 1.16 Fixed some cases in the code where abs() was used instead of fabs(). -/// \version 1.17 Added example ProportionalControl -/// \version 1.18 Fixed a problem: If one calls the funcion runSpeed() when Speed is zero, it makes steps -/// without counting. reported by Friedrich, Klappenbach. -/// \version 1.19 Added MotorInterfaceType and symbolic names for the number of pins to use -/// for the motor interface. Updated examples to suit. -/// Replaced individual pin assignment variables _pin1, _pin2 etc with array _pin[4]. -/// _pins member changed to _interface. -/// Added _pinInverted array to simplify pin inversion operations. -/// Added new function setOutputPins() which sets the motor output pins. -/// It can be overridden in order to provide, say, serial output instead of parallel output -/// Some refactoring and code size reduction. -/// \version 1.20 Improved documentation and examples to show need for correctly -/// specifying AccelStepper::FULL4WIRE and friends. -/// \version 1.21 Fixed a problem where desiredSpeed could compute the wrong step acceleration -/// when _speed was small but non-zero. Reported by Brian Schmalz. -/// Precompute sqrt_twoa to improve performance and max possible stepping speed -/// \version 1.22 Added Bounce.pde example -/// Fixed a problem where calling moveTo(), setMaxSpeed(), setAcceleration() more -/// frequently than the step time, even -/// with the same values, would interfere with speed calcs. Now a new speed is computed -/// only if there was a change in the set value. Reported by Brian Schmalz. -/// \version 1.23 Rewrite of the speed algorithms in line with -/// http://fab.cba.mit.edu/classes/MIT/961.09/projects/i0/Stepper_Motor_Speed_Profile.pdf -/// Now expect smoother and more linear accelerations and decelerations. The desiredSpeed() -/// function was removed. -/// \version 1.24 Fixed a problem introduced in 1.23: with runToPosition, which did never returned -/// \version 1.25 Now ignore attempts to set acceleration to 0.0 -/// \version 1.26 Fixed a problem where certina combinations of speed and accelration could cause -/// oscillation about the target position. -/// \version 1.27 Added stop() function to stop as fast as possible with current acceleration parameters. -/// Also added new Quickstop example showing its use. -/// \version 1.28 Fixed another problem where certain combinations of speed and accelration could cause -/// oscillation about the target position. -/// Added support for 3 wire full and half steppers such as Hard Disk Drive spindle. -/// Contributed by Yuri Ivatchkovitch. -/// \version 1.29 Fixed a problem that could cause a DRIVER stepper to continually step -/// with some sketches. Reported by Vadim. -/// \version 1.30 Fixed a problem that could cause stepper to back up a few steps at the end of -/// accelerated travel with certain speeds. Reported and patched by jolo. -/// \version 1.31 Updated author and distribution location details to airspayce.com -/// \version 1.32 Fixed a problem with enableOutputs() and setEnablePin on Arduino Due that -/// prevented the enable pin changing stae correctly. Reported by Duane Bishop. -/// \version 1.33 Fixed an error in example AFMotor_ConstantSpeed.pde did not setMaxSpeed(); -/// Fixed a problem that caused incorrect pin sequencing of FULL3WIRE and HALF3WIRE. -/// Unfortunately this meant changing the signature for all step*() functions. -/// Added example MotorShield, showing how to use AdaFruit Motor Shield to control -/// a 3 phase motor such as a HDD spindle motor (and without using the AFMotor library. -/// \version 1.34 Added setPinsInverted(bool pin1Invert, bool pin2Invert, bool pin3Invert, bool pin4Invert, bool enableInvert) -/// to allow inversion of 2, 3 and 4 wire stepper pins. Requested by Oleg. -/// \version 1.35 Removed default args from setPinsInverted(bool, bool, bool, bool, bool) to prevent ambiguity with -/// setPinsInverted(bool, bool, bool). Reported by Mac Mac. -/// \version 1.36 Changed enableOutputs() and disableOutputs() to be virtual so can be overridden. -/// Added new optional argument 'enable' to constructor, which allows you toi disable the -/// automatic enabling of outputs at construction time. Suggested by Guido. -/// \version 1.37 Fixed a problem with step1 that could cause a rogue step in the -/// wrong direction (or not, -/// depending on the setup-time requirements of the connected hardware). -/// Reported by Mark Tillotson. -/// \version 1.38 run() function incorrectly always returned true. Updated function and doc so it returns true -/// if the motor is still running to the target position. -/// \version 1.39 Updated typos in keywords.txt, courtesey Jon Magill. -/// \version 1.40 Updated documentation, including testing on Teensy 3.1 -/// \version 1.41 Fixed an error in the acceleration calculations, resulting in acceleration of haldf the intended value -/// \version 1.42 Improved support for FULL3WIRE and HALF3WIRE output pins. These changes were in Yuri's original -/// contribution but did not make it into production.
-/// \version 1.43 Added DualMotorShield example. Shows how to use AccelStepper to control 2 x 2 phase steppers using the -/// Itead Studio Arduino Dual Stepper Motor Driver Shield model IM120417015.
-/// \version 1.44 examples/DualMotorShield/DualMotorShield.ino examples/DualMotorShield/DualMotorShield.pde -/// was missing from the distribution.
-/// \version 1.45 Fixed a problem where if setAcceleration was not called, there was no default -/// acceleration. Reported by Michael Newman.
-/// \version 1.45 Fixed inaccuracy in acceleration rate by using Equation 15, suggested by Sebastian Gracki.
-/// Performance improvements in runSpeed suggested by Jaakko Fagerlund.
-/// \version 1.46 Fixed error in documentation for runToPosition(). -/// Reinstated time calculations in runSpeed() since new version is reported -/// not to work correctly under some circumstances. Reported by Oleg V Gavva.
-/// \version 1.48 2015-08-25 -/// Added new class MultiStepper that can manage multiple AccelSteppers, -/// and cause them all to move -/// to selected positions at such a (constant) speed that they all arrive at their -/// target position at the same time. Suitable for X-Y flatbeds etc.
-/// Added new method maxSpeed() to AccelStepper to return the currently configured maxSpeed.
-/// \version 1.49 2016-01-02 -/// Testing with VID28 series instrument stepper motors and EasyDriver. -/// OK, although with light pointers -/// and slow speeds like 180 full steps per second the motor movement can be erratic, -/// probably due to some mechanical resonance. Best to accelerate through this speed.
-/// Added isRunning().
-/// \version 1.50 2016-02-25 -/// AccelStepper::disableOutputs now sets the enable pion to OUTPUT mode if the enable pin is defined. -/// Patch from Piet De Jong.
-/// Added notes about the fact that AFMotor_* examples do not work with Adafruit Motor Shield V2.
-/// \version 1.51 2016-03-24 -/// Fixed a problem reported by gregor: when resetting the stepper motor position using setCurrentPosition() the -/// stepper speed is reset by setting _stepInterval to 0, but _speed is not -/// reset. this results in the stepper motor not starting again when calling -/// setSpeed() with the same speed the stepper was set to before. -/// \version 1.52 2016-08-09 -/// Added MultiStepper to keywords.txt. -/// Improvements to efficiency of AccelStepper::runSpeed() as suggested by David Grayson. -/// Improvements to speed accuracy as suggested by David Grayson. -/// \version 1.53 2016-08-14 -/// Backed out Improvements to speed accuracy from 1.52 as it did not work correctly. -/// \version 1.54 2017-01-24 -/// Fixed some warnings about unused arguments. -/// \version 1.55 2017-01-25 -/// Fixed another warning in MultiStepper.cpp -/// \version 1.56 2017-02-03 -/// Fixed minor documentation error with DIRECTION_CCW and DIRECTION_CW. Reported by David Mutterer. -/// Added link to Binpress commercial license purchasing. -/// \version 1.57 2017-03-28 -/// _direction moved to protected at the request of Rudy Ercek. -/// setMaxSpeed() and setAcceleration() now correct negative values to be positive. -/// \version 1.58 2018-04-13 -/// Add initialisation for _enableInverted in constructor. -/// -/// \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS -// Copyright (C) 2009-2013 Mike McCauley -// $Id: AccelStepper.h,v 1.27 2016/08/14 10:26:54 mikem Exp mikem $ - -#ifndef AccelStepper_h -#define AccelStepper_h - -#include -#if ARDUINO >= 100 -#include -#else -#include -#include -#endif - -// These defs cause trouble on some versions of Arduino -#undef round - -///////////////////////////////////////////////////////////////////// -/// \class AccelStepper AccelStepper.h -/// \brief Support for stepper motors with acceleration etc. -/// -/// This defines a single 2 or 4 pin stepper motor, or stepper moter with fdriver chip, with optional -/// acceleration, deceleration, absolute positioning commands etc. Multiple -/// simultaneous steppers are supported, all moving -/// at different speeds and accelerations. -/// -/// \par Operation -/// This module operates by computing a step time in microseconds. The step -/// time is recomputed after each step and after speed and acceleration -/// parameters are changed by the caller. The time of each step is recorded in -/// microseconds. The run() function steps the motor once if a new step is due. -/// The run() function must be called frequently until the motor is in the -/// desired position, after which time run() will do nothing. -/// -/// \par Positioning -/// Positions are specified by a signed long integer. At -/// construction time, the current position of the motor is consider to be 0. Positive -/// positions are clockwise from the initial position; negative positions are -/// anticlockwise. The current position can be altered for instance after -/// initialization positioning. -/// -/// \par Caveats -/// This is an open loop controller: If the motor stalls or is oversped, -/// AccelStepper will not have a correct -/// idea of where the motor really is (since there is no feedback of the motor's -/// real position. We only know where we _think_ it is, relative to the -/// initial starting point). -/// -/// \par Performance -/// The fastest motor speed that can be reliably supported is about 4000 steps per -/// second at a clock frequency of 16 MHz on Arduino such as Uno etc. -/// Faster processors can support faster stepping speeds. -/// However, any speed less than that -/// down to very slow speeds (much less than one per second) are also supported, -/// provided the run() function is called frequently enough to step the motor -/// whenever required for the speed set. -/// Calling setAcceleration() is expensive, -/// since it requires a square root to be calculated. -/// -/// Gregor Christandl reports that with an Arduino Due and a simple test program, -/// he measured 43163 steps per second using runSpeed(), -/// and 16214 steps per second using run(); -class AccelStepper -{ -public: - /// \brief Symbolic names for number of pins. - /// Use this in the pins argument the AccelStepper constructor to - /// provide a symbolic name for the number of pins - /// to use. - typedef enum - { - FUNCTION = 0, ///< Use the functional interface, implementing your own driver functions (internal use only) - DRIVER = 1, ///< Stepper Driver, 2 driver pins required - FULL2WIRE = 2, ///< 2 wire stepper, 2 motor pins required - FULL3WIRE = 3, ///< 3 wire stepper, such as HDD spindle, 3 motor pins required - FULL4WIRE = 4, ///< 4 wire full stepper, 4 motor pins required - HALF3WIRE = 6, ///< 3 wire half stepper, such as HDD spindle, 3 motor pins required - HALF4WIRE = 8 ///< 4 wire half stepper, 4 motor pins required - } MotorInterfaceType; - - /// Constructor. You can have multiple simultaneous steppers, all moving - /// at different speeds and accelerations, provided you call their run() - /// functions at frequent enough intervals. Current Position is set to 0, target - /// position is set to 0. MaxSpeed and Acceleration default to 1.0. - /// The motor pins will be initialised to OUTPUT mode during the - /// constructor by a call to enableOutputs(). - /// \param[in] interface Number of pins to interface to. Integer values are - /// supported, but it is preferred to use the \ref MotorInterfaceType symbolic names. - /// AccelStepper::DRIVER (1) means a stepper driver (with Step and Direction pins). - /// If an enable line is also needed, call setEnablePin() after construction. - /// You may also invert the pins using setPinsInverted(). - /// AccelStepper::FULL2WIRE (2) means a 2 wire stepper (2 pins required). - /// AccelStepper::FULL3WIRE (3) means a 3 wire stepper, such as HDD spindle (3 pins required). - /// AccelStepper::FULL4WIRE (4) means a 4 wire stepper (4 pins required). - /// AccelStepper::HALF3WIRE (6) means a 3 wire half stepper, such as HDD spindle (3 pins required) - /// AccelStepper::HALF4WIRE (8) means a 4 wire half stepper (4 pins required) - /// Defaults to AccelStepper::FULL4WIRE (4) pins. - /// \param[in] pin1 Arduino digital pin number for motor pin 1. Defaults - /// to pin 2. For a AccelStepper::DRIVER (interface==1), - /// this is the Step input to the driver. Low to high transition means to step) - /// \param[in] pin2 Arduino digital pin number for motor pin 2. Defaults - /// to pin 3. For a AccelStepper::DRIVER (interface==1), - /// this is the Direction input the driver. High means forward. - /// \param[in] pin3 Arduino digital pin number for motor pin 3. Defaults - /// to pin 4. - /// \param[in] pin4 Arduino digital pin number for motor pin 4. Defaults - /// to pin 5. - /// \param[in] enable If this is true (the default), enableOutputs() will be called to enable - /// the output pins at construction time. - AccelStepper(uint8_t interface = AccelStepper::FULL4WIRE, uint8_t pin1 = 2, uint8_t pin2 = 3, uint8_t pin3 = 4, uint8_t pin4 = 5, bool enable = true); - - /// Alternate Constructor which will call your own functions for forward and backward steps. - /// You can have multiple simultaneous steppers, all moving - /// at different speeds and accelerations, provided you call their run() - /// functions at frequent enough intervals. Current Position is set to 0, target - /// position is set to 0. MaxSpeed and Acceleration default to 1.0. - /// Any motor initialization should happen before hand, no pins are used or initialized. - /// \param[in] forward void-returning procedure that will make a forward step - /// \param[in] backward void-returning procedure that will make a backward step - AccelStepper(void (*forward)(), void (*backward)()); - - /// Set the target position. The run() function will try to move the motor (at most one step per call) - /// from the current position to the target position set by the most - /// recent call to this function. Caution: moveTo() also recalculates the speed for the next step. - /// If you are trying to use constant speed movements, you should call setSpeed() after calling moveTo(). - /// \param[in] absolute The desired absolute position. Negative is - /// anticlockwise from the 0 position. - void moveTo(long absolute); - - /// Set the target position relative to the current position - /// \param[in] relative The desired position relative to the current position. Negative is - /// anticlockwise from the current position. - void move(long relative); - - /// Poll the motor and step it if a step is due, implementing - /// accelerations and decelerations to acheive the target position. You must call this as - /// frequently as possible, but at least once per minimum step time interval, - /// preferably in your main loop. Note that each call to run() will make at most one step, and then only when a step is due, - /// based on the current speed and the time since the last step. - /// \return true if the motor is still running to the target position. - boolean run(); - - /// Poll the motor and step it if a step is due, implementing a constant - /// speed as set by the most recent call to setSpeed(). You must call this as - /// frequently as possible, but at least once per step interval, - /// \return true if the motor was stepped. - boolean runSpeed(); - - /// Sets the maximum permitted speed. The run() function will accelerate - /// up to the speed set by this function. - /// Caution: the maximum speed achievable depends on your processor and clock speed. - /// \param[in] speed The desired maximum speed in steps per second. Must - /// be > 0. Caution: Speeds that exceed the maximum speed supported by the processor may - /// Result in non-linear accelerations and decelerations. - void setMaxSpeed(float speed); - - /// returns the maximum speed configured for this stepper - /// that was previously set by setMaxSpeed(); - /// \return The currently configured maximum speed - float maxSpeed(); - - /// Sets the acceleration/deceleration rate. - /// \param[in] acceleration The desired acceleration in steps per second - /// per second. Must be > 0.0. This is an expensive call since it requires a square - /// root to be calculated. Dont call more ofthen than needed - void setAcceleration(float acceleration); - - /// Sets the desired constant speed for use with runSpeed(). - /// \param[in] speed The desired constant speed in steps per - /// second. Positive is clockwise. Speeds of more than 1000 steps per - /// second are unreliable. Very slow speeds may be set (eg 0.00027777 for - /// once per hour, approximately. Speed accuracy depends on the Arduino - /// crystal. Jitter depends on how frequently you call the runSpeed() function. - void setSpeed(float speed); - - /// The most recently set speed - /// \return the most recent speed in steps per second - float speed(); - - /// The distance from the current position to the target position. - /// \return the distance from the current position to the target position - /// in steps. Positive is clockwise from the current position. - long distanceToGo(); - - /// The most recently set target position. - /// \return the target position - /// in steps. Positive is clockwise from the 0 position. - long targetPosition(); - - /// The currently motor position. - /// \return the current motor position - /// in steps. Positive is clockwise from the 0 position. - long currentPosition(); - - /// Resets the current position of the motor, so that wherever the motor - /// happens to be right now is considered to be the new 0 position. Useful - /// for setting a zero position on a stepper after an initial hardware - /// positioning move. - /// Has the side effect of setting the current motor speed to 0. - /// \param[in] position The position in steps of wherever the motor - /// happens to be right now. - void setCurrentPosition(long position); - - /// Moves the motor (with acceleration/deceleration) - /// to the target position and blocks until it is at - /// position. Dont use this in event loops, since it blocks. - void runToPosition(); - - /// Runs at the currently selected speed until the target position is reached - /// Does not implement accelerations. - /// \return true if it stepped - boolean runSpeedToPosition(); - - /// Moves the motor (with acceleration/deceleration) - /// to the new target position and blocks until it is at - /// position. Dont use this in event loops, since it blocks. - /// \param[in] position The new target position. - void runToNewPosition(long position); - - /// Sets a new target position that causes the stepper - /// to stop as quickly as possible, using the current speed and acceleration parameters. - void stop(); - - /// Disable motor pin outputs by setting them all LOW - /// Depending on the design of your electronics this may turn off - /// the power to the motor coils, saving power. - /// This is useful to support Arduino low power modes: disable the outputs - /// during sleep and then reenable with enableOutputs() before stepping - /// again. - /// If the enable Pin is defined, sets it to OUTPUT mode and clears the pin to disabled. - virtual void disableOutputs(); - - /// Enable motor pin outputs by setting the motor pins to OUTPUT - /// mode. Called automatically by the constructor. - /// If the enable Pin is defined, sets it to OUTPUT mode and sets the pin to enabled. - virtual void enableOutputs(); - - /// Sets the minimum pulse width allowed by the stepper driver. The minimum practical pulse width is - /// approximately 20 microseconds. Times less than 20 microseconds - /// will usually result in 20 microseconds or so. - /// \param[in] minWidth The minimum pulse width in microseconds. - void setMinPulseWidth(unsigned int minWidth); - - /// Sets the enable pin number for stepper drivers. - /// 0xFF indicates unused (default). - /// Otherwise, if a pin is set, the pin will be turned on when - /// enableOutputs() is called and switched off when disableOutputs() - /// is called. - /// \param[in] enablePin Arduino digital pin number for motor enable - /// \sa setPinsInverted - void setEnablePin(uint8_t enablePin = 0xff); - - /// Sets the inversion for stepper driver pins - /// \param[in] directionInvert True for inverted direction pin, false for non-inverted - /// \param[in] stepInvert True for inverted step pin, false for non-inverted - /// \param[in] enableInvert True for inverted enable pin, false (default) for non-inverted - void setPinsInverted(bool directionInvert = false, bool stepInvert = false, bool enableInvert = false); - - /// Sets the inversion for 2, 3 and 4 wire stepper pins - /// \param[in] pin1Invert True for inverted pin1, false for non-inverted - /// \param[in] pin2Invert True for inverted pin2, false for non-inverted - /// \param[in] pin3Invert True for inverted pin3, false for non-inverted - /// \param[in] pin4Invert True for inverted pin4, false for non-inverted - /// \param[in] enableInvert True for inverted enable pin, false (default) for non-inverted - void setPinsInverted(bool pin1Invert, bool pin2Invert, bool pin3Invert, bool pin4Invert, bool enableInvert); - - /// Checks to see if the motor is currently running to a target - /// \return true if the speed is not zero or not at the target position - bool isRunning(); - -protected: - - /// \brief Direction indicator - /// Symbolic names for the direction the motor is turning - typedef enum - { - DIRECTION_CCW = 0, ///< Counter-Clockwise - DIRECTION_CW = 1 ///< Clockwise - } Direction; - - /// Forces the library to compute a new instantaneous speed and set that as - /// the current speed. It is called by - /// the library: - /// \li after each step - /// \li after change to maxSpeed through setMaxSpeed() - /// \li after change to acceleration through setAcceleration() - /// \li after change to target position (relative or absolute) through - /// move() or moveTo() - void computeNewSpeed(); - - /// Low level function to set the motor output pins - /// bit 0 of the mask corresponds to _pin[0] - /// bit 1 of the mask corresponds to _pin[1] - /// You can override this to impment, for example serial chip output insted of using the - /// output pins directly - virtual void setOutputPins(uint8_t mask); - - /// Called to execute a step. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default calls step1(), step2(), step4() or step8() depending on the - /// number of pins defined for the stepper. - /// \param[in] step The current step phase number (0 to 7) - virtual void step(long step); - - /// Called to execute a step using stepper functions (pins = 0) Only called when a new step is - /// required. Calls _forward() or _backward() to perform the step - /// \param[in] step The current step phase number (0 to 7) - virtual void step0(long step); - - /// Called to execute a step on a stepper driver (ie where pins == 1). Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of Step pin1 to step, - /// and sets the output of _pin2 to the desired direction. The Step pin (_pin1) is pulsed for 1 microsecond - /// which is the minimum STEP pulse width for the 3967 driver. - /// \param[in] step The current step phase number (0 to 7) - virtual void step1(long step); - - /// Called to execute a step on a 2 pin motor. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of pin1 and pin2 - /// \param[in] step The current step phase number (0 to 7) - virtual void step2(long step); - - /// Called to execute a step on a 3 pin motor, such as HDD spindle. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of pin1, pin2, - /// pin3 - /// \param[in] step The current step phase number (0 to 7) - virtual void step3(long step); - - /// Called to execute a step on a 4 pin motor. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of pin1, pin2, - /// pin3, pin4. - /// \param[in] step The current step phase number (0 to 7) - virtual void step4(long step); - - /// Called to execute a step on a 3 pin motor, such as HDD spindle. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of pin1, pin2, - /// pin3 - /// \param[in] step The current step phase number (0 to 7) - virtual void step6(long step); - - /// Called to execute a step on a 4 pin half-steper motor. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of pin1, pin2, - /// pin3, pin4. - /// \param[in] step The current step phase number (0 to 7) - virtual void step8(long step); - - /// Current direction motor is spinning in - /// Protected because some peoples subclasses need it to be so - boolean _direction; // 1 == CW - -private: - /// Number of pins on the stepper motor. Permits 2 or 4. 2 pins is a - /// bipolar, and 4 pins is a unipolar. - uint8_t _interface; // 0, 1, 2, 4, 8, See MotorInterfaceType - - /// Arduino pin number assignments for the 2 or 4 pins required to interface to the - /// stepper motor or driver - uint8_t _pin[4]; - - /// Whether the _pins is inverted or not - uint8_t _pinInverted[4]; - - /// The current absolution position in steps. - long _currentPos; // Steps - - /// The target position in steps. The AccelStepper library will move the - /// motor from the _currentPos to the _targetPos, taking into account the - /// max speed, acceleration and deceleration - long _targetPos; // Steps - - /// The current motos speed in steps per second - /// Positive is clockwise - float _speed; // Steps per second - - /// The maximum permitted speed in steps per second. Must be > 0. - float _maxSpeed; - - /// The acceleration to use to accelerate or decelerate the motor in steps - /// per second per second. Must be > 0 - float _acceleration; - float _sqrt_twoa; // Precomputed sqrt(2*_acceleration) - - /// The current interval between steps in microseconds. - /// 0 means the motor is currently stopped with _speed == 0 - unsigned long _stepInterval; - - /// The last step time in microseconds - unsigned long _lastStepTime; - - /// The minimum allowed pulse width in microseconds - unsigned int _minPulseWidth; - - /// Is the direction pin inverted? - ///bool _dirInverted; /// Moved to _pinInverted[1] - - /// Is the step pin inverted? - ///bool _stepInverted; /// Moved to _pinInverted[0] - - /// Is the enable pin inverted? - bool _enableInverted; - - /// Enable pin for stepper driver, or 0xFF if unused. - uint8_t _enablePin; - - /// The pointer to a forward-step procedure - void (*_forward)(); - - /// The pointer to a backward-step procedure - void (*_backward)(); - - /// The step counter for speed calculations - long _n; - - /// Initial step size in microseconds - float _c0; - - /// Last step size in microseconds - float _cn; - - /// Min step size in microseconds based on maxSpeed - float _cmin; // at max speed - -}; - -/// @example Random.pde -/// Make a single stepper perform random changes in speed, position and acceleration - -/// @example Overshoot.pde -/// Check overshoot handling -/// which sets a new target position and then waits until the stepper has -/// achieved it. This is used for testing the handling of overshoots - -/// @example MultipleSteppers.pde -/// Shows how to multiple simultaneous steppers -/// Runs one stepper forwards and backwards, accelerating and decelerating -/// at the limits. Runs other steppers at the same time - -/// @example ConstantSpeed.pde -/// Shows how to run AccelStepper in the simplest, -/// fixed speed mode with no accelerations - -/// @example Blocking.pde -/// Shows how to use the blocking call runToNewPosition -/// Which sets a new target position and then waits until the stepper has -/// achieved it. - -/// @example AFMotor_MultiStepper.pde -/// Control both Stepper motors at the same time with different speeds -/// and accelerations. - -/// @example AFMotor_ConstantSpeed.pde -/// Shows how to run AccelStepper in the simplest, -/// fixed speed mode with no accelerations - -/// @example ProportionalControl.pde -/// Make a single stepper follow the analog value read from a pot or whatever -/// The stepper will move at a constant speed to each newly set posiiton, -/// depending on the value of the pot. - -/// @example Bounce.pde -/// Make a single stepper bounce from one limit to another, observing -/// accelrations at each end of travel - -/// @example Quickstop.pde -/// Check stop handling. -/// Calls stop() while the stepper is travelling at full speed, causing -/// the stepper to stop as quickly as possible, within the constraints of the -/// current acceleration. - -/// @example MotorShield.pde -/// Shows how to use AccelStepper to control a 3-phase motor, such as a HDD spindle motor -/// using the Adafruit Motor Shield http://www.ladyada.net/make/mshield/index.html. - -/// @example DualMotorShield.pde -/// Shows how to use AccelStepper to control 2 x 2 phase steppers using the -/// Itead Studio Arduino Dual Stepper Motor Driver Shield -/// model IM120417015 - -#endif diff --git a/src/2018arm/Makefile b/src/2018arm/Makefile deleted file mode 100644 index 22039ad..0000000 --- a/src/2018arm/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -ARDUINO=10805 -F_CPU=16000000L -MCU=atmega328p - -INCLUDES= \ - -I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino \ - -I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/variants/eightanaloginputs - -ARGS=-Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -DARDUINO_AVR_PRO -DARDUINO_ARCH_AVR - -CPPS=$(patsubst %.cpp,%.o,$(wildcard *.cpp)) - -all: lib.a - -lib.a: ${CPPS} - $(foreach obj, $(CPPS), avr-ar rcs $@ $(obj);) - -%.o: %.cpp - avr-g++ ${ARGS} ${INCLUDES} -DF_CPU=${F_CPU} -DARDUINO=${ARDUINO} -mmcu=${MCU} -c $< -o $@ - -clean: - rm *.o - rm *.d diff --git a/src/2018arm/Servo.cpp b/src/2018arm/Servo.cpp deleted file mode 100644 index 3037c59..0000000 --- a/src/2018arm/Servo.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - Servo.cpp - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2 - Copyright (c) 2009 Michael Margolis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if defined(ARDUINO_ARCH_AVR) - -#include -#include - -#include "Servo.h" - -#define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8) // converts microseconds to tick (assumes prescale of 8) // 12 Aug 2009 -#define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds - - -#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009 - -//#define NBR_TIMERS (MAX_SERVOS / SERVOS_PER_TIMER) - -static servo_t servos[MAX_SERVOS]; // static array of servo structures -static volatile int8_t Channel[_Nbr_16timers ]; // counter for the servo being pulsed for each timer (or -1 if refresh interval) - -uint8_t ServoCount = 0; // the total number of attached servos - - -// convenience macros -#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo -#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer -#define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel -#define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel - -#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo -#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo - -/************ static functions common to all instances ***********************/ - -long map(long x, long in_min, long in_max, long out_min, long out_max) -{ - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - -static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA) -{ - if( Channel[timer] < 0 ) - *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer - else{ - if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true ) - digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated - } - - Channel[timer]++; // increment to the next channel - if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) { - *OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks; - if(SERVO(timer,Channel[timer]).Pin.isActive == true) // check if activated - digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high - } - else { - // finished all channels so wait for the refresh period to expire before starting over - if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed - *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL); - else - *OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed - Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel - } -} - -#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform -// Interrupt handlers for Arduino -#if defined(_useTimer1) -SIGNAL (TIMER1_COMPA_vect) -{ - handle_interrupts(_timer1, &TCNT1, &OCR1A); -} -#endif - -#if defined(_useTimer3) -SIGNAL (TIMER3_COMPA_vect) -{ - handle_interrupts(_timer3, &TCNT3, &OCR3A); -} -#endif - -#if defined(_useTimer4) -SIGNAL (TIMER4_COMPA_vect) -{ - handle_interrupts(_timer4, &TCNT4, &OCR4A); -} -#endif - -#if defined(_useTimer5) -SIGNAL (TIMER5_COMPA_vect) -{ - handle_interrupts(_timer5, &TCNT5, &OCR5A); -} -#endif - -#elif defined WIRING -// Interrupt handlers for Wiring -#if defined(_useTimer1) -void Timer1Service() -{ - handle_interrupts(_timer1, &TCNT1, &OCR1A); -} -#endif -#if defined(_useTimer3) -void Timer3Service() -{ - handle_interrupts(_timer3, &TCNT3, &OCR3A); -} -#endif -#endif - - -static void initISR(timer16_Sequence_t timer) -{ -#if defined (_useTimer1) - if(timer == _timer1) { - TCCR1A = 0; // normal counting mode - TCCR1B = _BV(CS11); // set prescaler of 8 - TCNT1 = 0; // clear the timer count -#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__) - TIFR |= _BV(OCF1A); // clear any pending interrupts; - TIMSK |= _BV(OCIE1A) ; // enable the output compare interrupt -#else - // here if not ATmega8 or ATmega128 - TIFR1 |= _BV(OCF1A); // clear any pending interrupts; - TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt -#endif -#if defined(WIRING) - timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service); -#endif - } -#endif - -#if defined (_useTimer3) - if(timer == _timer3) { - TCCR3A = 0; // normal counting mode - TCCR3B = _BV(CS31); // set prescaler of 8 - TCNT3 = 0; // clear the timer count -#if defined(__AVR_ATmega128__) - TIFR |= _BV(OCF3A); // clear any pending interrupts; - ETIMSK |= _BV(OCIE3A); // enable the output compare interrupt -#else - TIFR3 = _BV(OCF3A); // clear any pending interrupts; - TIMSK3 = _BV(OCIE3A) ; // enable the output compare interrupt -#endif -#if defined(WIRING) - timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only -#endif - } -#endif - -#if defined (_useTimer4) - if(timer == _timer4) { - TCCR4A = 0; // normal counting mode - TCCR4B = _BV(CS41); // set prescaler of 8 - TCNT4 = 0; // clear the timer count - TIFR4 = _BV(OCF4A); // clear any pending interrupts; - TIMSK4 = _BV(OCIE4A) ; // enable the output compare interrupt - } -#endif - -#if defined (_useTimer5) - if(timer == _timer5) { - TCCR5A = 0; // normal counting mode - TCCR5B = _BV(CS51); // set prescaler of 8 - TCNT5 = 0; // clear the timer count - TIFR5 = _BV(OCF5A); // clear any pending interrupts; - TIMSK5 = _BV(OCIE5A) ; // enable the output compare interrupt - } -#endif -} - -static void finISR(timer16_Sequence_t timer) -{ - //disable use of the given timer -#if defined WIRING // Wiring - if(timer == _timer1) { - #if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__) - TIMSK1 &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt - #else - TIMSK &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt - #endif - timerDetach(TIMER1OUTCOMPAREA_INT); - } - else if(timer == _timer3) { - #if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__) - TIMSK3 &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt - #else - ETIMSK &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt - #endif - timerDetach(TIMER3OUTCOMPAREA_INT); - } -#else - //For arduino - in future: call here to a currently undefined function to reset the timer - (void) timer; // squash "unused parameter 'timer' [-Wunused-parameter]" warning -#endif -} - -static boolean isTimerActive(timer16_Sequence_t timer) -{ - // returns true if any servo is active on this timer - for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) { - if(SERVO(timer,channel).Pin.isActive == true) - return true; - } - return false; -} - - -/****************** end of static functions ******************************/ - -Servo::Servo() -{ - if( ServoCount < MAX_SERVOS) { - this->servoIndex = ServoCount++; // assign a servo index to this instance - servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009 - } - else - this->servoIndex = INVALID_SERVO ; // too many servos -} - -uint8_t Servo::attach(int pin) -{ - return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH); -} - -uint8_t Servo::attach(int pin, int min, int max) -{ - if(this->servoIndex < MAX_SERVOS ) { - pinMode( pin, OUTPUT) ; // set servo pin to output - servos[this->servoIndex].Pin.nbr = pin; - // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128 - this->min = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS - this->max = (MAX_PULSE_WIDTH - max)/4; - // initialize the timer if it has not already been initialized - timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex); - if(isTimerActive(timer) == false) - initISR(timer); - servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive - } - return this->servoIndex ; -} - -void Servo::detach() -{ - servos[this->servoIndex].Pin.isActive = false; - timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex); - if(isTimerActive(timer) == false) { - finISR(timer); - } -} - -void Servo::write(int value) -{ - if(value < MIN_PULSE_WIDTH) - { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds) - if(value < 0) value = 0; - if(value > 180) value = 180; - value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX()); - } - this->writeMicroseconds(value); -} - -void Servo::writeMicroseconds(int value) -{ - // calculate and store the values for the given channel - byte channel = this->servoIndex; - if( (channel < MAX_SERVOS) ) // ensure channel is valid - { - if( value < SERVO_MIN() ) // ensure pulse width is valid - value = SERVO_MIN(); - else if( value > SERVO_MAX() ) - value = SERVO_MAX(); - - value = value - TRIM_DURATION; - value = usToTicks(value); // convert to ticks after compensating for interrupt overhead - 12 Aug 2009 - - uint8_t oldSREG = SREG; - cli(); - servos[channel].ticks = value; - SREG = oldSREG; - } -} - -int Servo::read() // return the value as degrees -{ - return map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180); -} - -int Servo::readMicroseconds() -{ - unsigned int pulsewidth; - if( this->servoIndex != INVALID_SERVO ) - pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION ; // 12 aug 2009 - else - pulsewidth = 0; - - return pulsewidth; -} - -bool Servo::attached() -{ - return servos[this->servoIndex].Pin.isActive ; -} - -#endif // ARDUINO_ARCH_AVR - diff --git a/src/2018arm/Servo.h b/src/2018arm/Servo.h deleted file mode 100644 index da73484..0000000 --- a/src/2018arm/Servo.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2 - Copyright (c) 2009 Michael Margolis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* - A servo is activated by creating an instance of the Servo class passing - the desired pin to the attach() method. - The servos are pulsed in the background using the value most recently - written using the write() method. - - Note that analogWrite of PWM on pins associated with the timer are - disabled when the first servo is attached. - Timers are seized as needed in groups of 12 servos - 24 servos use two - timers, 48 servos will use four. - The sequence used to sieze timers is defined in timers.h - - The methods are: - - Servo - Class for manipulating servo motors connected to Arduino pins. - - attach(pin ) - Attaches a servo motor to an i/o pin. - attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds - default min is 544, max is 2400 - - write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds) - writeMicroseconds() - Sets the servo pulse width in microseconds - read() - Gets the last written servo pulse width as an angle between 0 and 180. - readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release) - attached() - Returns true if there is a servo attached. - detach() - Stops an attached servos from pulsing its i/o pin. - */ - -#ifndef Servo_h -#define Servo_h - -#include - -/* - * Defines for 16 bit timers used with Servo library - * - * If _useTimerX is defined then TimerX is a 16 bit timer on the current board - * timer16_Sequence_t enumerates the sequence that the timers should be allocated - * _Nbr_16timers indicates how many 16 bit timers are available. - */ - -// Architecture specific include -#if defined(ARDUINO_ARCH_AVR) -#include "ServoTimers.h" -#elif defined(ARDUINO_ARCH_SAM) -#include "sam/ServoTimers.h" -#elif defined(ARDUINO_ARCH_SAMD) -#include "samd/ServoTimers.h" -#elif defined(ARDUINO_ARCH_STM32F4) -#include "stm32f4/ServoTimers.h" -#elif defined(ARDUINO_ARCH_NRF52) -#include "nrf52/ServoTimers.h" -#else -#error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor." -#endif - -#define Servo_VERSION 2 // software version of this library - -#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo -#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo -#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached -#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds - -#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer -#define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER) - -#define INVALID_SERVO 255 // flag indicating an invalid servo index - -#if !defined(ARDUINO_ARCH_STM32F4) - -typedef struct { - uint8_t nbr :6 ; // a pin number from 0 to 63 - uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false -} ServoPin_t ; - -typedef struct { - ServoPin_t Pin; - volatile unsigned int ticks; -} servo_t; - -class Servo -{ -public: - Servo(); - uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure - uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes. - void detach(); - void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds - void writeMicroseconds(int value); // Write pulse width in microseconds - int read(); // returns current pulse width as an angle between 0 and 180 degrees - int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release) - bool attached(); // return true if this servo is attached, otherwise false -private: - uint8_t servoIndex; // index into the channel data for this servo - int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH - int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH -}; - -#endif -#endif diff --git a/src/2018arm/ServoTimers.h b/src/2018arm/ServoTimers.h deleted file mode 100644 index 9794c8e..0000000 --- a/src/2018arm/ServoTimers.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2 - Copyright (c) 2009 Michael Margolis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* - * Defines for 16 bit timers used with Servo library - * - * If _useTimerX is defined then TimerX is a 16 bit timer on the current board - * timer16_Sequence_t enumerates the sequence that the timers should be allocated - * _Nbr_16timers indicates how many 16 bit timers are available. - */ - -/** - * AVR Only definitions - * -------------------- - */ - -// Say which 16 bit timers can be used and in what order -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -#define _useTimer5 -#define _useTimer1 -#define _useTimer3 -#define _useTimer4 -typedef enum { _timer5, _timer1, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t; - -#elif defined(__AVR_ATmega32U4__) -#define _useTimer1 -typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t; - -#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) -#define _useTimer3 -#define _useTimer1 -typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t; - -#elif defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2561__) -#define _useTimer3 -#define _useTimer1 -typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t; - -#else // everything else -#define _useTimer1 -typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t; -#endif - diff --git a/src/2018arm/nodeh_ext.h b/src/2018arm/nodeh_ext.h deleted file mode 100644 index d81e9a8..0000000 --- a/src/2018arm/nodeh_ext.h +++ /dev/null @@ -1,67 +0,0 @@ - -#include "../Header.h" - -class ServoGoto: public Node { -private: - Node *pos; - static Function *fservo_goto; -public: - ServoGoto(Node *position): pos(position) {} - - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - // value for the two parameters - vector args; - args.push_back(pos->generate(func, block, allocblock)); - - // get the function signature - if (!fservo_goto) { - - vector arg_types; - arg_types.push_back(Type::getInt16Ty(global_context)); - FunctionType *ftype = FunctionType::get(Type::getVoidTy(global_context), ArrayRef(arg_types), false); - fservo_goto = Function::Create(ftype, Function::ExternalLinkage, "servo_goto", mainmodule); - fservo_goto->setCallingConv(CallingConv::C); - } - - // generate code to call servo_goto function - ArrayRef argsRef(args); - return CallInst::Create(fservo_goto, argsRef, "", block); - } -}; - -class StepperGoto: public Node { -private: - int stp; - Node *pos; - static Function *fstepper_goto; -public: - StepperGoto(int stepper, Node *position): stp(stepper), pos(position) {} - - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - // value for the two parameters - Int16 nstp(stp); - - vector args; - args.push_back(nstp.generate(func, block, allocblock)); - args.push_back(pos->generate(func, block, allocblock)); - - // get the function signature - if (!fstepper_goto) { - - vector arg_types; - arg_types.push_back(Type::getInt16Ty(global_context)); - arg_types.push_back(Type::getInt16Ty(global_context)); - FunctionType *ftype = FunctionType::get(Type::getVoidTy(global_context), ArrayRef(arg_types), false); - fstepper_goto = Function::Create(ftype, Function::ExternalLinkage, "stepper_goto", mainmodule); - fstepper_goto->setCallingConv(CallingConv::C); - } - - // generate code to call stepper_goto function - ArrayRef argsRef(args); - return CallInst::Create(fstepper_goto, argsRef, "", block); - } -}; - -Function *StepperGoto::fstepper_goto = NULL; -Function *ServoGoto::fservo_goto = NULL; - diff --git a/src/2018arm/stepper_aux.cpp b/src/2018arm/stepper_aux.cpp deleted file mode 100644 index e35f011..0000000 --- a/src/2018arm/stepper_aux.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "stepper_aux.h" - -bool stepper_configured = false; -AccelStepper stepper_base(AccelStepper::HALF4WIRE, 2, 4, 3, 5); -AccelStepper stepper_updown(AccelStepper::HALF4WIRE, 6, 8, 7, 9); -AccelStepper stepper_forward(AccelStepper::HALF4WIRE, 10, 12, 11, 13); - -#define SERVO_PORT A5 -Servo servo_gripper; - -void stepper_goto(int stepper, int pos) { - if (!stepper_configured) { - // Change these to suit your stepper if you want - int maxSpeed = 4000; - int speed = 10; -// float acceleration = 100000; - float acceleration = 1000; - stepper_base.setMaxSpeed(maxSpeed); - stepper_updown.setMaxSpeed(maxSpeed); - stepper_forward.setMaxSpeed(maxSpeed); - stepper_base.setAcceleration(acceleration); - stepper_updown.setAcceleration(acceleration); - stepper_forward.setAcceleration(acceleration); - stepper_configured = true; - } - - AccelStepper *s; - if (stepper == 0) - s = &stepper_base; - else if (stepper == 1) - s = &stepper_updown; - else - s = &stepper_forward; - s->enableOutputs(); - s->runToNewPosition(pos); - s->disableOutputs(); -} - -void servo_goto(int pos) { - #define MIN_POS 82 - if (!servo_gripper.attached()) - servo_gripper.attach(SERVO_PORT); - if (pos >= 0 && pos <= 38) { - servo_gripper.write(pos + MIN_POS); - delay(15); // small delay - } -} - -void print(char t, char *p) { -} - diff --git a/src/2018arm/stepper_aux.h b/src/2018arm/stepper_aux.h deleted file mode 100644 index ea78da4..0000000 --- a/src/2018arm/stepper_aux.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef STEPPER_AUXH -#define STEPPER_AUXH - -#include "AccelStepper.h" -#include "Servo.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void stepper_goto(int stepper, int pos); -void servo_goto(int pos); -void print(char t, char *p); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/Array.cpp b/src/Array.cpp index ce21b53..9aa62cb 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -1,33 +1,89 @@ -#include "Header.h" +#include "Array.h" +#include "ArrayElements.h" +#include "BackLLVM.h" +#include "FunctionImpl.h" +#include "NamedConst.h" +#include "BinaryOp.h" +#include "semantic/PropagateTypes.h" +#include "semantic/Visitor.h" -Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - //Create an Array of Type Int8, and Size = size. - size = elements->getArraySize(); - Value *array_size = ConstantInt::get(Type::getInt8Ty(global_context), size); +Array::Array(const string& n, ArrayElements *aes, location_t loc) : Variable(n, loc), arrayElements(aes) { + NamedConst *nc = new NamedConst("size", getNodeForUIntConst(aes->getArraySize(), loc)); + addChild(nc); + addSymbol(nc); +} + +Array::Array(const string& n, location_t loc) : Variable(n, loc) { + arrayElements = new ArrayElements(getLoc()); +} + +DataType Array::getDataType() { + if (arrayType == NULL) + createDataType(); + return dt; +} + +void Array::createDataType() { + if (arrayType != NULL) + return; + + //Create a constant with the array size + size = arrayElements->getArraySize(); //Get Type of elements in Array of Elements, and define as I. - Type* I = elements->getArrayType(block, allocblock); + element_dt = arrayElements->getArrayType(); + dt = buildTypes->getArrayType(buildTypes->name(element_dt), + this->getLoc(), 1, true); + + Type* I = buildTypes->llvmType(element_dt); + if (buildTypes->isComplex(element_dt)) { + // in rob, all arrays of user types (complex types) + // are array of references + I = PointerType::getUnqual(I); + } //Declare array type. - ArrayType* arrayType = ArrayType::get(I, size); + arrayType = ArrayType::get(I, size); +} + +Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + createDataType(); //Generate array elements - unsigned int struct_size = elements->getStructSize(); unsigned int index = 0; bool allConst = true; vector elementValues; - elementValues.reserve(elements->getArraySize()); + map ctorsValues; + + int currentElement = 0; + elementValues.reserve(arrayElements->getArraySize()); + unsigned int struct_size = arrayElements->getStructSize(); for (int i=0; igetElementCount(i); - for (int j=0; jgetStructElement(i); - Value *val = elValue->generate(func, block, allocblock); - if (!val) + Node* elValue = arrayElements->getStructElement(i); + Value *val; + Constructor *ctor; + if ((ctor = dynamic_cast(elValue))) { + // constructors are called latter, for each array element + val = nullptr; + allConst = false; + } else { + ctor = nullptr; + val = elValue->generate(func, block, allocblock); + if (!val) { + yyerrorcpp(string_format("Can not generate the value for element at pos %d", i).c_str(), elValue, true); return NULL; - val = Coercion::Convert(val, I, block, elValue); + } if (!dyn_cast(val)) allConst = false; + } + + unsigned elCount = arrayElements->getElementCount(i); + for (int j=0; j < elCount; j++) { elementValues.push_back(val); + if (!val) // is ctor + ctorsValues[currentElement] = ctor; + currentElement++; } } @@ -37,8 +93,10 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock return NULL; } + auto sp = RobDbgInfo.currScope(); + auto funit = RobDbgInfo.currFile(); + //Allocate array. - Value* var; if (allocblock == global_alloc) { // when alloc is global vector constantValues; constantValues.reserve(elementValues.size()); @@ -46,23 +104,114 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock constantValues.push_back(dyn_cast(a)); ArrayRef constantRefs(constantValues); GlobalVariable *gv = new GlobalVariable(*mainmodule, arrayType, - false, GlobalValue::ExternalLinkage, ConstantArray::get(arrayType, constantRefs), name); - var = gv; + false, GlobalValue::InternalLinkage, + ConstantArray::get(arrayType, constantRefs), name); + alloc = gv; + + if (debug_info) { + auto di_ptr = DBuilder->createPointerType(buildTypes->diType(element_dt), + buildTypes->bitWidth(currentTarget().pointerType)); + auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", + funit, this->getLineNo(), di_ptr, false); + gv->addDebugInfo(d); + } + } else { - var = new AllocaInst(arrayType, 0, name, allocblock); + Builder->SetInsertPoint(allocblock); + + if (getGEPIndex() != -1) + alloc = getLLVMValue(func); + else { + alloc = Builder->CreateAlloca(arrayType, dataAddrSpace, 0, name); + if (debug_info) { + RobDbgInfo.emitLocation(this); + RobDbgInfo.declareVar(this, alloc, allocblock); + } + } Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); - StoreInst *store = NULL; + + // create an array and initialize the Copy/Constructors instances + // e.g. a = {element(), element():2, copy(x1), copy(y)} + if (ctorsValues.size() > 0) { + Type* ctorTy = buildTypes->llvmType(element_dt); + ArrayType *ctorArrayType = ArrayType::get(ctorTy, ctorsValues.size()); + Builder->SetInsertPoint(allocblock); + Value *ctorArray = Builder->CreateAlloca(ctorArrayType, dataAddrSpace, 0, "inlineArrayElems"); + + Builder->SetInsertPoint(block); + int idxCtor = 0; + for(auto &[key, ctor] : ctorsValues) { + Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), idxCtor); + Value* indexList[2] = {zero, idx}; + RobDbgInfo.emitLocation(ctor); + Value* gep = Builder->CreateGEP(ctorArrayType, ctorArray, indexList, "ctorElem"); + ctor->setLeftGEP(gep); + ctor->generate(func, block, allocblock); + elementValues[key] = gep; + idxCtor++; + } + } + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + // set array elements for(unsigned index = 0; index < elementValues.size(); index++) { Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), index); Value* indexList[2] = {zero, idx}; - GetElementPtrInst* gep = GetElementPtrInst::Create(arrayType, var, - ArrayRef(indexList), "", block); - store = new StoreInst(elementValues[index], gep, false, block); + Value* gep = Builder->CreateGEP(arrayType, alloc, indexList, "elem"); + Builder->CreateStore(elementValues[index], gep, false); } } - //Add array to table of symbols. - tabelasym[allocblock][name] = new RobSymbol(var); - return var; + return alloc; +} + +Node* Array::accept(Visitor& v) { + return v.visit(*this); +} + +Type* Array::getLLVMType() { + createDataType(); + return arrayType; +} + +Node *Array::getElementIndex(Node *p1, Node *p2, const string& name, int p1size, int p2size, + Node *columnNumber) { + + // if constant, validate indexes + if (p1->isConstExpr() && p1size != -1) { + Value *p1v = p1->generate(NULL, NULL, NULL); + Constant *c = dyn_cast(p1v); + int64_t v = c->getUniqueInteger().getZExtValue(); + if (v >= p1size) { + yyerrorcpp(string_format("Index (%d) for %s is out of bounds.", + v, name.c_str()), p1); + } + } + + if (p2 && p2->isConstExpr() && p2size != -1) { + Value *p1v = p2->generate(NULL, NULL, NULL); + Constant *c = dyn_cast(p1v); + int64_t v = c->getUniqueInteger().getZExtValue(); + if (v >= p2size) { + yyerrorcpp(string_format("Index (%d) for %s is out of bounds.", + v, name.c_str()), p2); + } + } + + if (!p2) // is an array + return p1; + + // Generate index of element for matrix + Node *i16p1; + if (buildTypes->isSignedDataType(p1->getDataType())) + i16p1 = new SExtInt(p1, tint16); + else + i16p1 = new ZExtInt(p1, tint16u); + BinaryOp *op = new BinaryOp(new BinaryOp(i16p1, '*', columnNumber), '+', p2); + PropagateTypes pt; + pt.visit(*op); + return op; } diff --git a/src/Array.h b/src/Array.h index 1ad92dd..9a90aa0 100644 --- a/src/Array.h +++ b/src/Array.h @@ -1,12 +1,75 @@ #pragma once -class Array: public Node { -private: - string name; +#include "Node.h" +#include "Variable.h" +#include "ArrayElements.h" + +class ArrayElements; + +class ParamArray: public Variable { +protected: + DataType element_dt = BuildTypes::undefinedType; + string element_dt_name; +public: + ParamArray(const string& n, string element_dt_name, location_t loc): Variable(n, loc) { + this->element_dt_name = element_dt_name; + } + + ParamArray(const string &n, DataType dt, location_t loc): Variable(n, loc) { + this->dt = dt; + this->element_dt = buildTypes->getArrayElementType(dt); + } + + virtual int getDimensions() { + return 1; + } + + DataType getDataType() override { + if (dt == BuildTypes::undefinedType) { + element_dt = buildTypes->getType(element_dt_name, true); + dt = buildTypes->getArrayType(element_dt_name, getLoc(), getDimensions(), true); + } + return dt; + } +}; + +class Array: public Variable { +protected: unsigned int size; - ArrayElements *elements; + DataType element_dt = BuildTypes::undefinedType; + ArrayType *arrayType = NULL; + ArrayElements *arrayElements; + virtual void createDataType(); + public: - Array(const char *n, ArrayElements *aes) : name(n), elements(aes) { } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + Array(const string& n, ArrayElements *aes, location_t loc); + Array(const string& n, location_t loc); + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + static Node *getElementIndex(Node *p1, Node *p2, const string& name, + int p1size = -1, int p2size = -1, Node *columnNumber = NULL); + + virtual std::vector& getElements() { + return arrayElements->getElements(); + } + + virtual Node* accept(Visitor& v) override; + + virtual Type *getLLVMType() override; + + virtual DataType getDataType() override; + + virtual DataType getElementDataType() { + return element_dt; + } + + virtual int getSize() const { + return size; + } + + const ArrayType* getArrayType() { + return arrayType; + } }; diff --git a/src/ArrayElements.cpp b/src/ArrayElements.cpp index 7f3e469..fb0a4d7 100644 --- a/src/ArrayElements.cpp +++ b/src/ArrayElements.cpp @@ -1,62 +1,96 @@ -#include "Header.h" -ArrayElements::ArrayElements() {}; +#include "ArrayElements.h" +#include "ConstructorCall.h" +#include "MemCopy.h" -void ArrayElements::append(ArrayElement& e) { +ArrayElements::ArrayElements(location_t loc): location(loc) {}; + +void ArrayElements::append(ArrayElement *e) { elements.push_back(e); }; - -unsigned ArrayElements::getArraySize() const { + +unsigned ArrayElements::getArraySize() { unsigned r = 0; for(auto& i : elements) - r += i.count; + r += i->count; return r; }; -unsigned ArrayElements::getStructSize() const { +unsigned ArrayElements::getStructSize() { return elements.size(); } -Type *ArrayElements::getArrayType(BasicBlock *block, BasicBlock *allocblock) const { - unsigned intsize = 0; - unsigned floatsize = 0; - for(auto& i : elements) { - Type *ty = i.value->getLLVMResultType(block, allocblock); - if (ty->isIntegerTy() && intsize < ty->getIntegerBitWidth()) - intsize = ty->getIntegerBitWidth(); - - if (floatsize < 32 && ty->isFloatTy()) - floatsize = 32; - else if (floatsize < 64 && ty->isDoubleTy()) - floatsize = 64; - else if (floatsize < 128 && ty->isFP128Ty()) - floatsize = 128; +DataType ArrayElements::getArrayConstType(const set& types, SourceLocation *location) { + + // detect use of two or more usertype + if (types.size() >= 2) { + int userTypesCount = 0; + for(auto &dt : types) { + if (buildTypes->isComplex(dt)) + userTypesCount++; + } + if (userTypesCount > 1) { + yyerrorcpp(string_format("There are %d heterogeneous element types. Can not convert between them.", userTypesCount), location); + return tvoid; + } } - if (intsize == 0 && floatsize == 0) { - yyerrorcpp("FIXME: vector of non-consts.", NULL); - return NULL; + + if (types.size() == 1) { + // only one type + return *types.begin(); + } else if (types.size() == 2) { + // convert tchar and tint8 to tchar + if (types.find(tchar) != types.end() && + types.find(tint8) != types.end()) + return tchar; } - if (floatsize == 0) { - switch (intsize) { - case 1: return Type::getInt1Ty(global_context); - case 8: return Type::getInt8Ty(global_context); - case 16: return Type::getInt16Ty(global_context); - case 32: return Type::getInt32Ty(global_context); - default: return Type::getInt64Ty(global_context); + + // int or float types: detect the largest + DataType intdt, floatdt; + unsigned largest_int = 0; + unsigned largest_float = 0; + for(auto dt : types) { + unsigned bitw = buildTypes->bitWidth(dt); + if (buildTypes->isIntegerDataType(dt) && largest_int < bitw) { + largest_int = bitw; + intdt = dt; } - } else { - switch (floatsize) { - case 32: return Type::getFloatTy(global_context); - case 64: return Type::getDoubleTy(global_context); - default: return Type::getFP128Ty(global_context); + if (buildTypes->isFloatDataType(dt) && largest_float < bitw) { + largest_float = bitw; + floatdt = dt; } } + + if (largest_float > 0) + return floatdt; // convert all to largest float + else if (largest_int > 0) + return intdt; // convert all to largest int + + yyerrorcpp("Can't identify the array type based on its values.", location); + return BuildTypes::undefinedType; +} + +DataType ArrayElements::getArrayType() { + // find distinct types + set types; + for(auto& i : elements) { + DataType edt = i->value->getDataType(); + if (buildTypes->isEnum(edt)) + edt = tint8; + + if (buildTypes->isArrayOrMatrix(edt)) + yyerrorcpp("Can not make array of arrays yet.", i->value); + else + types.emplace(edt); + } + + return getArrayConstType(types, &location); } -Node *ArrayElements::getStructElement(int position) const { - return elements[position].value; +Node *ArrayElements::getStructElement(int position) { + return elements[position]->value; } -unsigned ArrayElements::getElementCount(int position) const { - return elements[position].count; +unsigned ArrayElements::getElementCount(int position) { + return elements[position]->count; } diff --git a/src/ArrayElements.h b/src/ArrayElements.h index c11f4b2..8cb3f73 100644 --- a/src/ArrayElements.h +++ b/src/ArrayElements.h @@ -1,21 +1,36 @@ -#ifndef __ARRAY_ELEMENT_H__ -#define __ARRAY_ELEMENT_H__ + +#pragma once #include "Node.h" +class ArrayElement { +public: + Node *value; + unsigned count; + ArrayElement(Node *value, unsigned count): value(value), count(count) {} +}; + class ArrayElements { private: + std::vector elements; + SourceLocation location; public: - std::vector elements; - ArrayElements(); - void append(ArrayElement& e); + ArrayElements(location_t loc); + void append(ArrayElement *e); - unsigned getArraySize() const; - unsigned getStructSize () const; - unsigned getElementCount (int position) const; - Node *getStructElement (int position) const; - Type *getArrayType(BasicBlock *block, BasicBlock *allocblock) const; -}; - -#endif + unsigned getArraySize(); + unsigned getStructSize (); + unsigned getElementCount (int position); + Node *getStructElement (int position); + DataType getArrayType(); + static DataType getArrayConstType(const set& types, SourceLocation *location); + + std::vector& getElements() { + return elements; + } + void insertElements(ArrayElements *newElements) { + elements.insert(elements.end(), + newElements->elements.begin(), newElements->elements.end()); + } +}; diff --git a/src/AttachInterrupt.h b/src/AttachInterrupt.h index b4a6261..43081a7 100644 --- a/src/AttachInterrupt.h +++ b/src/AttachInterrupt.h @@ -1,53 +1,5 @@ #ifndef __ATTACHINTERRUPT_H__ #define __ATTACHINTERRUPT_H__ -#include "Node.h" -class AttachInterrupt: public Node { -private: - string fname; - int port; - int event; - static Function *fattach; -public: - AttachInterrupt(int _port, string _fname, int _event) { - this->fname = _fname; - this->port = _port; - this->event = _event; - } - - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - - auto symbol = search_symbol(fname); - assert(symbol != NULL); - Value *cfunc = symbol->value; - - // called func type (the function that is attached to interruption) - std::vector arg_types; - FunctionType *fcalledtype = FunctionType::get(Type::getVoidTy(global_context), - arg_types, false); - - // setup arduino attachInterrupt function - if (!fattach) { - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - arg_types.push_back(fcalledtype->getPointerTo()); - arg_types.push_back(Type::getInt16Ty(global_context)); - - FunctionType *ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - - fattach = Function::Create(ftype, Function::ExternalLinkage, "attachInterrupt", mainmodule); - fattach->setCallingConv(CallingConv::C); - } - - vector args; - args.push_back(ConstantInt::get(Type::getInt8Ty(global_context), port)); - args.push_back(cfunc); - args.push_back(ConstantInt::get(Type::getInt16Ty(global_context), event)); - - ArrayRef argsRef(args); - return CallInst::Create(fattach, argsRef, "", block); - } -}; #endif diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 7f4a0ed..43c9977 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -1,66 +1,118 @@ + +#include #include + +#include #include #include #include #include #include +#include #include #include #include #include #include - +#include #include #include - -#include #include +#include +#include #include +#include #include #include +#include -#include "Header.h" +#include "BackLLVM.h" +#include "passes/PassStripUnusedFields.h" using namespace llvm; // Program main module -Module *mainmodule; -BasicBlock *global_alloc; +Module* mainmodule; +BasicBlock* global_alloc; LLVMContext global_context; -static IRBuilder<> builder(global_context); +std::unique_ptr> Builder; +std::unique_ptr DBuilder; +struct DebugInfo RobDbgInfo; +std::unique_ptr buildTypes; +TargetMachine *targetMachine; + +unsigned int codeAddrSpace = 1; +unsigned int dataAddrSpace = 0; + -// symbol table -std::map> tabelasym; +// Injections +map injections; +set unusedParents; -Type* robTollvmDataType[__ldt_last]; +enum SupportedTargets currentTargetId; +extern char *build_outputfilename; -// arduino functions -Function *analogWrite; -Function *analogRead; -Function *delay; -Function *delayMicroseconds; -Function *init; -Function *print; -Function *i16div; +TargetInfo supportedTargets[__last_target] = { + {rb_native, "native", "", "", "", tint64}, // default target -void print_llvm_ir(const char *target, char opt_level) { + {rb_avr, "attiny13a", "avr", "attiny13a", "+avr25", tint16}, + {rb_avr, "attiny85", "avr", "attiny85", "+avr25", tint16}, + {rb_avr, "atmega328p", "avr", "atmega328p", "+avr5", tint16}, + {rb_avr, "atmega32u4", "avr", "atmega32u4", "+avr5", tint16}, + {rb_avr, "atmega1284p", "avr", "atmega1284p", "+avr51", tint16}, + + {rb_arm, "stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, - InitializeAllTargetInfos(); - InitializeAllTargets(); - InitializeAllTargetMCs(); - InitializeAllAsmParsers(); - InitializeAllAsmPrinters(); + {rb_arm, "rp2040", "thumbv6m-none-eabi", "cortex-m0plus", "+soft-float", tint32}, + + {rb_xtensa, "esp32", "xtensa", "", "", tint32}, +}; + +void setup_target_machine(char opt_level) { + + const TargetInfo& ai = currentTarget(); + if (ai.backend == rb_native) { + // Native target init + InitializeNativeTarget(); + InitializeNativeTargetAsmParser(); + InitializeNativeTargetAsmPrinter(); + } else if (ai.backend == rb_avr) { + // AVR target init + LLVMInitializeAVRTargetInfo(); + LLVMInitializeAVRTarget(); + LLVMInitializeAVRTargetMC(); + LLVMInitializeAVRAsmParser(); + LLVMInitializeAVRAsmPrinter(); + } else if (ai.backend == rb_arm) { + // ARM target init + LLVMInitializeARMTargetInfo(); + LLVMInitializeARMTarget(); + LLVMInitializeARMTargetMC(); + LLVMInitializeARMAsmParser(); + LLVMInitializeARMAsmPrinter(); + } else { + cerr << "No backend set for target " << ai.triple << ".\n"; + return; + } std::string defaultt = sys::getDefaultTargetTriple(); supportedTargets[0].triple = defaultt.c_str(); - TargetInfo ai = supportedTargets[0]; - for(int t = 0; t < (sizeof(supportedTargets)/sizeof(TargetInfo)); t++) { - if (strcmp(target, supportedTargets[t].name) == 0) { - ai = supportedTargets[t]; - break; + SubtargetFeatures Features; + + #if LLVM_VERSION_MAJOR < 19 + StringMap HostFeatures; + if (sys::getHostCPUFeatures(HostFeatures)) { + #else + auto HostFeatures = sys::getHostCPUFeatures(); { + #endif + for (auto &F : HostFeatures) { + Features.AddFeature(F.first(), F.second); } } + static string nativeFeatures = Features.getString(); + supportedTargets[0].features = nativeFeatures.c_str(); + std::string Error; auto Target = TargetRegistry::lookupTarget(ai.triple, Error); if (!Target) { @@ -69,11 +121,35 @@ void print_llvm_ir(const char *target, char opt_level) { } TargetOptions opt; - auto RM = optional(); - auto targetMachine = Target->createTargetMachine(ai.triple, ai.cpu, ai.features, opt, RM); + opt.FunctionSections = true; + opt.DataSections = true; + opt.ExceptionModel = ExceptionHandling::None; - mainmodule->setDataLayout(targetMachine->createDataLayout()); + auto reloc = Reloc::PIC_; + if (ai.backend == rb_arm) + reloc = Reloc::Static; + + CodeGenOptLevel cgoptl = CodeGenOptLevel::None; + switch (opt_level) { + case '1': cgoptl = CodeGenOptLevel::Less; break; + case '2': cgoptl = CodeGenOptLevel::Default; break; + case '3': + case 's': + case 'z': + cgoptl = CodeGenOptLevel::Aggressive; + break; + } + + targetMachine = Target->createTargetMachine(ai.triple, + ai.cpu, ai.features, opt, reloc, CodeModel::Small, cgoptl); + const DataLayout dl = targetMachine->createDataLayout(); + + mainmodule->setDataLayout(dl); mainmodule->setTargetTriple(ai.triple); + mainmodule->setFramePointer(FramePointerKind::All); +} + +int print_llvm_ir(char opt_level) { PassBuilder passBuilder(targetMachine); auto loopAnalysisManager = LoopAnalysisManager{}; @@ -88,6 +164,7 @@ void print_llvm_ir(const char *target, char opt_level) { passBuilder.crossRegisterProxies( loopAnalysisManager, functionAnalysisManager, cGSCCAnalysisManager, moduleAnalysisManager); + bool debugopt = false; OptimizationLevel ol; switch (opt_level) { case '0': ol = OptimizationLevel::O0; break; @@ -95,16 +172,55 @@ void print_llvm_ir(const char *target, char opt_level) { case '2': ol = OptimizationLevel::O2; break; case '3': ol = OptimizationLevel::O3; break; case 's': ol = OptimizationLevel::Os; break; + case 'd': debugopt = true; break; case 'z': default : ol = OptimizationLevel::Oz; break; } - if (opt_level != '0') { - ModulePassManager modulePassManager = - passBuilder.buildPerModuleDefaultPipeline(ol); - modulePassManager.run(*mainmodule, moduleAnalysisManager); + bool llvmir_errors = false; + for(auto &f : mainmodule->getFunctionList()) { + if (verifyFunction(f, &llvm::errs())) { + cerr << endl << "Error(s) detected while verifying function " << f.getName().str() << endl; + llvmir_errors = true; + } + } + + bool broken_debug = false; + if (verifyModule(*mainmodule, &llvm::errs(), &broken_debug)) { + cerr << endl << "Error(s) detected while verifying the global module." << endl; + llvmir_errors = true; } + if (broken_debug) + cerr << "Errors in debug information were detected while verifying the global module." << endl; + + // This is used to see the llvm IR prior to any analysis. + // Sometimes when adding new features, we want to see the IR even + // it being invalid. + if (debugopt) { + mainmodule->print(outs(), nullptr); + return 0; + } + + if (llvmir_errors) + return 1; + + UpgradeDebugInfo(*mainmodule); + + // Run passes that need unoptimized code + auto modulePassManagerUnopt = ModulePassManager(); + modulePassManagerUnopt.addPass(StripUnusedParentFieldsPass()); + modulePassManagerUnopt.run(*mainmodule, moduleAnalysisManager); + + ModulePassManager modulePassManager; + if (ol == OptimizationLevel::O0) + modulePassManager = passBuilder.buildO0DefaultPipeline(ol); + else + //modulePassManager = passBuilder.buildPerModuleDefaultPipeline(ol); + modulePassManager = passBuilder.buildThinLTODefaultPipeline(ol, nullptr); + + modulePassManager.run(*mainmodule, moduleAnalysisManager); + if (build_outputfilename) { std::error_code ec; raw_fd_ostream dest(build_outputfilename, ec); @@ -113,12 +229,34 @@ void print_llvm_ir(const char *target, char opt_level) { exit(1); } legacy::PassManager pass_codegen; - targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, llvm::CGFT_ObjectFile); + targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, CodeGenFileType::ObjectFile); + //targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, CodeGenFileType::AssemblyFile); pass_codegen.run(*mainmodule); - dest.flush(); + dest.close(); } else { // print IR to stdout mainmodule->print(outs(), nullptr); } + + return 0; } +const TargetInfo& currentTarget() { + return supportedTargets[currentTargetId]; +} + +void setTarget(const char *targetarch) { + currentTargetId = st_native; //native + for(int t = st_native; t < __last_target; t++) { + if (strcmp(targetarch, supportedTargets[t].name) == 0) { + currentTargetId = static_cast(t); + break; + } + } + + // must set cpu before function generation + if (currentTargetId == st_native) { + static string defaultcpu = sys::getHostCPUName().str(); + supportedTargets[0].cpu = defaultcpu.c_str(); + } +} diff --git a/src/BackLLVM.h b/src/BackLLVM.h new file mode 100644 index 0000000..dc1cb49 --- /dev/null +++ b/src/BackLLVM.h @@ -0,0 +1,52 @@ + +#pragma once + +#include "BuildTypes.h" +#include "Injections.h" + +extern std::unique_ptr> Builder; + +enum RobBackend {rb_native, rb_avr, rb_arm, rb_xtensa}; + +typedef struct { + enum RobBackend backend; + const char *name; + const char *triple; + const char *cpu; + const char *features; + const DataType pointerType; +} TargetInfo; + +extern unsigned int codeAddrSpace; +extern unsigned int dataAddrSpace; + +enum SupportedTargets { + st_native, + + // avr + st_attiny13a, + st_attiny85, + st_atmega328p, + st_atmega32u4, + st_atmega1284p, + + // stm32 + st_stm32f1, + + // raspberry pico + st_rp2040, + + // awaiting backend goes mainstream + st_esp32, + __last_target}; + +extern enum SupportedTargets currentTargetId; + +extern TargetInfo supportedTargets[__last_target]; +void setTarget(const char *targetarch); +const TargetInfo& currentTarget(); + +class Variable; + +extern map injections; +extern set unusedParents; diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index c70a0e5..f661787 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -1,145 +1,94 @@ -#include "Header.h" -#include "Int8.h" +#include "FlexDependencies.h" +#include "Language_gen_y.hpp" -BinaryOp::BinaryOp(Node *l, int op, Node *r) { - this->lhsn = l; - this->rhsn = r; +#include "BinaryOp.h" +#include "FunctionImpl.h" + +BinaryOp::BinaryOp(Node *l, int op, Node *r) : Node(l->getLoc()) { this->op = op; - this->node_children.reserve(2); - this->node_children.push_back(lhsn); - this->node_children.push_back(rhsn); + this->addChild(l); + this->addChild(r); } Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, - Function *func, BasicBlock *block, BasicBlock *allocblock) { + FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + // The code below implements boolean short-circuit evaluation + // See https://en.wikipedia.org/wiki/Short-circuit_evaluation + + // left + BasicBlock *newlblock = block; + Value *lhs = lhsn()->generateNewBlock(func, &newlblock, allocblock); + Type *lhsty = lhs->getType(); + + BasicBlock *fullev = BasicBlock::Create(global_context, "fullev", func->getLLVMFunction()); + BasicBlock *phiblock = BasicBlock::Create(global_context, "phiblock", func->getLLVMFunction()); + PHINode *phi = PHINode::Create(lhsty, 0, "phi", phiblock); + phi->addIncoming(lhs, newlblock); + + if (op == Instruction::BinaryOps::Or) + BranchInst::Create(phiblock, fullev, lhs, newlblock); + else // and + BranchInst::Create(fullev, phiblock, lhs, newlblock); + + // right + BasicBlock *newrblock = fullev; + Value *rhs = rhsn()->generateNewBlock(func, &newrblock, allocblock); + Builder->SetInsertPoint(newrblock); + Value *binop = Builder->CreateBinOp(op, lhs, rhs, "logicop"); + BranchInst::Create(phiblock, newrblock); + phi->addIncoming(binop, newrblock); + + if (!lhsty->isIntegerTy() || !(lhsty->getIntegerBitWidth() == 1)) { + errs() << "Left: " << *lhsty << "\n"; + yyerrorcpp("The left side of the logical expression is not boolean.", this); + } + + Type *rhsty = rhs->getType(); + if (!rhsty->isIntegerTy() || !(rhsty->getIntegerBitWidth() == 1)) + yyerrorcpp("The right side of the logical expression is not boolean.", this); - Value *lhs = lhsn->generate(func, block, allocblock); - Value *rhs = rhsn->generate(func, block, allocblock); - return BinaryOperator::Create(op, lhs, rhs, "logicop", block); + return phi; } Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, - enum Instruction::BinaryOps opflt, Function *func, BasicBlock *block, BasicBlock *allocblock) { + enum Instruction::BinaryOps opflt, FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + DataType lty = lhsn()->getDataType(); + DataType rty = rhsn()->getDataType(); + + // Generate left and right side + Value *lhs = lhsn()->generateNewBlock(func, &block, allocblock); + Value *rhs = rhsn()->generateNewBlock(func, &block, allocblock); - Value *lhs = lhsn->generate(func, block, allocblock); - Value *rhs = rhsn->generate(func, block, allocblock); if (lhs == NULL || rhs == NULL) return NULL; - Type *Ty1 = lhs->getType(); - Type *Ty2 = rhs->getType(); - enum Instruction::BinaryOps llvmop; - - if (Ty1->isIntegerTy() && Ty2->isIntegerTy()) { - /*fallback SDiv disabled - if (opint == Instruction::SDiv) { - vector args; - args.push_back(lhs); - args.push_back(rhs); - ArrayRef argsRef(args); - return CallInst::Create(i16div, argsRef, "", block); - }*/ - - if (opint == Instruction::Shl || opint == Instruction::LShr) { - // sext the left operator if we know the rside bitwidth - Constant *c = NULL; - if (rhsn->isConstExpr(block, allocblock)) { - Value *v = rhsn->generate(NULL, block, allocblock); - c = dyn_cast(v); - } - if (c) { - int64_t v = c->getUniqueInteger().getZExtValue(); - if (Ty1->getIntegerBitWidth() < v) { - if (v >= 8 && v <= 15) - lhs = new SExtInst(lhs, Type::getInt16Ty(global_context), "sext16", block); - else if (v >= 16 && v <= 31) - lhs = new SExtInst(lhs, Type::getInt32Ty(global_context), "sext32", block); - else if (v >= 32 && v <= 63) - lhs = new SExtInst(lhs, Type::getInt64Ty(global_context), "sext64", block); - else - yyerrorcpp("Number of shift bits exceeds the max int precision for left side.", this); - Ty1 = lhs->getType(); - } - } + if (buildTypes->isIntegerDataType(lty)) { // it suffices to check one side, operands has been coerced + if (buildTypes->isUnsignedDataType(lty)) { + if (opint == Instruction::SDiv) + opint = Instruction::UDiv; + else if (opint == Instruction::SRem) + opint = Instruction::URem; + else if (opint == Instruction::AShr) + opint = Instruction::LShr; } - - if (dyn_cast(Ty1)->getBitWidth() > dyn_cast(Ty2)->getBitWidth()) - rhs = Coercion::Convert(rhs, Ty1, block, rhsn); - else - lhs = Coercion::Convert(lhs, Ty2, block, lhsn); - llvmop = opint; - } - else { - if (Ty1->isIntegerTy()) - lhs = new SIToFPInst(lhs, Ty2, "castitof", block); - else if (Ty2->isIntegerTy()) - rhs = new SIToFPInst(rhs, Ty1, "castitof", block); + } else { llvmop = opflt; } - Constant *c0 = dyn_cast(lhs); - Constant *c1 = dyn_cast(rhs); - if (c0 && c1) { - switch (getOperator()) { - case '+': return ConstantExpr::getAdd(c0, c1); - case '-': return ConstantExpr::getSub(c0, c1); - case '*': return ConstantExpr::getMul(c0, c1); - - case TOK_OR: - case '|': return ConstantExpr::getOr(c0, c1); - - case TOK_AND: - case '&': return ConstantExpr::getAnd(c0, c1); - - case '^': return ConstantExpr::getXor(c0, c1); - case TOK_LSHIFT: return ConstantExpr::getShl(c0, c1); - case TOK_RSHIFT: return ConstantExpr::getLShr(c0, c1); - default: - break; - } - } - - return BinaryOperator::Create(llvmop, lhs, rhs, "binop", block); + Builder->SetInsertPoint(block); + RobDbgInfo.emitLocation(this); + return Builder->CreateBinOp(llvmop, lhs, rhs, "binop"); } -Type *BinaryOp::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { - Type *lty = lhsn->getLLVMResultType(block, allocblock); - Type *rty = rhsn->getLLVMResultType(block, allocblock); - if (lty->isIntegerTy() && rty->isIntegerTy()) { - if (op == TOK_LSHIFT || op == TOK_RSHIFT) { - // sext the left operator if we know the rside bitwidth - Constant *c = NULL; - if (rhsn->isConstExpr(block, allocblock)) { - Value *v = rhsn->generate(NULL, block, allocblock); - c = dyn_cast(v); - } - if (c) { - int64_t v = c->getUniqueInteger().getZExtValue(); - if (lty->getIntegerBitWidth() < v) { - if (v >= 8 && v <= 15) - return Type::getInt16Ty(global_context); - else if (v >= 16 && v <= 31) - return Type::getInt32Ty(global_context); - else if (v >= 32 && v <= 63) - return Type::getInt64Ty(global_context); - else - return NULL; - } - } - } - return lty->getIntegerBitWidth() > rty->getIntegerBitWidth() ? lty : rty; - - } else { - if (lty->isIntegerTy()) - return rty; - else - return lty; - } +DataType BinaryOp::getDataType() { + return dt; } -Value *BinaryOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *BinaryOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { switch (op) { case '+' : return binary_operator(Instruction::Add, Instruction::FAdd, func, block, allocblock); case '-' : return binary_operator(Instruction::Sub, Instruction::FSub, func, block, allocblock); @@ -150,18 +99,14 @@ Value *BinaryOp::generate(Function *func, BasicBlock *block, BasicBlock *allocbl case '&' : return binary_operator(Instruction::And, Instruction::And, func, block, allocblock); case '^' : return binary_operator(Instruction::Xor, Instruction::Xor, func, block, allocblock); case TOK_LSHIFT: return binary_operator(Instruction::Shl, Instruction::Shl, func, block, allocblock); - case TOK_RSHIFT: return binary_operator(Instruction::LShr, Instruction::LShr, func, block, allocblock); + case TOK_RSHIFT: return binary_operator(Instruction::AShr, Instruction::AShr, func, block, allocblock); case TOK_AND : return logical_operator(BinaryOperator::And, func, block, allocblock); case TOK_OR : return logical_operator(BinaryOperator::Or, func, block, allocblock); default: return NULL; } } -void BinaryOp::accept(Visitor& v) { - v.visit(*this); -} - -bool BinaryOp::isConstExpr(BasicBlock *block, BasicBlock *allocblock) { - return lhsn->isConstExpr(block, allocblock) && - rhsn->isConstExpr(block, allocblock); +bool BinaryOp::isConstExpr() { + return lhsn()->isConstExpr() && + rhsn()->isConstExpr(); } diff --git a/src/BinaryOp.h b/src/BinaryOp.h index 1cfeb06..ad89640 100644 --- a/src/BinaryOp.h +++ b/src/BinaryOp.h @@ -1,30 +1,39 @@ -#ifndef __BINARYOP_H__ -#define __BINARYOP_H__ + +#pragma once + #include "Node.h" +#include "semantic/Visitor.h" class BinaryOp: public Node { private: int op; - Node *lhsn; - Node *rhsn; + public: BinaryOp(Node *l, int op, Node *r); Value *logical_operator(enum Instruction::BinaryOps op, - Function *func, BasicBlock *block, BasicBlock *allocblock); + FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); Value *binary_operator(enum Instruction::BinaryOps opint, - enum Instruction::BinaryOps opflt, Function *func, BasicBlock *block, BasicBlock *allocblock); - - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + enum Instruction::BinaryOps opflt, FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); - virtual void accept(Visitor &v) override; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; int getOperator() const { return op; }; - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override; + virtual DataType getDataType() override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; -}; + virtual bool isConstExpr() override; + + Node *lhsn() { + return node_children[0]; + } + + Node *rhsn() { + return node_children[1]; + }; -#endif + Node* accept(Visitor &v) override { + return v.visit(*this); + } +}; diff --git a/src/BitCast.cpp b/src/BitCast.cpp new file mode 100644 index 0000000..7813488 --- /dev/null +++ b/src/BitCast.cpp @@ -0,0 +1,9 @@ + +#include "BitCast.h" + +Value *BitCast::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) +{ + Value *v = value->generate(func, block, allocblock); + Type *dTy = buildTypes->llvmType(destTy); + return Builder->CreateBitCast(v, dTy); +} diff --git a/src/BitCast.h b/src/BitCast.h new file mode 100644 index 0000000..bf3a891 --- /dev/null +++ b/src/BitCast.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Node.h" +#include "semantic/Visitor.h" + +class BitCast: public Node { +private: + Node *value; + DataType destTy; + +public: + BitCast(Node *v, DataType dTy): Node(v->getLoc()), value(v), destTy(dTy) { + addChild(v); + } + + virtual DataType getDataType() override { + return destTy; + } + + virtual DataType getSourceType() { + return value->getDataType(); + } + + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; +}; diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp new file mode 100644 index 0000000..40dc609 --- /dev/null +++ b/src/BuildTypes.cpp @@ -0,0 +1,330 @@ + +#include "BuildTypes.h" +#include "HeaderGlobals.h" +#include "Identifier.h" +#include "NamedConst.h" +#include "Node.h" +#include "Program.h" +#include "Scanner.h" +#include "Variable.h" +#include "Array.h" +#include "Matrix.h" +#include "UserType.h" +#include "BackLLVM.h" +#include "Int8.h" + +BuildTypes::BuildTypes(DataType targetPointerType, Program *program) : + targetPointerType(targetPointerType) { + + unsigned pts = tinfo[targetPointerType].bitWidth; + + tinfo[tvoid] = {"void", 0, Type::getVoidTy(global_context), dwarf::DW_ATE_address}; + tinfo[tbool] = {"bool", 1, Type::getInt1Ty(global_context), dwarf::DW_ATE_boolean}; + tinfo[tchar] = {"char", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned_char}; + tinfo[tint8] = {"int8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint16] = {"int16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint32] = {"int32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint64] = {"int64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint2u] = {"uint2", 2, Type::getIntNTy(global_context, 2), dwarf::DW_ATE_unsigned}; + tinfo[tint3u] = {"uint3", 3, Type::getIntNTy(global_context, 3), dwarf::DW_ATE_unsigned}; + tinfo[tint4u] = {"uint4", 4, Type::getIntNTy(global_context, 4), dwarf::DW_ATE_unsigned}; + tinfo[tint5u] = {"uint5", 5, Type::getIntNTy(global_context, 5), dwarf::DW_ATE_unsigned}; + tinfo[tint6u] = {"uint6", 6, Type::getIntNTy(global_context, 6), dwarf::DW_ATE_unsigned}; + tinfo[tint7u] = {"uint7", 7, Type::getIntNTy(global_context, 7), dwarf::DW_ATE_unsigned}; + tinfo[tint8u] = {"uint8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint9u] = {"uint9", 9, Type::getIntNTy(global_context, 9), dwarf::DW_ATE_unsigned}; + tinfo[tint10u] = {"uint10", 10, Type::getIntNTy(global_context, 10),dwarf::DW_ATE_unsigned}; + tinfo[tint11u] = {"uint11", 11, Type::getIntNTy(global_context, 11),dwarf::DW_ATE_unsigned}; + tinfo[tint12u] = {"uint12", 12, Type::getIntNTy(global_context, 12),dwarf::DW_ATE_unsigned}; + tinfo[tint13u] = {"uint13", 13, Type::getIntNTy(global_context, 13),dwarf::DW_ATE_unsigned}; + tinfo[tint14u] = {"uint14", 14, Type::getIntNTy(global_context, 14),dwarf::DW_ATE_unsigned}; + tinfo[tint15u] = {"uint15", 15, Type::getIntNTy(global_context, 15),dwarf::DW_ATE_unsigned}; + tinfo[tint16u] = {"uint16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint17u] = {"uint17", 17, Type::getIntNTy(global_context, 17),dwarf::DW_ATE_unsigned}; + tinfo[tint18u] = {"uint18", 18, Type::getIntNTy(global_context, 18),dwarf::DW_ATE_unsigned}; + tinfo[tint19u] = {"uint19", 19, Type::getIntNTy(global_context, 19),dwarf::DW_ATE_unsigned}; + tinfo[tint20u] = {"uint20", 20, Type::getIntNTy(global_context, 20),dwarf::DW_ATE_unsigned}; + tinfo[tint21u] = {"uint21", 21, Type::getIntNTy(global_context, 21),dwarf::DW_ATE_unsigned}; + tinfo[tint22u] = {"uint22", 22, Type::getIntNTy(global_context, 22),dwarf::DW_ATE_unsigned}; + tinfo[tint23u] = {"uint23", 23, Type::getIntNTy(global_context, 23),dwarf::DW_ATE_unsigned}; + tinfo[tint24u] = {"uint24", 24, Type::getIntNTy(global_context, 24),dwarf::DW_ATE_unsigned}; + tinfo[tint25u] = {"uint25", 25, Type::getIntNTy(global_context, 25),dwarf::DW_ATE_unsigned}; + tinfo[tint26u] = {"uint26", 26, Type::getIntNTy(global_context, 26),dwarf::DW_ATE_unsigned}; + tinfo[tint27u] = {"uint27", 27, Type::getIntNTy(global_context, 27),dwarf::DW_ATE_unsigned}; + tinfo[tint28u] = {"uint28", 28, Type::getIntNTy(global_context, 28),dwarf::DW_ATE_unsigned}; + tinfo[tint29u] = {"uint29", 29, Type::getIntNTy(global_context, 29),dwarf::DW_ATE_unsigned}; + tinfo[tint30u] = {"uint30", 30, Type::getIntNTy(global_context, 30),dwarf::DW_ATE_unsigned}; + tinfo[tint31u] = {"uint31", 31, Type::getIntNTy(global_context, 31),dwarf::DW_ATE_unsigned}; + tinfo[tint32u] = {"uint32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint64u] = {"uint64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tfloat] = {"float", 32, Type::getFloatTy(global_context), dwarf::DW_ATE_float}; + tinfo[tdouble] = {"double", 64, Type::getDoubleTy(global_context), dwarf::DW_ATE_float}; + tinfo[tldouble] = {"ldouble", 128, Type::getFP128Ty(global_context), dwarf::DW_ATE_float}; + + // a generic internal pointer + tinfo[tobject] = {"object", pts, PointerType::getUnqual(Type::getVoidTy(global_context)), dwarf::DW_ATE_address}; + tinfo[tobject].isComplex = true; + + const DataLayout &dl = mainmodule->getDataLayout(); + for(int t = 0; t < __bdt_last; t++) { + DataTypeInfo &info = tinfo[t]; + namedTypes[info.name] = t; + if (debug_info) { + unsigned bitWidth = 0; + if (t > 0) // no void + bitWidth = dl.getTypeAllocSizeInBits(info.llvmType); + info.diType = DBuilder->createBasicType(info.name, bitWidth, info.dwarfEnc); + info.diPointerType = DBuilder->createPointerType(info.diType, pts); + } + + NamedConst *typeidConst = new NamedConst(info.name, new Int8(t, program->getLoc())); + program->addSymbol(typeidConst); + } +} + +DataType BuildTypes::getArrayType(const string& elementName, SourceLocation n, + unsigned char dimensions, bool createUndefined) { + + string arrayTyName = elementName; + for(int i = 0; i < dimensions; i++) + arrayTyName += "[]"; + + auto ut = namedTypes.find(arrayTyName); + if (ut == namedTypes.end()) { + if (createUndefined) { + auto elementTyIter = namedTypes.find(elementName); + auto elementInfo = tinfo[elementTyIter->second]; + if (elementTyIter == namedTypes.end() || elementInfo.llvmType == NULL) { + yyerrorcpp(string_format("Type %s is not defined.", + elementName.c_str()), &n, true); + } else { + DataType dt = addDataType(DataTypeInfo(arrayTyName)); + DataTypeInfo &info = tinfo[dt]; + Type *I = elementInfo.llvmType; + if (elementInfo.isComplex) { + // In rob, any array of complex types is an array of refs + I = PointerType::getUnqual(elementInfo.llvmType); + } + // we don't know the array size at compile time + info.llvmType = ArrayType::get(I, 0); + info.isDefined = true; + info.isComplex = false; + info.arrayDimensions = dimensions; + info.bitWidth = tinfo[targetPointerType].bitWidth; + info.dwarfEnc = dwarf::DW_ATE_address; + return dt; + } + } + } else if (tinfo[ut->second].isDefined || createUndefined) { + return ut->second; + } + return undefinedType; +} + +DataType BuildTypes::getArrayElementType(DataType arrayDt) { + assert(isArrayOrMatrix(arrayDt) && "arrayDt must be an array or matrix."); + string elementName = name(arrayDt); + elementName = elementName.substr(0, elementName.length() - 2*dimensions(arrayDt)); + return getType(elementName); +} + +DataType BuildTypes::getType(const string& name, bool createUndefined) { + auto ut = namedTypes.find(name); + if (ut == namedTypes.end()) { + if (createUndefined) { + DataTypeInfo dti(name); + dti.isComplex = true; + return addDataType(dti); + } + } else { + return ut->second; + } + return undefinedType; +} + +DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBitWidth, + bool isEnum) { + string name = userType->getName(); + if (UserType *ut = dynamic_cast(userType)) + name = ut->getTypeName(); + auto udt = namedTypes.find(name); + DataType id; + + const DataLayout& dl = mainmodule->getDataLayout(); + uint64_t bitWidth = typeBitWidth; + if (typeBitWidth == 0 && llvmType->isSized()) + typeBitWidth = dl.getTypeAllocSizeInBits(llvmType); + + if (udt == namedTypes.end()) { + DataTypeInfo info(name.c_str(), bitWidth, llvmType, 0); + id = addDataType(info); + } else { + id = udt->second; + } + DataTypeInfo &info = tinfo[id]; + info.sl = userType; + info.llvmType = llvmType; + info.isDefined = true; + info.isComplex = !isEnum; + info.isEnum = isEnum; + info.dwarfEnc = 0; + info.bitWidth = bitWidth; + info.isInternal = false; + info.isInterface = false; + return id; +} + +Type *BuildTypes::llvmType(DataType tid) { + if (tid == -1) + return NULL; + else + return tinfo[tid].llvmType; +} + +void BuildTypes::generateDebugInfoForEnum(DataTypeInfo &info, Node *userType) { + + unsigned offset = 0; + vector elems; + + for(auto *m : userType->children()) { + if (NamedConst *n = dynamic_cast(m)) { + Node *value = n->getValue(); + uint8_t v = 0; + if (Int8 *i8 = dynamic_cast(value)) + v = i8->getNumber(); + else if (UInt8 *ui8 = dynamic_cast(value)) + v = ui8->getNumber(); + else + assert(0 && "Unknown enum value node."); + + auto etor = DBuilder->createEnumerator(n->getName(), v); + elems.push_back(etor); + } else + assert(0 && "Unknown enum node."); + } + + auto dielems = DBuilder->getOrCreateArray(elems); + info.diType = DBuilder->createEnumerationType(RobDbgInfo.currScope(), info.name, + RobDbgInfo.currFile(), userType->getLineNo(), info.bitWidth, 1, + dielems, tinfo[tint8].diType); +} + +void BuildTypes::generateDebugInfoForUserType(DataTypeInfo &info, Node *userType) { + + const DataLayout& dl = mainmodule->getDataLayout(); + unsigned offset = 0; + vector elems; + vector members; + for(auto *m : userType->children()) { + if (Node *n = dynamic_cast(m)) + members.push_back(n); + } + + //assert((members.size() == llvmType->getNumContainedTypes()) && + // "Number of fields differ between LLVM Type and Node."); + + elems.reserve(members.size()); + for(Node *m : members) { + DataType mdt = m->getDataType(); + if (isInterface(mdt)) { + // search the injections + string fieldName = info.name; + fieldName.append("." + m->getName()); + if (injections.find(fieldName) != injections.end()) { + string injType = injections[fieldName]->bind; + Node *symbol = Identifier(injType, userType->getLoc()).getSymbol(program, false); + if (symbol) + mdt = symbol->getDataType(); + } + } + if (mdt == -1 || tinfo[mdt].bitWidth == 0) { + continue; + } + + Type *memberTy = tinfo[mdt].llvmType; + DIType *memberDiType = diType(mdt); + if (Variable *v = dynamic_cast(m)) { + if (v->getPointerMode() == pm_pointer) { + memberTy = PointerType::getUnqual(memberTy); + memberDiType = diPointerType(mdt); + if (!memberDiType) { + // parent field + memberDiType = diPointerType(targetPointerType); + } + } + } + + uint64_t memberBitWidth = dl.getTypeAllocSizeInBits(memberTy); + if (memberTy->isArrayTy()) { + memberBitWidth = dl.getTypeAllocSizeInBits(memberTy->getArrayElementType()); + if (Matrix *matrix = dynamic_cast(m)) + memberBitWidth *= matrix->getRows() * matrix->getCols(); + else if (Array *array = dynamic_cast(m)) + memberBitWidth *= array->getSize(); + } + uint32_t memberAlignInBits = dl.getABITypeAlign(memberTy).value() * 8; + + // align offset according to memberAlign + // TODO: improved this when implementing packed structs/types + if (offset % memberAlignInBits != 0) + offset += memberAlignInBits - (offset % memberAlignInBits); + + DIType *di = DBuilder->createMemberType(RobDbgInfo.currScope(), m->getName(), + RobDbgInfo.currFile(), m->getLineNo(), memberBitWidth, memberAlignInBits, + offset, DINode::DIFlags::FlagZero, memberDiType); + assert(di); + elems.push_back(di); + offset += memberBitWidth; + } + + auto dielems = DBuilder->getOrCreateArray(elems); + info.diType = DBuilder->createClassType(RobDbgInfo.currScope(), info.name, + RobDbgInfo.currFile(), userType->getLineNo(), info.bitWidth, 1, 0, + DINode::DIFlags::FlagZero, nullptr, dielems); + unsigned ptbw = tinfo[targetPointerType].bitWidth; + info.diPointerType = DBuilder->createPointerType(info.diType, ptbw); +} + +void BuildTypes::generateDebugInfoForTypes() { + if (!debug_info) + return; + + for (DataType dt = nextt-1; dt >= __bdt_last; dt--) { + auto& info = tinfo[dt]; + + Node *userType = program->findSymbol(info.name); + if (userType) { + if (info.isEnum) + generateDebugInfoForEnum(info, userType); + else if (info.isComplex) + generateDebugInfoForUserType(info, userType); + + } + } + + for (DataType dt = nextt-1; dt >= __bdt_last; dt--) { + auto& info = tinfo[dt]; + if (info.arrayDimensions > 0) { + auto elementInfo = tinfo[getArrayElementType(dt)]; + info.diType = DBuilder->createArrayType(0, 0, elementInfo.diPointerType, {}); + unsigned ptbw = tinfo[currentTarget().pointerType].bitWidth; + info.diPointerType = DBuilder->createPointerType(elementInfo.diType, ptbw); + } + } +} + +bool BuildTypes::isArrayCompatible(DataType srcDt, DataType destDt) { + if (isArray(srcDt) ^ isArray(destDt)) + return false; + if (tinfo[srcDt].arrayDimensions != tinfo[destDt].arrayDimensions) + return false; + DataType elSrc = getArrayElementType(srcDt); + DataType elDest = getArrayElementType(destDt); + if (elSrc != elDest) { + if ((elSrc == tint8 || elSrc == tint8u || elSrc == tchar) && + (elDest == tint8 || elDest == tint8u || elDest == tchar)) { + return true; + } + } + return true; +} \ No newline at end of file diff --git a/src/BuildTypes.h b/src/BuildTypes.h new file mode 100644 index 0000000..931688d --- /dev/null +++ b/src/BuildTypes.h @@ -0,0 +1,275 @@ + +#pragma once + +#include +#include "HeaderGlobals.h" +#include "SourceLocation.h" + +typedef int DataType; + +/* Don't change the order of these types without updating the code below accordingly. + In another words, don't change it. + */ +enum BasicDataType {tvoid, tbool, tchar, + tint8, tint16, tint32, tint64, + tint2u, tint3u, tint4u, tint5u, tint6u, tint7u, tint8u, + tint9u, tint10u, tint11u, tint12u, tint13u, tint14u, tint15u, tint16u, + tint17u, tint18u, tint19u, tint20u, tint21u, tint22u, tint23u, tint24u, + tint25u, tint26u, tint27u, tint28u, tint29u, tint30u, tint31u, tint32u, + tint64u, + tfloat, tdouble, tldouble, + /* new types here! */ + tobject, + __bdt_last}; + +enum DataQualifier {qnone, qconst, qvolatile}; +typedef DataQualifier DataQualifier; + +struct DataTypeInfo { + string name; + unsigned bitWidth; + Type *llvmType; + unsigned dwarfEnc; + DIType *diType; + DIDerivedType *diPointerType; + SourceLocation *sl; + bool isDefined; + bool isComplex; + bool isEnum; + bool isInterface; + bool isInternal; + unsigned char arrayDimensions; + + DataTypeInfo() {} + + DataTypeInfo(string name) { + this->name = name; + this->bitWidth = 0; + this->llvmType = NULL; + this->dwarfEnc = 0; + this->diType = NULL; + this->diPointerType = NULL; + this->isDefined = false; + this->isComplex = false; + this->isEnum = false; + this->isInternal = false; + this->isInterface = false; + this->arrayDimensions = 0; + } + + DataTypeInfo(const char* name, unsigned bitWidth, Type *llvmType, unsigned dwarfEnc): + name(name), bitWidth(bitWidth), llvmType(llvmType), dwarfEnc(dwarfEnc), diType(NULL), + diPointerType(NULL), sl(NULL), isDefined(true), isComplex(false), isInternal(false), + isInterface(false), isEnum(false), arrayDimensions(0) {}; +}; + +class Program; + +class BuildTypes { +private: + map tinfo; + map namedTypes; + DataType nextt = __bdt_last; + DataType targetPointerType; + + DataType addDataType(const DataTypeInfo& udt) { + DataType result = nextt++; + tinfo[result] = udt; + namedTypes[udt.name] = result; + return result; + } + + void generateDebugInfoForEnum(DataTypeInfo &info, Node *userType); + void generateDebugInfoForUserType(DataTypeInfo &info, Node *userType); + +public: + static const DataType undefinedType = -1; + + BuildTypes(DataType targetPointerType, Program *program); + + DataType addDataType(Node* userType, Type* llvmType, + unsigned typeBitWidth = 0, bool isEnum = false); + + DataType getType(const string& name, bool createUndefined = false); + + DataType getArrayType(const string& elementName, SourceLocation n, + unsigned char dimensions, bool createUndefined = false); + + DataType getArrayElementType(DataType arrayDt); + + const char *name(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].name.c_str(); + } + + void updateName(DataType tid, const string& name) { + namedTypes.erase(tinfo[tid].name); + tinfo[tid].name = name; + namedTypes[name] = tid; + StructType *st = dyn_cast(llvmType(tid)); + if (st) + st->setName(name); + } + + const unsigned bitWidth(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].bitWidth; + } + + Type *llvmType(DataType tid); + + DIType *diType(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].diType; + } + + DIDerivedType *diPointerType(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].diPointerType; + } + + SourceLocation *location(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].sl; + } + + bool isPrimitiveType(DataType tid) const { + return tid >= tbool && tid < __bdt_last; + } + + bool isNumericDataType(DataType tid) { + return (tid >= tbool && tid <= tldouble) || isEnum(tid); + } + + bool isIntegerDataType(DataType tid) const { + return tid >= tbool && tid <= tint64u; + } + + bool isSignedDataType(DataType tid) const { + return (tid >= tint8 && tid <= tint64); + } + + bool isUnsignedDataType(DataType tid) const { + return (tid >= tint2u && tid <= tint64u) || (tid == tchar) || (tid == tbool); + } + + bool isFloatDataType(DataType tid) const { + return tid >= tfloat && tid <= tldouble; + } + + bool isComplex(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isComplex; + } + + bool isEnum(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isEnum; + } + + bool isInternal(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isInternal; + } + + void setInternal(DataType tid, bool v) { + assert(tid != -1 && "Undefined type"); + tinfo[tid].isInternal = v; + } + + void setInterface(DataType tid, bool v) { + assert(tid != -1 && "Undefined type"); + tinfo[tid].isInterface = v; + } + + bool isInterface(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isInterface; + } + + bool isUserType(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isComplex && !tinfo[tid].isInterface; + } + + bool isArray(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].arrayDimensions == 1; + } + + bool isMatrix(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].arrayDimensions == 2; + } + + bool isArrayOrMatrix(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].arrayDimensions > 0; + } + + unsigned char dimensions(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].arrayDimensions; + } + + DataType unsignedToSigned(DataType tid) { + assert(isUnsignedDataType(tid)); + switch (tid) { + case tchar: + return tint8; + case tint2u: + case tint3u: + case tint4u: + case tint5u: + case tint6u: + case tint7u: + case tint8u: + return tint8; + case tint16u: + return tint16; + case tint32u: + return tint32; + case tint64u: + default: + return tint64; + } + } + + DataType signedToUnsigned(DataType tid) { + assert(isSignedDataType(tid)); + if (tid == tbool) + return tid; + switch (tid) { + case tint8: + return tint8u; + case tint16: + return tint16u; + case tint32: + return tint32u; + case tint64: + default: + return tint64u; + } + } + + bool isDefined(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isDefined; + } + + unsigned getTargetPointerBitWidth() { + return tinfo[targetPointerType].bitWidth; + } + + void generateDebugInfoForTypes(); + + bool isArrayCompatible(DataType srcDt, DataType destDt); +}; + +// TODO: Replace all places with buildType::name +static string getTypeName(Type *ty) { + string type_str; + llvm::raw_string_ostream rso(type_str); + ty->print(rso); + return rso.str(); +} diff --git a/src/Capsule.cpp b/src/Capsule.cpp deleted file mode 100644 index 6ee260e..0000000 --- a/src/Capsule.cpp +++ /dev/null @@ -1,7 +0,0 @@ - -#include "Header.h" - -Value *Capsule::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - return node->generate(func, block, allocblock); -} - diff --git a/src/Capsule.h b/src/Capsule.h deleted file mode 100644 index b22e387..0000000 --- a/src/Capsule.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __CAPSULE_H__ -#define __CAPSULE_H__ -#include "Node.h" - -class Capsule: public Node { -private: - Node *node; -public: - Capsule (Node *n) : node(n) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); -}; - -#endif diff --git a/src/Cast.cpp b/src/Cast.cpp deleted file mode 100644 index f40781d..0000000 --- a/src/Cast.cpp +++ /dev/null @@ -1,28 +0,0 @@ - -#include "Header.h" - -Type *Cast::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { - return robTollvmDataType[dt]; -} - -Value *Cast::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) -{ - Value *exprv = expr->generate(func, block, allocblock); - if (!exprv) - return NULL; - - Type *destty = robTollvmDataType[dt]; - Value *ret = Coercion::Convert(exprv, destty, block, expr); - - if (ret == NULL) { - yyerrorcpp("Can't cast from '" + getTypeName(exprv->getType()) + "' to '" + - LanguageDataTypeNames[dt], this); - return NULL; - } - - return ret; -} - -void Cast::accept(Visitor &v) { - v.visit(*this); -} diff --git a/src/Cast.h b/src/Cast.h deleted file mode 100644 index cfd1ce9..0000000 --- a/src/Cast.h +++ /dev/null @@ -1,15 +0,0 @@ - -#pragma once - -#include "Header.h" - -class Cast: public Node { -private: - Node *expr; - LanguageDataType dt; -public: - Cast(LanguageDataType dt, Node *expr): dt(dt), expr(expr) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override; -}; diff --git a/src/Char.cpp b/src/Char.cpp new file mode 100644 index 0000000..8d71eec --- /dev/null +++ b/src/Char.cpp @@ -0,0 +1,7 @@ + +#include "Char.h" + +Value *Char::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) +{ + return ConstantInt::get(Type::getInt8Ty(global_context), value); +} diff --git a/src/Char.h b/src/Char.h new file mode 100644 index 0000000..0099e6d --- /dev/null +++ b/src/Char.h @@ -0,0 +1,24 @@ + +#pragma once + +#include "Node.h" + +class Char: public Node { +private: + char value; + +public: + Char(char v, location_t loc): Node(loc), value(v) {} + + char getValue() const { return value; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tchar; + } +}; diff --git a/src/CmpOp.cpp b/src/CmpOp.cpp index c200ed5..477045b 100644 --- a/src/CmpOp.cpp +++ b/src/CmpOp.cpp @@ -1,70 +1,73 @@ -#include "Header.h" +#include "CmpOp.h" +#include "FlexDependencies.h" +#include "Language_gen_y.hpp" -CmpOp::CmpOp (Node *l, int op, Node *r) : lexpn(l), rexpn(r) { +CmpOp::CmpOp (Node *l, int op, Node *r, location_t loc): Node(loc) { this->op = op; - node_children.reserve(2); - node_children.push_back(lexpn); - node_children.push_back(rexpn); + this->dt = tbool; + addChild(l); + addChild(r); } -Value *CmpOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *CmpOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { CmpInst::Predicate predicate; - Value *lexp = lexpn->generate(func, block, allocblock); - Value *rexp = rexpn->generate(func, block, allocblock); + Value *lexp = lexpn()->generateNewBlock(func, &block, allocblock); + Value *rexp = rexpn()->generateNewBlock(func, &block, allocblock); if (rexp == NULL || lexp == NULL) // can't generate values, error message emitted during generate. - return ConstantInt::get(Type::getInt1Ty(global_context), 1); // error recover + return ConstantInt::get(Type::getInt1Ty(global_context), 1); // error recovery - Type *tl = lexp->getType(); - Type *tr = rexp->getType(); + // it suffices to check one side, operands has been coerced + DataType edt = lexpn()->getDataType(); + bool isFloatCmp = buildTypes->isFloatDataType(edt); + bool isSignedCmp = buildTypes->isSignedDataType(edt); + bool isUnsignedCmp = buildTypes->isUnsignedDataType(edt); - bool canCompare = (tl->isIntegerTy() || tl->isFloatingPointTy()) && - (tr->isIntegerTy() || tr->isFloatingPointTy()); - if (!canCompare) { - yyerrorcpp("Can not compare " + getTypeName(tl) + " and " + - getTypeName(tr) + " types.", lexpn); - return ConstantInt::get(Type::getInt1Ty(global_context), 1); // error recover - } + if (buildTypes->isEnum(edt)) + isUnsignedCmp = true; + + const string op_error = "Invalid operator for comparison."; - bool isFloatPointCmp = true; - if (tl->isFloatingPointTy() && tr->isIntegerTy()) - rexp = Coercion::Convert(rexp, tl, block, rexpn); - else if (tl->isIntegerTy() && tr->isFloatingPointTy()) - lexp = Coercion::Convert(lexp, tr, block, lexpn); - else { - // left and right are integers - isFloatPointCmp = false; - unsigned tlbw = dyn_cast(tl)->getBitWidth(); - unsigned trbw = dyn_cast(tr)->getBitWidth(); - if (tlbw > trbw) - rexp = Coercion::Convert(rexp, tl, block, rexpn); - else if (tlbw < trbw) - lexp = Coercion::Convert(lexp, tr, block, lexpn); - } + if (isFloatCmp) { + switch (op) { + case EQ_OP: predicate = FCmpInst::FCMP_OEQ; break; + case NE_OP: predicate = FCmpInst::FCMP_ONE; break; + case GE_OP: predicate = FCmpInst::FCMP_OGE; break; + case LE_OP: predicate = FCmpInst::FCMP_OLE; break; + case GT_OP: predicate = FCmpInst::FCMP_OGT; break; + case LT_OP: predicate = FCmpInst::FCMP_OLT; break; + default: yyerrorcpp(op_error, lexpn()); break; + } + } else if (isSignedCmp) { + switch (op) { + case EQ_OP: predicate = FCmpInst::ICMP_EQ; break; + case NE_OP: predicate = FCmpInst::ICMP_NE; break; + case GE_OP: predicate = FCmpInst::ICMP_SGE; break; + case LE_OP: predicate = FCmpInst::ICMP_SLE; break; + case GT_OP: predicate = FCmpInst::ICMP_SGT; break; + case LT_OP: predicate = FCmpInst::ICMP_SLT; break; + default: yyerrorcpp(op_error, lexpn()); break; + } + } else if (isUnsignedCmp) { + switch (op) { + case EQ_OP: predicate = FCmpInst::ICMP_EQ; break; + case NE_OP: predicate = FCmpInst::ICMP_NE; break; + case GE_OP: predicate = FCmpInst::ICMP_UGE; break; + case LE_OP: predicate = FCmpInst::ICMP_ULE; break; + case GT_OP: predicate = FCmpInst::ICMP_UGT; break; + case LT_OP: predicate = FCmpInst::ICMP_ULT; break; + default: yyerrorcpp(op_error, lexpn()); break; + } + } else + yyerrorcpp(op_error, lexpn()); - if (rexp == NULL || lexp == NULL) // coercion not possible, error message during coercion - return ConstantInt::get(Type::getInt1Ty(global_context), 1); // error recover - - if (op == EQ_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_OEQ : ICmpInst::ICMP_EQ; - else if (op == NE_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_UNE : ICmpInst::ICMP_NE; - else if (op == GE_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_OGE : ICmpInst::ICMP_SGE; - else if (op == LE_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_OLE : ICmpInst::ICMP_SLE; - else if (op == GT_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_OGT : ICmpInst::ICMP_SGT; - else if (op == LT_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_OLT : ICmpInst::ICMP_SLT; + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + if (isFloatCmp) + return Builder->CreateFCmp(predicate, lexp, rexp, "cmpf"); else { - yyerrorcpp("Invalid predicate for comparison.", lexpn); - return NULL; + return Builder->CreateICmp(predicate, lexp, rexp, "cmpi"); } - - if (isFloatPointCmp) - return new FCmpInst(*block, predicate, lexp, rexp, "cmpf"); - else { - return new ICmpInst(*block, predicate, lexp, rexp, "cmpi"); - } -} - -void CmpOp::accept(Visitor& v) { - v.visit(*this); } diff --git a/src/CmpOp.h b/src/CmpOp.h index 013b2c6..a20a7a6 100644 --- a/src/CmpOp.h +++ b/src/CmpOp.h @@ -1,18 +1,23 @@ -#ifndef __CMPOP_H__ -#define __CMPOP_H__ +#pragma once + #include "Node.h" +#include "semantic/Visitor.h" class CmpOp: public Node { private: - Node *lexpn; - Node *rexpn; int op; + public: - CmpOp (Node *l, int op, Node *r); + CmpOp (Node *l, int op, Node *r, location_t loc); int getOperator() const { return op; }; - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; - + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + Node *lexpn() { + return node_children[0]; + } + Node *rexpn() { + return node_children[1]; + } + Node* accept(Visitor &v) override { + return v.visit(*this); + } }; - -#endif diff --git a/src/Coercion.cpp b/src/Coercion.cpp deleted file mode 100644 index 7c645ab..0000000 --- a/src/Coercion.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "Header.h" - -unsigned Coercion::GetFloatingPointBitwidth(Type *ty) { - switch (ty->getTypeID()) { - case Type::FloatTyID: - return 32; - case Type::DoubleTyID: - return 64; - case Type::X86_FP80TyID: - return 80; - case Type::PPC_FP128TyID: - case Type::FP128TyID: - return 128; - default: - return 0; - } -} - -Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocation *loc){ - - Value *r = v; - Type *ty = v->getType(); - - if (ty != destty){ - //Float to Integer - if (ty->isFloatingPointTy() && destty->isIntegerTy()){ - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getFPToSI(c, destty); - else - r = new FPToSIInst(v, destty, "fptosi", block); - yywarncpp("Float point converted to integer.", loc); - } - //Integer to Float - else if (destty->isFloatingPointTy() && ty->isIntegerTy()){ - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getSIToFP(c, destty); - else - r = new SIToFPInst(v, destty, "sitofp", block); - } - //Floating point to Floating point - else if (ty->isFloatingPointTy() && destty->isFloatingPointTy()) { - unsigned tybw = GetFloatingPointBitwidth(ty); - unsigned dtybw = GetFloatingPointBitwidth(destty); - if (dtybw > tybw) - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getFPExtend(c, destty); - else - r = new FPExtInst(v, destty, "fpext", block); - else if (dtybw < tybw) { - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getFPTrunc(c, destty); - else - r = new FPTruncInst(v, destty, "fptrunc", block); - yywarncpp("Float point value truncated.", loc); - } - } - //Generic ExtInt to Int - else if (destty->isIntegerTy() && ty->isIntegerTy()){ - unsigned wty = dyn_cast(ty)->getBitWidth(); - unsigned wdestty = dyn_cast(destty)->getBitWidth(); - if (wty > wdestty){ - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getTrunc(c, destty); - else - r = new TruncInst(v, destty, "trunc", block); - yywarncpp("Integer value truncated.", loc); - } - else if (wty < wdestty) { - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getSExt(c, destty); - else - r = new SExtInst(v, destty, "sext", block); - } - } - else if (!destty->isPointerTy()) { - yyerrorcpp("No coercion between " + getTypeName(ty) + " and " + - getTypeName(destty) + " implemented.", loc); - } - } - return r; - -} diff --git a/src/Coercion.h b/src/Coercion.h deleted file mode 100644 index 6fe4674..0000000 --- a/src/Coercion.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __COERCION_H__ -#define __COERCION_H__ - -class Coercion{ - public: - static Value *Convert(Value *v, Type *destty, BasicBlock *block, SourceLocation *loc); - static unsigned GetFloatingPointBitwidth(Type *ty); -}; - -#endif diff --git a/src/Colors.h b/src/Colors.h new file mode 100644 index 0000000..03b22a1 --- /dev/null +++ b/src/Colors.h @@ -0,0 +1,10 @@ + +#pragma once + +#define COLOR_RED "\x1b[31m" +#define COLOR_GREEN "\x1b[32m" +#define COLOR_YELLOW "\x1b[33m" +#define COLOR_BLUE "\x1b[34m" +#define COLOR_MAGENTA "\x1b[35m" +#define COLOR_CYAN "\x1b[36m" +#define COLOR_RESET "\x1b[0m" diff --git a/src/ConstructorCall.cpp b/src/ConstructorCall.cpp new file mode 100644 index 0000000..ae56f26 --- /dev/null +++ b/src/ConstructorCall.cpp @@ -0,0 +1,103 @@ + +#include "ConstructorCall.h" +#include "BackLLVM.h" +#include "Program.h" +#include "UserType.h" + +Value* ConstructorCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + if (dt == BuildTypes::undefinedType) + getDataType(); + + // alloc + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + GlobalVariable *gv = NULL; + + Value *var; + if (leftGEP) { + // init a previously set gep (e.g., array element) + var = leftGEP; + } else { + assert(leftValue && "leftValue or gep must be set."); + var = leftValue->getLLVMValue(func); + } + + if (var == NULL) { + // is a new left var + Type *vty = buildTypes->llvmType(dt); + if (buildTypes->isInterface(dt)) { + vty = PointerType::getUnqual(vty); + leftValue->setPointerToPointer(true); + } + Builder->SetInsertPoint(allocblock); + if (allocblock == global_alloc) { + //Constant *init = ConstantAggregateZero::get(buildTypes->llvmType(dt)); + PointerType *dtPointerTy = PointerType::getUnqual(buildTypes->llvmType(dt)); + Constant *init = ConstantPointerNull::get(dtPointerTy); + gv = new GlobalVariable(*mainmodule, vty, hasQualifier(qconst), + GlobalValue::ExternalLinkage, init, leftValue->getName()); + var = gv; + } else { + var = Builder->CreateAlloca(vty, dataAddrSpace, 0, + leftValue->getName()); + } + leftValue->setAlloca(var); + leftValue->setDataType(dt); + if (debug_info) { + if (allocblock != global_alloc) + RobDbgInfo.declareVar(leftValue, var, allocblock); + } + } + vector args; + args.push_back(var); + + // if calling a constructor of an interface, emit code to bind it + if (buildTypes->isInterface(dt)) { + Node *scope = leftValue->getScope(); + UserType *parent= dynamic_cast(scope); + const string toInjection = parent ? + parent->getName() + "." + leftValue->getName() : + leftValue->getName(); + + const string injectFuncName = "__get_injection_for_" + toInjection; + Node *funcNode = findSymbol(injectFuncName); + FunctionBase *funcDecl = dynamic_cast(funcNode); + if (!funcDecl) { + funcDecl = new FunctionDecl(dt, injectFuncName, new FunctionParams(), this->getLoc()); + funcDecl->setReturnIsPointer(true); + funcDecl->setScope(program); + funcDecl->setLocation(this); + funcDecl->generate(NULL, NULL, global_alloc); + funcDecl->setAttributes(new FunctionAttributes(fa_inline)); + program->addSymbol(funcDecl); + } + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(allocblock == global_alloc ? global_alloc : block); + return Builder->CreateCall(funcDecl->getLLVMFunction()); + + } else { + // call the init constructor + + // find the user type + Node *type = findSymbol(name); + if (!type) + return NULL; + + Node *fsymbol = type->findMember("init"); + assert(fsymbol && "the init method for the type must exists"); + + FunctionBase *initfunc = dynamic_cast(fsymbol); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(allocblock == global_alloc ? global_alloc : block); + + if (initfunc->needsParent()) { + Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); + Value *ptr = Builder->CreateLoad(PointerType::getUnqual(thisTy), func->getThisArg(), "derefthis"); + args.push_back(ptr); + } + + CallInst *c = Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); + return NULL; // init doesn't return; is a call to a void func + } +} diff --git a/src/ConstructorCall.h b/src/ConstructorCall.h new file mode 100644 index 0000000..c6f964c --- /dev/null +++ b/src/ConstructorCall.h @@ -0,0 +1,31 @@ + +#pragma once + +#include "Node.h" +#include "FunctionImpl.h" +#include "MemCopy.h" + +class ConstructorCall: public Constructor { +protected: + string name; +public: + ConstructorCall(const string tyName, location_t loc): Constructor(loc), name(tyName) { } + + virtual Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + DataType getDataType() override { + if (dt == BuildTypes::undefinedType) + dt = buildTypes->getType(name); + return dt; + } + + virtual map const& getSymbols() override { + getDataType(); + if (dt != BuildTypes::undefinedType) { + auto symbol = findSymbol(name); + if (symbol) + return symbol->getSymbols(); + } + return symbols; + } +}; diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp new file mode 100644 index 0000000..3caea4f --- /dev/null +++ b/src/DebugInfo.cpp @@ -0,0 +1,92 @@ +#include "HeaderGlobals.h" +#include "SourceLocation.h" +#include "Node.h" +#include "BackLLVM.h" + +void DebugInfo::emitLocation(SourceLocation *s) { + if (!debug_info || !s || s->getLineNo() == 0) + return; + + DIScope *scope; + if (scopes.empty()) + scope = cunit; + else + scope = scopes.back(); + + Builder->SetCurrentDebugLocation(DILocation::get( + scope->getContext(), s->getLineNo(), s->getColNo(), scope)); +} + +void DebugInfo::push_scope(DIScope *s) { + scopes.push_back(s); +} + +void DebugInfo::push_file(DIFile *f) { + files.push_back(f); +} + +void DebugInfo::pop_scope() { + scopes.pop_back(); +} + +void DebugInfo::pop_file() { + files.pop_back(); +} + +DIFile* DebugInfo::currFile() { + if (!debug_info) + return NULL; + return files.back(); +} + +DIScope* DebugInfo::currScope() { + if (!debug_info) + return NULL; + return scopes.back(); +} + +DIExpression *DebugInfo::getFixedOffsetExpression() { + // TODO: For some unknown reason (to me), we need to offset + // the var declaration by one to see its actual value + if (currentTarget().backend == rb_avr) { + SmallVector Ops; + DIExpression *ex = DBuilder->createExpression(); + ex->appendOffset(Ops, 1); + return DIExpression::prependOpcodes(ex, Ops, false); + } else { + return DBuilder->createExpression(); + } +} + +void DebugInfo::declareVar(Node *n, Value *alloc, BasicBlock *allocblock) { + DataType dt = n->getDataType(); + llvm::DIType *dty = buildTypes->diType(dt); + if (n->isPointerToPointer()) + dty = buildTypes->diPointerType(dt); + + if (n->hasQualifier(qvolatile)) { + dty = DBuilder->createQualifiedType(dwarf::DW_TAG_volatile_type, dty); + } + auto sp = RobDbgInfo.currScope(); + auto funit = RobDbgInfo.currFile(); + DILocalVariable *d = DBuilder->createAutoVariable( + sp, n->getName(), funit, n->getLineNo(), dty); + + DBuilder->insertDeclare(alloc, d, getFixedOffsetExpression(), + DILocation::get(sp->getContext(), n->getLineNo(), n->getColNo(), sp), allocblock); +} + +void DebugInfo::declareGlobalVar(Node *n, GlobalVariable *gv, BasicBlock *allocblock) { + DataType dt = n->getDataType(); + llvm::DIType *dty = buildTypes->diType(dt); + if (n->isPointerToPointer()) + dty = buildTypes->diPointerType(dt); + if (n->hasQualifier(qvolatile)) { + dty = DBuilder->createQualifiedType(dwarf::DW_TAG_volatile_type, dty); + } + auto sp = RobDbgInfo.currScope(); + auto funit = RobDbgInfo.currFile(); + auto *d = DBuilder->createGlobalVariableExpression(sp, gv->getName(), "", + funit, n->getLineNo(), dty, false); + gv->addDebugInfo(d); +} \ No newline at end of file diff --git a/src/Delay.cpp b/src/Delay.cpp deleted file mode 100644 index ea61c52..0000000 --- a/src/Delay.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "Header.h" - -Delay::Delay(Node *mseg) : ms(mseg) { - node_children.reserve(1); - node_children.push_back(ms); -} - -Value *Delay::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - Value *msv = ms->generate(func, block, allocblock); - Value *msv32 = new SExtInst(msv, Type::getInt32Ty(global_context), "conv", block); - - vector args; - args.push_back(msv32); - ArrayRef argsRef(args); - return CallInst::Create(delay, argsRef, "", block); -} - -void Delay::accept(Visitor& v) { - v.visit(*this); -} - diff --git a/src/Delay.h b/src/Delay.h deleted file mode 100644 index fccc7d1..0000000 --- a/src/Delay.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __DELAY_H__ -#define __DELAY_H__ -#include "Node.h" -#include "Int32.h" - -class Delay: public Node { -private: - Node *ms; -public: - Delay (Node *mseg); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; - -}; - -#endif diff --git a/src/Dispatch.cpp b/src/Dispatch.cpp new file mode 100644 index 0000000..090cda2 --- /dev/null +++ b/src/Dispatch.cpp @@ -0,0 +1,137 @@ + +#include "Dispatch.h" +#include "Identifier.h" +#include "Interface.h" +#include "FunctionImpl.h" +#include "BackLLVM.h" +#include "Program.h" +#include "UserType.h" +#include "Scanner.h" + +void Dispatch::addDataTypeImplementation(DataType base, DataType impl) { + //errs() << "addDataTypeImplementation: " << buildTypes->name(base) << " -> " << buildTypes->name(impl) << "\n"; + set& impls = dispatchHash[base]; + impls.insert(impl); +} + +int Dispatch::getImplementationCount(DataType intf) { + if (dispatchHash.find(intf) != dispatchHash.end()) + return dispatchHash[intf].size(); + return 0; +} + +void Dispatch::addIntfInvocation(DataType intf) { + intfsInvoked.insert(intf); +} + +void Dispatch::generateDispatchFunctions(Node *scope) { + + /* for each base type, generates a function: + void base_type.method(this) { + switch (this.id) { + case x: xtype->method(this); + case y: ytype->method(this); + ... + } + } + */ + + for(auto& [baseType, impls] : dispatchHash) { + string baseTypeName = buildTypes->name(baseType); + Identifier baseTypeId(baseTypeName, scope->getLoc()); + Node *baseTypeNode = baseTypeId.getSymbol(scope); + Interface *baseTypeTy = dynamic_cast(baseTypeNode); + + for(const auto & [method, function] : baseTypeTy->getSymbols()) { + if (FunctionDecl *functionDecl = dynamic_cast(function)) { + + // if the function is declared in this module, FunctionCall already create it + string dispatchFuncName = baseTypeName + ":" + method; + Function *dispatchFunc = mainmodule->getFunction(dispatchFuncName); + if (!dispatchFunc) { + dispatchFunc = Function::Create(functionDecl->getLLVMFunction()->getFunctionType(), + Function::ExternalLinkage, codeAddrSpace, dispatchFuncName, mainmodule); + dispatchFunc->setCallingConv(CallingConv::C); + if (impls.size() == 1) + dispatchFunc->addFnAttr(Attribute::AlwaysInline); + } + + auto fblock = BasicBlock::Create(global_context, "", dispatchFunc); + Builder->SetInsertPoint(fblock); + + if (impls.size() == 0) { + // provide an empty implementation for the dispatcher + + Type *retTy = dispatchFunc->getReturnType(); + if (retTy->isVoidTy()) { + Builder->CreateRetVoid(); + } else { + // this returns zero for integers and floats + Builder->CreateRet(Constant::getNullValue(retTy)); + } + continue; + } + + // the first field of arg this is the object type id + Type *thisTy = buildTypes->llvmType(functionDecl->getThisArgDt()); + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); + Value *indexList[2] = {zero, zero}; + Type *idType = Type::getInt8Ty(global_context); + Value *idValue = Builder->CreateLoad(idType, functionDecl->getThisArg(), "typeid"); + + SwitchInst *switchi = Builder->CreateSwitch(idValue, NULL, impls.size()); + + bool hasDefault = false; + for(DataType implDt : impls) { + auto implDtBlock = BasicBlock::Create(global_context, "", dispatchFunc); + Builder->SetInsertPoint(implDtBlock); + + vector args; + for(auto& arg : dispatchFunc->args()) { + args.push_back(&arg); + } + + string destTypeName = buildTypes->name(implDt); + string destFuncName = destTypeName + ":" + method; + Function *destFunc = mainmodule->getFunction(destFuncName); + + if (!destFunc) { + yyerrorcpp(string_format("Function %s not found while generating dispatch.", + destFuncName.c_str()), scope); + continue; + } + + Value *call = Builder->CreateCall(destFunc, args); + if (call->getType()->isVoidTy()) + Builder->CreateRetVoid(); + else + Builder->CreateRet(call); + + // add switch case + Builder->SetInsertPoint(fblock); + if (!hasDefault && destTypeName.find("void_") == string::npos) { + //TODO: The default should halt the MCU? For security reasons, memory corruption, control flow hijack. + switchi->setDefaultDest(implDtBlock); + hasDefault = true; + } else { + UserType *type = dynamic_cast(program->findSymbol(destTypeName)); + assert(type && "UserType should exists."); + int concreteId = type->getConcreteId(); + if (concreteId != -1) { + ConstantInt *implDtId = ConstantInt::get(Type::getInt8Ty(global_context), concreteId, true); + switchi->addCase(implDtId, implDtBlock); + } + } + } + } + } + } +} + +void Dispatch::notifyInterface(DataType intf) { + dispatchHash[intf]; +} + +bool Dispatch::isIntfInvoked(DataType intf) { + return (intfsInvoked.find(intf) != intfsInvoked.end()); +} \ No newline at end of file diff --git a/src/Dispatch.h b/src/Dispatch.h new file mode 100644 index 0000000..bec3c4e --- /dev/null +++ b/src/Dispatch.h @@ -0,0 +1,24 @@ + +#pragma once + +#include +#include +#include "BuildTypes.h" + +//using namespace std; + +class Dispatch { +protected: + map> dispatchHash; + set intfsInvoked; + set possibleObjectsInvoked; + +public: + void addDataTypeImplementation(DataType base, DataType impl); + void addIntfInvocation(DataType intf); + void addNodeInvocation(Node *node); + void generateDispatchFunctions(Node *scope); + void notifyInterface(DataType intf); + int getImplementationCount(DataType intf); + bool isIntfInvoked(DataType intf); +}; diff --git a/src/Double.cpp b/src/Double.cpp index 442f440..9e869b8 100644 --- a/src/Double.cpp +++ b/src/Double.cpp @@ -1,6 +1,7 @@ -#include "Header.h" -Value *Double::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +#include "Double.h" + +Value *Double::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return ConstantFP::get(Type::getDoubleTy(global_context), number); } diff --git a/src/Double.h b/src/Double.h index 4c26290..42b1f77 100644 --- a/src/Double.h +++ b/src/Double.h @@ -1,19 +1,18 @@ -#ifndef __DOUBLE_H__ -#define __DOUBLE_H__ + +#pragma once + #include "Node.h" class Double: public Node { private: - float number; + double number; public: - Double(float n): number(n) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + Double(double n, location_t loc): Node(loc), number(n) {} + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual bool isConstExpr() override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getDoubleTy(global_context); + virtual DataType getDataType() override { + return tdouble; } }; - -#endif diff --git a/src/Enum.cpp b/src/Enum.cpp new file mode 100644 index 0000000..18fb8a0 --- /dev/null +++ b/src/Enum.cpp @@ -0,0 +1,65 @@ + +#include "Enum.h" +#include "Int8.h" +#include "NamedConst.h" + +void Enum::createDataType() { + if (children().size() > 256) { + yyerrorcpp("Maximum number of elements for enum type was reached (256).", this); + return; + } + + dt = buildTypes->getType(name); + if (dt != BuildTypes::undefinedType && buildTypes->isDefined(dt)) { + yyerrorcpp("Type " + name + " alread defined.", this); + yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); + return; + } + + /* set enum items values + * enum A {B=1, C, D, E, F=10, G, H=127, I} => C=2, D=3 ... G=11 ... I=-128 + * enum B {C=3, D=2, E, F} => E=4, F=5 + */ + uint8_t v = 0; + map values; + for(Node *n : children()) { + NamedConst *nc = (NamedConst*)n; + Node *nv = nc->getValue(); + if (nv) { + if (Int8 *i8 = dynamic_cast(nv)) + v = i8->getNumber(); + else if (UInt8 *ui8 = dynamic_cast(nv)) + v = ui8->getNumber(); + + if (values.count(v) == 1) { + yyerrorcpp(string_format("Value %d alread taken for %s.", + v, values[v]->getName().c_str()), nc); + } else { + values[v] = nc; + } + } else { + while (values.count(v) == 1) + v++; + nc->setValue(new UInt8(v, nc->getLoc())); + values[v] = nc; + } + } + + dt = buildTypes->addDataType(this, buildTypes->llvmType(tint8), + buildTypes->bitWidth(tint8), true); + + for(Node *n : children()) { + n->setDataType(dt); + } +} + +Value* Enum::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + getDataType(); + return NULL; +} + +DataType Enum::getDataType() { + if (dt == BuildTypes::undefinedType) + createDataType(); + return dt; +} \ No newline at end of file diff --git a/src/Enum.h b/src/Enum.h new file mode 100644 index 0000000..d3d54be --- /dev/null +++ b/src/Enum.h @@ -0,0 +1,23 @@ + +#pragma once + +#include "Node.h" +#include "semantic/Visitor.h" + +class Enum : public NamedNode { +private: + void createDataType(); + +public: + Enum(const string& name, vector &&items, location_t loc): + NamedNode(name, std::move(items), loc) { + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual DataType getDataType() override; + + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } +}; diff --git a/src/FlexDependencies.h b/src/FlexDependencies.h new file mode 100644 index 0000000..459263e --- /dev/null +++ b/src/FlexDependencies.h @@ -0,0 +1,31 @@ + +#pragma once + +#include + +#include +#include +using namespace std; + +class Node; +class Stmts; +class ArrayElements; +class MatrixElements; +class FunctionParams; +class ParamsCall; +class Structure; +class ArrayElement; +class MatrixElement; +class Variable; +class Field; + +#include "Colors.h" +#include "SourceLocation.h" +#include "FunctionAttributes.h" + +typedef void* yyscan_t; + +#ifdef __MINGW64__ +char* strndup(const char *src, size_t size); +#endif + diff --git a/src/FlipOp.cpp b/src/FlipOp.cpp index 6651185..69315f0 100644 --- a/src/FlipOp.cpp +++ b/src/FlipOp.cpp @@ -1,27 +1,22 @@ -#include "Header.h" +#include "FlipOp.h" -FlipOp::FlipOp(Node *value) : value(value) { - this->node_children.reserve(1); - this->node_children.push_back(value); +FlipOp::FlipOp(Node *value) : Node(value->getLoc()), value(value) { + this->addChild(value); }; -Value *FlipOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *FlipOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { // generate code to produce the value to flip - Value *exprv = value->generate(func, block, allocblock); + Value *exprv = value->generateNewBlock(func, &block, allocblock); if (exprv == NULL) return NULL; if (Constant *c = dyn_cast(exprv)) - return ConstantExpr::getNeg(c); + return ConstantExpr::getNot(c); else return BinaryOperator::Create(Instruction::Xor, exprv, Constant::getAllOnesValue(exprv->getType()), "neg", block); } -void FlipOp::accept(Visitor& v) { - v.visit(*this); -} - -bool FlipOp::isConstExpr(BasicBlock *block, BasicBlock *allocblock) { - return value->isConstExpr(block, allocblock); +bool FlipOp::isConstExpr() { + return value->isConstExpr(); } diff --git a/src/FlipOp.h b/src/FlipOp.h index 32c4b24..565a90f 100644 --- a/src/FlipOp.h +++ b/src/FlipOp.h @@ -7,18 +7,17 @@ class FlipOp: public Node { private: Node *value; + public: FlipOp(Node *value); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - - virtual void accept(Visitor &v) override; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return value->getLLVMResultType(block, allocblock); + virtual DataType getDataType() override { + return value->getDataType(); } - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; + virtual bool isConstExpr() override; }; #endif diff --git a/src/Float.cpp b/src/Float.cpp index c511871..1705876 100644 --- a/src/Float.cpp +++ b/src/Float.cpp @@ -1,6 +1,7 @@ -#include "Header.h" -Value *Float::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +#include "Float.h" + +Value *Float::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return ConstantFP::get(Type::getFloatTy(global_context), number); } diff --git a/src/Float.h b/src/Float.h index 74fc342..2f1c19e 100644 --- a/src/Float.h +++ b/src/Float.h @@ -1,19 +1,19 @@ -#ifndef __FLOAT_H__ -#define __FLOAT_H__ + +#pragma once + #include "Node.h" class Float: public Node { private: float number; public: - Float(float n): number(n) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + Float(float n, location_t loc): Node(loc), number(n) {} + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual bool isConstExpr() override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getFloatTy(global_context); + + virtual DataType getDataType() override { + return tfloat; } }; - -#endif diff --git a/src/Float128.cpp b/src/Float128.cpp index e412399..4c946af 100644 --- a/src/Float128.cpp +++ b/src/Float128.cpp @@ -1,6 +1,7 @@ -#include "Header.h" -Value *Float128::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +#include "Float128.h" + +Value *Float128::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return ConstantFP::get(Type::getFP128Ty(global_context), number); } diff --git a/src/Float128.h b/src/Float128.h index bb87b32..983de29 100644 --- a/src/Float128.h +++ b/src/Float128.h @@ -1,21 +1,20 @@ -#ifndef __FLOAT128_H__ -#define __FLOAT128_H__ +#pragma once + #include "Node.h" class Float128: public Node { private: - float number; + long double number; public: - Float128(float n): number(n) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + Float128(long double n, location_t loc): Node(loc), number(n) {} + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + virtual bool isConstExpr() override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getFP128Ty(global_context); + virtual DataType getDataType() override { + return tldouble; } }; -#endif diff --git a/src/FunctionAttributes.h b/src/FunctionAttributes.h new file mode 100644 index 0000000..ea7ad80 --- /dev/null +++ b/src/FunctionAttributes.h @@ -0,0 +1,38 @@ + +#pragma once + +enum FunctionAttributeType { + fa_weak, + fa_inline, + fa_noinline, + fa_section, + fa_naked, + fa_signal, + fa_debugonly, + fa_noopt, +}; + +typedef pair FunctionAttribute; + +class FunctionAttributes { +protected: + map attributes; +public: + FunctionAttributes() {} + FunctionAttributes(FunctionAttributeType attr, const string& value = "") { + addAttribute(attr, value); + } + void addAttribute(FunctionAttributeType attr, const string& value = "") { + attributes[attr] = value; + } + void addAttribute(FunctionAttribute *attr) { + attributes[attr->first] = attr->second; + delete attr; + } + const map& getAttributes() { + return attributes; + } + bool hasAttribute(FunctionAttributeType attr) { + return attributes.find(attr) != attributes.end(); + } +}; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 66542c2..0ac21b4 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -1,39 +1,206 @@ -#include "Header.h" - -Type* FunctionCall::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { - auto symbol = search_symbol(name); - if (symbol) { - Function *cfunc = dyn_cast(symbol->value); - if (cfunc) - return cfunc->getReturnType(); - } - return NULL; +#include "FunctionCall.h" +#include "BuildTypes.h" +#include "FunctionDecl.h" +#include "FunctionImpl.h" +#include "HeaderGlobals.h" +#include "Load.h" +#include "BackLLVM.h" +#include "UserType.h" +#include "Program.h" +#include "Interface.h" +#include "semantic/PropagateTypes.h" +#include "semantic/Visitor.h" + +extern Program *program; + +DataType FunctionCall::getDataType() { + + if (dt == BuildTypes::undefinedType) { + // is a constructor? this can occur while running PropagateTypes. + dt = buildTypes->getType(ident.getFullName()); + if (node_children.size() <= 1 && dt != BuildTypes::undefinedType) { + return dt; + } + + if (!symbol) + symbol = ident.getSymbol(getScope()); + + if (symbol) + dt = symbol->getDataType(); + } + return dt; } -Value *FunctionCall::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - auto symbol = search_symbol(name); - if (symbol == NULL) { - yyerrorcpp("Function " + name + " not defined.", this); - return NULL; - } - - Function *cfunc = dyn_cast(symbol->value); - if (cfunc == NULL) { - yyerrorcpp("Symbol " + name + " is not a function.", this); - return NULL; - } - - vector args; - for (int i = 0; i < parameters->getNumParams(); i++){ - Value *valor = parameters->getParamElement(i)->generate(func, block, allocblock); - args.push_back(valor); - } - ArrayRef argsRef(args); - - bool isVoidReturn = cfunc->getReturnType()->isVoidTy(); - if (isVoidReturn) - return CallInst::Create(cfunc, argsRef, "", block); - else - return CallInst::Create(cfunc, argsRef, "fc", block); +Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + RobDbgInfo.emitLocation(this); + string name = ident.getFullName(); + + if (!symbol) + symbol = ident.getSymbol(getScope(), false); + + if (symbol == NULL) { + yyerrorcpp("Function " + name + " not defined.", this); + return NULL; + } + + FunctionBase *fsymbol = dynamic_cast(symbol); + if (fsymbol == NULL) { + yyerrorcpp("Symbol " + name + " is not a function.", this); + return NULL; + } else if (ident.isComplex()) { + Node *stem = ident.getStem().getSymbol(getScope()); + if (Interface *intf = dynamic_cast(stem)) { + yyerrorcpp("Can not call an interface function.", this); + return NULL; + } + } + + if (fsymbol->getNumCodedParams() != node_children.size()) { + yyerrorcpp(string_format("Function %s has %d argument(s) but was called with %d.", + name.c_str(), fsymbol->getNumCodedParams(), + node_children.size()), this); + yywarncpp("The function declaration is here.", symbol); + return NULL; + } + + // skip calling onlydebug functions when not debugging + if (!debug_info && fsymbol->getAttributes()->hasAttribute(fa_debugonly)) + return NULL; + + dt = fsymbol->getDataType(); + + Node *stemSymbol = NULL; + Value *stem = func->getThisArg(); + DataType stemdt = func->getThisArgDt(); + + Builder->SetInsertPoint(block); + if (ident.isComplex()) { + Identifier istem = ident.getStem(); + stemSymbol = istem.getSymbol(getScope()); + stemdt = stemSymbol->getDataType(); + stem = Load::getRecursiveField(istem, getScope(), func); + } + + vector args; + vector dataTypes; + int paramId = 0; + for (Node *param : node_children) { + DataType call_dt = param->getDataType(); + DataType def_dt = fsymbol->getParameters().getParamType(paramId); + string argName = fsymbol->getParameters().getParamName(paramId); + + Value *valor = param->generateNewBlock(func, &block, allocblock); + if (!valor) { + yyerrorcpp(string_format("The value for argument %s is undefined.", argName.c_str()), param); + return NULL; + } + Builder->SetInsertPoint(block); + + if (buildTypes->isArrayOrMatrix(call_dt)) { + // we pass the address of the first element + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); + Value *indexList[2] = {zero, zero}; + Value *ptr = Builder->CreateGEP(param->getLLVMType(), valor, ArrayRef(indexList), "gep"); + valor = ptr; + } + + args.insert(args.begin() + paramId, valor); + dataTypes.insert(dataTypes.begin() + paramId, def_dt); + + // add a size parameter after each array, or .rows and .cols for matrixes + if (buildTypes->isArrayOrMatrix(call_dt)) { + vector params; + if (buildTypes->isArray(call_dt)) + params.push_back(".size"); + else if (buildTypes->isMatrix(call_dt)) { + params.push_back(".rows"); + params.push_back(".cols"); + } + + for(const string& p: params) { + Node *coerced; + Value *value = NULL; + Node *size = param->findMember("size"); + if (size) { + coerced = PropagateTypes::coerceTo(size, tint32u); + value = coerced->generateNewBlock(func, &block, allocblock); + } + if (!value) { + string pname = param->getName() + p; + Load ld(Identifier(pname, param->getLoc())); + ld.setScope(func); + coerced = PropagateTypes::coerceTo(&ld, tint32u); + value = coerced->generateNewBlock(func, &block, allocblock); + } + assert(value != NULL && "must pass the array size."); + args.push_back(value); + dataTypes.push_back(coerced->getDataType()); + } + } + + paramId++; + } + + // this parameter + if (stemSymbol) { + args.push_back(stem); + dataTypes.push_back(stemSymbol->getDataType()); + } else if (fsymbol->getThisArgDt() != BuildTypes::undefinedType) { + // calling a function of the type itself, without stem + Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); + Value *ptr = Builder->CreateLoad(PointerType::getUnqual(thisTy), func->getThisArg(), "derefthis"); + args.push_back(ptr); + dataTypes.push_back(fsymbol->getThisArgDt()); + } + + ArrayRef argsRef(args); + + Builder->SetInsertPoint(allocblock); + Value *vfunc = symbol->getLLVMValue(func); + if (!vfunc) { + return NULL; //FIXME:?? + } + Function *cfunc = dyn_cast(vfunc); + + // symbol->getLLVMValue above can emit another location (preGenerate of the + // function being called), so we emit location again + RobDbgInfo.emitLocation(this); + + // calling an interface function; will use the dispatcher + if (stemSymbol && buildTypes->isInterface(stemSymbol->getDataType())) { + string func_full_name; + + func_full_name = buildTypes->name(stemSymbol->getDataType()); + func_full_name.append(":"); + func_full_name.append(ident.getLastName()); + + Function *intf_cfunc = mainmodule->getFunction(func_full_name); + if (!intf_cfunc) { + intf_cfunc = Function::Create(cfunc->getFunctionType(), Function::ExternalLinkage, + codeAddrSpace, func_full_name, mainmodule); + intf_cfunc->setCallingConv(CallingConv::C); + intf_cfunc->addFnAttr(Attribute::AlwaysInline); + } + cfunc = intf_cfunc; + } + + Builder->SetInsertPoint(block); + CallInst *call = Builder->CreateCall(cfunc, argsRef); + + // set signedness + if (cfunc->hasRetAttribute(Attribute::ZExt)) + call->addRetAttr(Attribute::ZExt); + int i = 0; + for(DataType adt : dataTypes) { + if (buildTypes->isUnsignedDataType(adt)) + call->addParamAttr(i, Attribute::ZExt); + i++; + } + + return call; } +Node* FunctionCall::accept(Visitor& v) { + return v.visit(*this); +} diff --git a/src/FunctionCall.h b/src/FunctionCall.h index 304eeb7..0533aa8 100644 --- a/src/FunctionCall.h +++ b/src/FunctionCall.h @@ -1,19 +1,48 @@ -#ifndef __FUNCTIONCALL_H__ -#define __FUNCTIONCALL_H__ + +#pragma once + #include "Node.h" +#include "ParamsCall.h" +#include "Identifier.h" +#include "Variable.h" class FunctionCall: public Node { private: - string name; - ParamsCall *parameters; + Identifier ident; + Node *symbol = NULL; + Variable *leftValue = NULL; + public: - FunctionCall(string name, ParamsCall *pc) { - this->name = name; - this->parameters = pc; + FunctionCall(const string& name, ParamsCall *pc, location_t loc): Node(loc), ident(name, loc) { + node_children.reserve(pc->getNumParams()); + node_children.insert(end(node_children), pc->getParameters().begin(), + pc->getParameters().end()); + delete pc; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - Type* getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override; -}; + virtual DataType getDataType() override; + + virtual void setLeftValue(Variable *symbol) override { + leftValue = symbol; + } + + std::vector& getParameters() { + return node_children; + } -#endif + Node* accept(Visitor& v) override; + + const string getName() const override { + return ident.getFullName(); + } + + Identifier& getIdent() { + return ident; + } + + void changeIdentifier(const string& id) { + ident.changeIdentifier(id); + } +}; diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 0c436b1..cfc6b05 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -1,66 +1,180 @@ -#include "Header.h" -Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) { - auto sym = search_symbol(name); - if (sym != NULL) { +#include "FunctionDecl.h" +#include "BackLLVM.h" +#include "FunctionAttributes.h" +#include "Array.h" +#include "Matrix.h" + +void FunctionBase::addThisArgument(DataType dt) { + thisArgDt = dt; + Variable *fp = new Variable("_this", dt, this->getLoc()); + fp->setScope(this); + parameters->append(fp); + symbols[fp->getName()] = fp; +} + +bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { + bool valid = true; + Type *xtype = buildTypes->llvmType(dt); + if (!xtype) { + yyerrorcpp(string_format("Type %s is not defined.", buildTypes->name(dt)), this); + valid = false; + } + for (int i = 0; i < parameters->getParameters().size(); i++) { + DataType dt = parameters->getParamType(i); + Type *atype = buildTypes->llvmType(dt); + if (!atype) { + yyerrorcpp(string_format("Type %s for argument %s is not defined.", + buildTypes->name(dt), parameters->getParamName(i).c_str()), this); + valid = false; + } else { + if (buildTypes->isComplex(dt) || buildTypes->isArrayOrMatrix(dt)) { + atype = PointerType::getUnqual(atype); + } + argsty.push_back(atype); + } + } + return valid; +} + +void FunctionBase::addParentArgument(DataType dt) { + parentArgDt = dt; + Variable *fp = new Variable("_parent", dt, this->getLoc()); + fp->setScope(this); + parameters->append(fp); + symbols[fp->getName()] = fp; +} + +void FunctionBase::addPseudoParameters() { + // add a size parameter after each array, or .rows and .cols for matrixes + std::vector const& vparams = this->parameters->getParameters(); + for (int i = 0; i < vparams.size(); ++i) { + Variable *p = vparams[i]; + + ParamArray *paramArray = dynamic_cast(p); + ParamMatrix *paramMatrix = dynamic_cast(p); + + if (paramArray || paramMatrix) { + vector pseudos; + if (paramMatrix) { + pseudos.push_back("rows"); + pseudos.push_back("cols"); + } else if (paramArray) + pseudos.push_back("size"); + + for(const string& s: pseudos) { + //TODO: There is something better than fix this to Int32? Fix here and in FunctionCall::generate + string spname = p->getName() + "." + s; + Variable *sp = new Variable(spname, tint32u, p->getLoc()); + sp->setPseudoVar(true); + this->parameters->append(sp); + + // add a pseudo symbol to resolve to pname.s + p->addSymbol(s, sp); + } + + // ParamMatrix need to know the number of cols to compute element indexes + if (paramMatrix) { + paramMatrix->addSymbol("cols", vparams.back()); + } + } + } +} + +void FunctionBase::addFunctionAttributes(Function *func) { + + //func->addFnAttr(Attribute::MinSize); + func->addFnAttr("target-cpu", currentTarget().cpu); + func->addFnAttr("frame-pointer", "all"); + func->addFnAttr("stack-protector-buffer-size", "8"); + + if (!attributes) + return; + + for(auto &[attr, value] : attributes->getAttributes()) { + switch (attr) { + case fa_weak: + func->setLinkage(GlobalValue::WeakAnyLinkage); + break; + case fa_inline: + func->addFnAttr(Attribute::AlwaysInline); + break; + case fa_noinline: + func->addFnAttr(Attribute::NoInline); + break; + case fa_section: + func->setSection(value); + break; + case fa_signal: + func->addFnAttr("signal"); + break; + case fa_naked: + func->addFnAttr(Attribute::Naked); + func->addFnAttr(Attribute::NoInline); + break; + case fa_noopt: + func->addFnAttr(Attribute::OptimizeNone); + func->addFnAttr(Attribute::NoInline); + break; + default: + break; + } + } +} + +Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocblock) { + + if (func) + return func; + + Node *symbol = findSymbol(name); + if (symbol != NULL && symbol != this) { yyerrorcpp("Function/symbol " + name + " already defined.", this); - yyerrorcpp(name + " was first defined here.", sym); + yyerrorcpp(name + " was first defined here.", symbol); return NULL; } std::vector arg_types; - if (parameters->getNumParams() != 0) - for (int i = 0; i < parameters->getNumParams(); i++) - arg_types.push_back(parameters->getParamType(i)); + if (!validateAndGetArgsTypes(arg_types)) + return NULL; + + Type *xtype = buildTypes->llvmType(dt); + if (returnIsPointer) + xtype = PointerType::getUnqual(xtype); - Type *xtype = robTollvmDataType[tipo]; FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); + Function *nfunc = Function::Create(ftype, linkage, codeAddrSpace, getFinalName(), mainmodule); + nfunc->setCallingConv(CallingConv::C); + addFunctionAttributes(nfunc); - Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, 0, name, mainmodule); - nfunc->setDSOLocal(true); - llvm::AttrBuilder attrs(global_context); - attrs.addAttribute(llvm::Attribute::MinSize); - //attrs.addAttribute("stack-protector-buffer-size", llvm::utostr(8)); - //attrs.addAttribute("frame-pointer", "all"); - //attrs.addAttribute("no-trapping-math", "true"); - nfunc->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); - - tabelasym[allocblock][name] = new RobSymbol(nfunc); - - BasicBlock *falloc = BasicBlock::Create(global_context, "entry", nfunc); - BasicBlock *fblock = BasicBlock::Create(global_context, "body", nfunc); + if (buildTypes->isUnsignedDataType(dt)) + nfunc->addRetAttr(Attribute::ZExt); + unsigned Idx = 0; - for (auto &Arg : nfunc->args()) - { - const char *argname = parameters->getParamElement(Idx); - Arg.setName(argname); - //Value *valor = search_symbol(argname, fblock, fblock); - AllocaInst* variable = new AllocaInst(parameters->getParamType(Idx), 0, argname, falloc); - tabelasym[falloc][argname] = new RobSymbol(variable); - StoreInst *val = new StoreInst(&Arg, variable, false, fblock); - Idx++; - } - nfunc->setCallingConv(CallingConv::C); + for (auto &Arg : nfunc->args()) { + Variable *fp = parameters->getParameters()[Idx]; + DataType ptype = fp->getDataType(); + + if (buildTypes->isUnsignedDataType(ptype)) + Arg.addAttr(Attribute::ZExt); - Value *last_block = stmts->generate(nfunc, fblock, falloc); - if (!last_block) - last_block = fblock; - - // prevent mallformed block at the end without proper return instruction - if (last_block && last_block->getValueID() == Value::BasicBlockVal) { - BasicBlock *lb = (BasicBlock*)last_block; - if (lb->getTerminator() == NULL) { - if (!xtype->isVoidTy()) { - Value *ret = ConstantInt::get(Type::getInt8Ty(global_context), 0); - ret = Coercion::Convert(ret, xtype, lb, this); - ReturnInst::Create(global_context, ret, lb); - } else - ReturnInst::Create(global_context, NULL, lb); + const string& argname = fp->getName(); + if (argname == "_this") { + thisArg = &Arg; + } else if (argname == "_parent") { + parentArg = &Arg; } + + Idx++; } - BranchInst::Create(fblock, falloc); + func = nfunc; + return func; +} - return nfunc; +Value* FunctionDecl::getLLVMValue(Node *, FunctionImpl *) { + if (!func) + generate(NULL, NULL, global_alloc); + return func; } diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 59b8226..9837686 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -1,28 +1,154 @@ -#ifndef __FUNCTIONDECL_H__ -#define __FUNCTIONDECL_H__ +#pragma once +#include "BuildTypes.h" #include "Node.h" +#include "FunctionParams.h" +#include "FunctionAttributes.h" -class FunctionDecl: public Node { -private: - Node *stmts; - LanguageDataType tipo; - string name; +class FunctionBase: public NamedNode { +protected: FunctionParams *parameters; + FunctionAttributes *attributes = new FunctionAttributes(); + Function *func = NULL; + bool declaration = true; + bool constructor = false; + bool external = false; + bool returnIsPointer = false; + DataType thisArgDt = BuildTypes::undefinedType; + Value *thisArg = NULL; + DataType parentArgDt = BuildTypes::undefinedType; + Value *parentArg = NULL; + string prefixName; + GlobalValue::LinkageTypes linkage = Function::ExternalLinkage; + + bool validateAndGetArgsTypes(std::vector &args); + void addFunctionAttributes(Function *f); + public: - FunctionDecl(LanguageDataType tipo, string name, FunctionParams *fp, Node *stmts){ - this->tipo = tipo; - this->stmts = stmts; - this->name = name; + FunctionBase(DataType dt, string name, FunctionParams *fp, location_t loc) : + NamedNode(name, loc) { + this->dt = dt; this->parameters = fp; + addPseudoParameters(); + } + + FunctionBase(DataType dt, string name, FunctionParams *fp, vector &&stmts, + location_t loc, bool constructor = false) : + NamedNode(name, std::move(stmts), loc) { + this->dt = dt; + this->parameters = fp; + this->constructor = constructor; + addPseudoParameters(); + } + + ~FunctionBase() { + delete parameters; + delete attributes; + } + + void addPseudoParameters(); + + FunctionParams& getParameters() { + return *parameters; + } + + virtual Value *getLLVMValue(Node *, FunctionImpl *) override { + return func; + } + + virtual Function *getLLVMFunction() { + return func; } + + unsigned getNumCodedParams() const { + return parameters->getNumCodedParams(); + } + + bool isDeclaration() { + return declaration; + } + + void setDeclaration(bool d) { + declaration = d; + } + + bool isConstructor() { + return constructor; + } + + void setConstructor(bool c) { + constructor = c; + } + + void setExternal(bool e) { + external = e; + } + + bool isExternal() { + return external; + } + + void setReturnIsPointer(bool r) { + returnIsPointer = r; + } + + virtual void addThisArgument(DataType dt); - bool isFunctionDecl() { - return true; + DataType getThisArgDt() const { + return thisArgDt; + } + + void addParentArgument(DataType dt); + + Value *getThisArg() const { + return thisArg; + } + + Value *getParentArg() const { + return parentArg; + } + + DataType getParentArgDt() const { + return parentArgDt; + } + + virtual bool needsParent() { + return parentArg != NULL; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + void setPrefixName(const string& prefix) { + prefixName = prefix; + } + + string getFinalName() { + if (prefixName == "") + return name; + else + return prefixName + ":" + name; + } + + void setAttributes(FunctionAttributes *attributes) { + delete this->attributes; + this->attributes = attributes; + } + + FunctionAttributes *getAttributes() { + return attributes; + } + void setLinkage(GlobalValue::LinkageTypes l) { + linkage = l; + } }; -#endif +class FunctionDecl: public FunctionBase { +public: + FunctionDecl(DataType dt, string name, FunctionParams *fp, location_t loc) : + FunctionBase(dt, name, fp, loc) { + declaration = true; + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual Value *getLLVMValue(Node *, FunctionImpl *) override; +}; diff --git a/src/FunctionDeclExtern.cpp b/src/FunctionDeclExtern.cpp deleted file mode 100644 index d0f0318..0000000 --- a/src/FunctionDeclExtern.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "Header.h" - -Value *FunctionDeclExtern::generate(Function *, BasicBlock *, BasicBlock *allocblock) { - auto sym = search_symbol(name); - if (sym != NULL) { - yyerrorcpp("Function/symbol " + name + " already defined.", this); - yyerrorcpp(name + " was first defined here.", sym); - return NULL; - } - - std::vector arg_types; - if (parameters->getNumParams() != 0) - for (int i = 0; i < parameters->getNumParams(); i++) - arg_types.push_back(parameters->getParamType(i)); - - Type *xtype = robTollvmDataType[tipo]; - FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, 0, name, mainmodule); - nfunc->setCallingConv(CallingConv::C); - tabelasym[allocblock][name] = new RobSymbol(nfunc); - - return nfunc; -} - diff --git a/src/FunctionDeclExtern.h b/src/FunctionDeclExtern.h deleted file mode 100644 index f97aadc..0000000 --- a/src/FunctionDeclExtern.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __FUNCTIONDECLEXTERN_H__ -#define __FUNCTIONDECLEXTERN_H__ - -#include "Node.h" - -class FunctionDeclExtern: public Node { -private: - int tipo; - string name; - FunctionParams *parameters; -public: - FunctionDeclExtern(int tipo, string name, FunctionParams *fp){ - this->tipo = tipo; - this->name = name; - this->parameters = fp; - } - - bool isFunctionDecl() { - return true; - } - - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); - -}; - -#endif - diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp new file mode 100644 index 0000000..eb99c06 --- /dev/null +++ b/src/FunctionImpl.cpp @@ -0,0 +1,225 @@ +#include "FunctionImpl.h" +#include "BackLLVM.h" +#include "semantic/Visitor.h" + +FunctionImpl::FunctionImpl(DataType dt, string name, FunctionParams *fp, vector &&stmts, + location_t loc, location_t ef, bool constructor) : + FunctionBase(dt, name, fp, std::move(stmts), loc, constructor), endfunction(ef) { + this->declaration = false; + funit = RobDbgInfo.currFile(); + + for(auto p: fp->getParameters()) { + symbols[p->getName()] = p; + p->setScope(this); + } +} + +bool FunctionImpl::preGenerate() { + preGenerated = true; + + Node *symbol = findSymbol(name); + FunctionDecl *fsymbol = dynamic_cast(symbol); + if (symbol != NULL && symbol != this && fsymbol != NULL && !fsymbol->isDeclaration()) { + yyerrorcpp("Function/symbol " + name + " already defined.", this); + yyerrorcpp(name + " was first defined here.", symbol); + return false; + } + + Type *xtype = buildTypes->llvmType(dt); + if (returnIsPointer) + xtype = PointerType::getUnqual(xtype); + + if (fsymbol) { + validateImplementation(fsymbol); + func = mainmodule->getFunction(name); + func->setName(getFinalName()); + } else { + std::vector arg_types; + if (!validateAndGetArgsTypes(arg_types)) + return false; + + FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); + func = Function::Create(ftype, linkage, codeAddrSpace, getFinalName(), mainmodule); + } + +#ifdef __MINGW64__ + if (name == "main") + func->setName("__main"); +#endif + + addFunctionAttributes(func); + func->setCallingConv(CallingConv::C); + + if (buildTypes->isUnsignedDataType(dt)) + func->addRetAttr(Attribute::ZExt); + + if (debug_info && !declaration) { + sp = DBuilder->createFunction(funit, getFinalName(), StringRef(), funit, + this->getLineNo(), getFunctionDIType(), this->getLineNo(), DINode::FlagZero, + DISubprogram::SPFlagDefinition); + func->setSubprogram(sp); + RobDbgInfo.push_scope(sp); + } + + if (isExternal()) + return true; + + falloc = BasicBlock::Create(global_context, "", func); + fblock = BasicBlock::Create(global_context, "body", func); + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(falloc); + + bool nooptfunc = func->hasFnAttribute(Attribute::OptimizeNone); + + unsigned Idx = 0; + for (auto &Arg : func->args()) { + Variable *fp = parameters->getParameters()[Idx]; + DataType ptype = fp->getDataType(); + const string& argname = fp->getName(); + Arg.setName(argname); + + if (nooptfunc) { + Arg.addAttr(Attribute::NoUndef); + } + + if (buildTypes->isUnsignedDataType(ptype)) + Arg.addAttr(Attribute::ZExt); + + Type *talloc = buildTypes->llvmType(ptype); + if (buildTypes->isComplex(ptype) || buildTypes->isArrayOrMatrix(ptype)) { + talloc = PointerType::getUnqual(talloc); + fp->setPointerToPointer(true); + } + Value *variable = Builder->CreateAlloca(talloc, dataAddrSpace, 0, argname); + + if (argname == "_this") { + thisArg = variable; + } else if (argname == "_parent") { + parentArg = variable; + } + + fp->setAlloca(variable); + + Builder->CreateStore(&Arg, variable, false); + + if (debug_info) { + DIType *dit = buildTypes->diType(ptype); + if (buildTypes->isComplex(ptype) || buildTypes->isArrayOrMatrix(ptype)) + dit = buildTypes->diPointerType(ptype); + + DILocalVariable *d = DBuilder->createParameterVariable(sp, argname, Idx+1, funit, + this->getLineNo(), dit, true); + DBuilder->insertDeclare(variable, d, RobDbgInfo.getFixedOffsetExpression(), + DILocation::get(sp->getContext(), this->getLineNo(), 0, sp), + falloc); + } + + Idx++; + } + + if (debug_info) + RobDbgInfo.pop_scope(); + + return true; +} + +Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblock) { + + if (!preGenerated) { + if (!preGenerate()) + return NULL; + } + + if (isExternal() || isDeclaration()) //can be declaration when came from USEparser + return NULL; + + if (debug_info) { + RobDbgInfo.push_scope(sp); + RobDbgInfo.emitLocation(this); + } + + Value *last_block = generateChildren(this, fblock, falloc); + if (!last_block) + last_block = fblock; + + // prevent mallformed block at the end without proper return instruction + if (last_block->getValueID() == Value::BasicBlockVal) { + BasicBlock *lb = (BasicBlock*)last_block; + Builder->SetInsertPoint(lb); + RobDbgInfo.emitLocation(&endfunction); + if (lb->sizeWithoutDebug() == 0 && !lb->hasNPredecessorsOrMore(1) && + lb != fblock) { + lb->eraseFromParent(); + + } else if (lb->getTerminator() == NULL) { + Type *xtype = buildTypes->llvmType(dt); + if (!xtype->isVoidTy()) { + yyerrorcpp("Missing return statement in function " + name, &endfunction); + } else + Builder->CreateRetVoid(); + } + } + + if (falloc->empty()) + falloc->removeFromParent(); + else + BranchInst::Create(fblock, falloc); + + if (debug_info) + RobDbgInfo.pop_scope(); + + return func; +} + +DISubroutineType *FunctionImpl::getFunctionDIType() { + SmallVector Tys; + Tys.push_back(buildTypes->diType(dt)); // return type + for(Variable *p : parameters->getParameters()) { + Tys.push_back(buildTypes->diType(p->getDataType())); + } + return DBuilder->createSubroutineType(DBuilder->getOrCreateTypeArray(Tys)); +} + +bool FunctionImpl::validateImplementation(FunctionDecl *decl) { + bool result = true; + FunctionParams& decl_parameters = decl->getParameters(); + unsigned pnum_decl = decl_parameters.getNumCodedParams(); + unsigned pnum_impl = parameters->getNumCodedParams(); + if (pnum_impl != pnum_decl) { + yyerrorcpp(string_format("The number of arguments differs between function declaration(%d) and definition(%d).", + pnum_decl, pnum_impl), this); + yywarncpp("The function declaration is here.", decl); + result = false; + } + int compareno = std::min(pnum_impl, pnum_decl); + for(int i = 0; i < compareno; i++) { + Variable *p = decl_parameters.getParameters()[i]; + if (p->getDataType() != parameters->getParamType(i)) { + yyerrorcpp(string_format("Argument %s has distinct type in declaration '%s' and definition '%s'.", + parameters->getParamName(i).c_str(), buildTypes->name(p->getDataType()), + buildTypes->name(parameters->getParamType(i))), this); + yywarncpp("The function declaration is here.", decl); + result = false; + } + } + DataType decl_type = decl->getDataType(); + if (dt != decl_type) { + yyerrorcpp(string_format("Function return type has distinct type in declaration '%s' and definition '%s'.", + buildTypes->name(decl_type), buildTypes->name(dt)), this); + yywarncpp("The function declaration is here.", decl); + result = false; + } + + return result; +} + +Node* FunctionImpl::accept(Visitor& v) { + return v.visit(*this); +} + +Value* FunctionImpl::getLLVMValue(Node *, FunctionImpl *) { + if (!preGenerated) + preGenerate(); + return func; +} diff --git a/src/FunctionImpl.h b/src/FunctionImpl.h new file mode 100644 index 0000000..4510728 --- /dev/null +++ b/src/FunctionImpl.h @@ -0,0 +1,45 @@ + +#pragma once + +#include "Node.h" +#include "FunctionDecl.h" + +class Visitor; + +class FunctionImpl: public FunctionBase { +private: + SourceLocation endfunction; + bool preGenerated = false; + BasicBlock *falloc = NULL; + BasicBlock *fblock = NULL; + + DIFile *funit; + DISubprogram *sp; + bool preGenerate(); + +public: + FunctionImpl(DataType dt, string name, FunctionParams *fp, vector &&stmts, location_t loc, + location_t ef, bool constructor = false); + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + DISubroutineType *getFunctionDIType(); + + bool validateImplementation(FunctionDecl *decl); + + virtual Node* accept(Visitor& v) override; + + virtual Value *getLLVMValue(Node *, FunctionImpl *) override; + + virtual Function *getLLVMFunction() override { + if (!preGenerated) + preGenerate(); + return func; + } + + void addThisArgument(DataType dt) override { + if (preGenerated) + assert(!preGenerated && "The function is already generated. This should not happen!\n"); + FunctionBase::addThisArgument(dt); + }; +}; diff --git a/src/FunctionParams.cpp b/src/FunctionParams.cpp index 31cf9bd..397a0c0 100644 --- a/src/FunctionParams.cpp +++ b/src/FunctionParams.cpp @@ -1,19 +1,32 @@ -#include "Header.h" + +#include "FunctionParams.h" FunctionParams::FunctionParams() {}; -void FunctionParams::append(FunctionParam& e) { +void FunctionParams::append(Variable *e) { parameters.push_back(e); }; + +void FunctionParams::insert(int at, Variable *fp) { + parameters.insert(parameters.begin() + at, fp); +} -unsigned FunctionParams::getNumParams() const { - return parameters.size(); +unsigned FunctionParams::getNumCodedParams() { + unsigned num = 0; + for(auto p : parameters) { + // don't count parameters _this, _parent, and other pseudo + // parameters like _any_.size, _any_.cols + if (p->getName() != "_this" && p->getName() != "_parent" && + p->getName().find('.') == string::npos) + num++; + } + return num; }; -Type *FunctionParams::getParamType(int position) const { - return robTollvmDataType[parameters[position].type]; +DataType FunctionParams::getParamType(int position) { + return parameters[position]->getDataType(); } -const char *FunctionParams::getParamElement(int position) const { - return parameters[position].name; +const string FunctionParams::getParamName(int position) { + return parameters[position]->getName(); } diff --git a/src/FunctionParams.h b/src/FunctionParams.h index 63bfe1b..3057a41 100644 --- a/src/FunctionParams.h +++ b/src/FunctionParams.h @@ -1,19 +1,22 @@ -#ifndef __FUNCTION_PARAMS_H__ -#define __FUNCTION_PARAMS_H__ +#pragma once #include "Node.h" +#include "Variable.h" class FunctionParams { private: + std::vector parameters; + public: - std::vector parameters; FunctionParams(); - void append(FunctionParam& fp); + void append(Variable *fp); + void insert(int at, Variable *fp); - unsigned getNumParams() const; - Type *getParamType (int position) const; - const char *getParamElement (int position) const; -}; - -#endif + unsigned getNumCodedParams(); + DataType getParamType (int position); + const string getParamName (int position); + std::vector const& getParameters() { + return parameters; + } +}; diff --git a/src/Header.h b/src/Header.h index d68056d..beb987c 100644 --- a/src/Header.h +++ b/src/Header.h @@ -1,206 +1,57 @@ -#ifndef __HEADER_H__ -#define __HEADER_H__ -//#define ENABLE_ARDUINO -//#define ENABLE_PRINT -#define COLOR_RED "\x1b[31m" -#define COLOR_GREEN "\x1b[32m" -#define COLOR_YELLOW "\x1b[33m" -#define COLOR_BLUE "\x1b[34m" -#define COLOR_MAGENTA "\x1b[35m" -#define COLOR_CYAN "\x1b[36m" -#define COLOR_RESET "\x1b[0m" +#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace llvm; - -/* After adding new types here, go to Program::generate to fill - * the robTollvmDataType vector */ -enum LanguageDataType {tvoid, tbool, tchar, tint8, tint16, tint32, tint64, - tint8u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, - __ldt_last}; - -static const char *LanguageDataTypeNames[__ldt_last] = {"void", "boolean", "char", "int8", - "int16", "int32", "int64", "unsigned int8", "unsigned int16", - "unsigned int32", "unsigned int64", "float", - "double", "long double"}; - -enum DataQualifier {qnone, qconst, qvolatile}; - -extern Type* robTollvmDataType[]; - -class Node; -class Stmts; -class ArrayElements; -class MatrixElements; -class FunctionParams; -class ParamsCall; - -typedef struct { - Node *value; - unsigned count; -} ArrayElement; - -typedef struct { - const char *name; - LanguageDataType type; -} FunctionParam; - -typedef struct { - ArrayElements *array; - unsigned count; -} MatrixElement; - -#include "bison.hpp" - -extern int yyerror(const char *s); -extern int yylex(); -extern int yylineno; -extern int yycolno; -extern Node* getNodeForIntConst(int64_t i); - -// Program main module -extern Module *mainmodule; -extern BasicBlock *global_alloc; - -extern char* build_filename; -extern char* build_outputfilename; -extern LLVMContext global_context; +#ifndef SCANNER_OR_VISITOR +#error Please include this file only on .y or visitor files +#endif +#include "HeaderGlobals.h" #include "SourceLocation.h" - -// symbol table -#include "RobSymbol.h" -extern map> tabelasym; - -// arduino functions -extern Function *analogWrite; -extern Function *analogRead; -extern Function *delay; -extern Function *delayMicroseconds; -extern Function *init; -extern Function *print; -extern Function *i16div; - -typedef struct { - const char *name; - const char *triple; - const char *cpu; - const char *features; -} TargetInfo; - -static TargetInfo supportedTargets[] = { - {"", "", "", ""}, // default target - {"avr328p", "avr-atmel-none", "atmega328p", "+avr5"}, - {"stm32f1", "thumbv7m-none-eabi", "cortex-m3", ""}, - {"esp32", "xtensa", "", ""}, -}; - -static string getTypeName(Type *ty) { - string type_str; - llvm::raw_string_ostream rso(type_str); - ty->print(rso); - return rso.str(); -} - -static int yyerrorcpp(const string& s, SourceLocation *n) { - string e = COLOR_RED "semantic error: " COLOR_RESET + s; - if (n) { - yylineno = n->getLineNo(); - yycolno = n->getColNo(); - } - return yyerror(e.c_str()); -} - -static void yywarncpp(const string& s, SourceLocation *n) { - string e = COLOR_BLUE "semantic warning: " COLOR_RESET + s; - if (n) { - yylineno = n->getLineNo(); - yycolno = n->getColNo(); - } - fprintf(stderr, "%s:%d:%d %s\n", - build_filename, yylineno, yycolno, e.c_str()); -} - -static RobSymbol *search_symbol(const string& ident, BasicBlock *firstb = NULL, BasicBlock *secondb = NULL) { - BasicBlock *blocks[] = {firstb, secondb, global_alloc}; - for(BasicBlock *b : blocks) { - if (b == NULL) - continue; - auto blocksym = tabelasym[b]; - auto var = blocksym.find(ident); - if (var != blocksym.end()) - return var->second; - } - return NULL; -} - +#include "Scanner.h" #include "Node.h" #include "ArrayElements.h" #include "AttachInterrupt.h" #include "BinaryOp.h" -#include "Capsule.h" #include "CmpOp.h" -#include "Coercion.h" -#include "Delay.h" #include "Double.h" #include "Float.h" #include "Float128.h" #include "FunctionCall.h" #include "FunctionDecl.h" -#include "FunctionDeclExtern.h" -#include "FunctionParams.h" +#include "FunctionImpl.h" +#include "Variable.h" #include "If.h" #include "Int1.h" +#include "Char.h" #include "Int8.h" #include "Int16.h" #include "Int32.h" #include "Int64.h" -#include "InPort.h" #include "Load.h" #include "LoadArray.h" #include "LoadMatrix.h" #include "Matrix.h" #include "MatrixElements.h" -#include "OutPort.h" #include "ParamsCall.h" -#include "Print.h" #include "Program.h" #include "Return.h" -#include "Stmts.h" #include "Scalar.h" -#include "Semantic.h" -#include "String.h" +#include "semantic/Semantic.h" +#include "StringConst.h" #include "UpdateArray.h" #include "UpdateMatrix.h" #include "Array.h" +#include "StringConst.h" #include "While.h" #include "Loop.h" #include "Pointer.h" #include "FlipOp.h" -#include "Cast.h" - -#include "Visitor.h" -#include "RecursiveVisitor.h" -#include "PrintAstVisitor.h" - -#endif - +#include "InlineAssembly.h" +#include "Interface.h" +#include "UserType.h" +#include "Enum.h" +#include "MemCopy.h" +#include "BackLLVM.h" +#include "NamedConst.h" +#include "BitCast.h" +#include "semantic/PropagateTypes.h" \ No newline at end of file diff --git a/src/HeaderExternals.h b/src/HeaderExternals.h new file mode 100644 index 0000000..9ffb792 --- /dev/null +++ b/src/HeaderExternals.h @@ -0,0 +1,34 @@ + +#pragma once + +/* Add only std cpp library related includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +/* Add only llvm related includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; diff --git a/src/HeaderGlobals.h b/src/HeaderGlobals.h new file mode 100644 index 0000000..4eca9f2 --- /dev/null +++ b/src/HeaderGlobals.h @@ -0,0 +1,54 @@ + +#pragma once + +#include "HeaderExternals.h" + +// Program main module and IR Builder +extern Module* mainmodule; +extern BasicBlock* global_alloc; +extern LLVMContext global_context; +extern unique_ptr> Builder; + +class BuildTypes; +extern unique_ptr buildTypes; + +class SourceLocation; +class Node; + +// Debug Info +extern bool debug_info; +extern unique_ptr DBuilder; +struct DebugInfo { + DICompileUnit *cunit; + vector files; + vector scopes; + void emitLocation(SourceLocation *s); + void push_scope(DIScope*); + void push_file(DIFile*); + void pop_scope(); + void pop_file(); + DIFile *currFile(); + DIScope *currScope(); + void declareVar(Node *n, Value *alloc, BasicBlock *allocblock); + void declareGlobalVar(Node *n, GlobalVariable *gv, BasicBlock *allocblock); + DIExpression *getFixedOffsetExpression(); +}; +extern struct DebugInfo RobDbgInfo; + +// Error messages +void yyerrorcpp(const string& s, SourceLocation *n, bool semantic = true); +void yywarncpp(const string& s, SourceLocation *n); + +template +string string_format(const char *format, Args ... args) { + int size_s = snprintf(nullptr, 0, format, args ...) + 1; + if( size_s <= 0 ) { + return ""; + } + auto size = static_cast(size_s); + unique_ptr buf(new char[ size ]); + snprintf(buf.get(), size, format, args ...); + return string(buf.get(), buf.get() + size - 1); +} + +class Node; diff --git a/src/Identifier.cpp b/src/Identifier.cpp new file mode 100644 index 0000000..1531fab --- /dev/null +++ b/src/Identifier.cpp @@ -0,0 +1,42 @@ + +#include "Identifier.h" + +Node* Identifier::getSymbol(Node *scope, bool validate, list *symbols) { + + if (scope == NULL) + assert(scope && "scope can't be null!"); + + Node *result = scope; + stringstream ss(ident); + string ci; + + // first symbol + getline(ss, ci, '.'); + result = result->findSymbol(ci); + if (result) { + while (!ss.eof() && result != NULL) { + getline(ss, ci, '.'); + if (symbols) + symbols->push_back(result); + result = result->findMember(ci); + } + } + + if (!result && validate) { + yyerrorcpp("Symbol " + ident + " not found.", this); + } + return result; +} + +Identifier Identifier::getStem() { + assert(complex && "identifier is not complex."); + size_t last = ident.find_last_of('.'); + return Identifier(ident.substr(0, last), this->getLoc()); +} + + string const Identifier::getLastName() const { + if (!complex) + return ident; + else + return ident.substr(ident.find_last_of(".")+1); +} diff --git a/src/Identifier.h b/src/Identifier.h new file mode 100644 index 0000000..97aadbe --- /dev/null +++ b/src/Identifier.h @@ -0,0 +1,35 @@ + +#pragma once + +#include +#include "Node.h" + +class Identifier: public SourceLocation { +private: + string ident; + bool complex; + +public: + Identifier(const string& ident, location_t loc): SourceLocation(loc) { + changeIdentifier(ident); + } + + void changeIdentifier(const string& ident) { + this->ident = ident; + complex = ident.find('.') != string::npos; + } + + Node* getSymbol(Node *scope, bool validate = true, list *symbols = nullptr); + + string const getFullName() const { + return ident; + } + + bool isComplex() const { + return complex; + } + + Identifier getStem(); + + string const getLastName() const; +}; diff --git a/src/If.cpp b/src/If.cpp index bcf5f87..7ba9148 100644 --- a/src/If.cpp +++ b/src/If.cpp @@ -1,30 +1,45 @@ -#include "Header.h" +#include "If.h" +#include "FunctionImpl.h" +#include "semantic/Visitor.h" -If::If(Node *e, Node *tst, Node *est) : expr(e), thenst(tst), elsest(est) { - node_children.reserve(3); - node_children.push_back(expr); - node_children.push_back(thenst); +If::If(Node *e, vector &&tst, location_t loc): Node(loc), expr(e) { + addChild(expr); + thenst = new Node(std::move(tst), loc); + addChild(thenst); + elsest = NULL; +} - if (est != NULL) - node_children.push_back(elsest); +If::If(Node *e, vector &&tst, vector &&est, location_t loc): If(e, std::move(tst), loc) { + elsest = new Node(std::move(est), loc); + addChild(elsest); } -Value *If::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - Value *exprv = expr->generate(func, block, allocblock); +Value *If::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - BasicBlock *thenb = BasicBlock::Create(global_context, "if_then", func, 0); - Value *thennewb = thenst->generate(func, thenb, allocblock); + BasicBlock *newblock = block; + Value *exprv = expr->generateNewBlock(func, &newblock, allocblock); + if (!exprv) { + // This occurs when loading a var still not defined, so + // we let it be False to recovery from the error + exprv = ConstantInt::get(Type::getInt1Ty(global_context), 0); + } + + BasicBlock *thenb = BasicBlock::Create(global_context, "if_then", + func->getLLVMFunction(), 0); + Value *thennewb = thenst->generateChildren(func, thenb, allocblock); Value *elsenewb = NULL; - BasicBlock *elseb = BasicBlock::Create(global_context, "if_else", func, 0); + BasicBlock *elseb = BasicBlock::Create(global_context, "if_else", + func->getLLVMFunction(), 0); if (elsest != 0) { - elsenewb = elsest->generate(func, elseb, allocblock); + elsenewb = elsest->generateChildren(func, elseb, allocblock); } - - BranchInst::Create(thenb, elseb, exprv, block); - BasicBlock *mergb = BasicBlock::Create(global_context, "if_cont", func, 0); + BranchInst::Create(thenb, elseb, exprv, newblock); + + BasicBlock *mergb = BasicBlock::Create(global_context, "if_cont", + func->getLLVMFunction(), 0); // identify last then block BasicBlock *lastthen = thenb; @@ -47,7 +62,6 @@ Value *If::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { return mergb; } -void If::accept(Visitor& v) { - v.visit(*this); -} - +Node* If::accept(Visitor& v) { + return v.visit(*this); +} diff --git a/src/If.h b/src/If.h index 62a3c52..a46ccce 100644 --- a/src/If.h +++ b/src/If.h @@ -1,5 +1,5 @@ -#ifndef __IF_H__ -#define __IF_H__ +#pragma once + #include "Node.h" class If: public Node { @@ -8,9 +8,8 @@ class If: public Node { Node *thenst; Node *elsest; public: - If(Node *e, Node *tst, Node *est); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; + If(Node *e, vector &&tst, location_t loc); + If(Node *e, vector &&tst, vector &&est, location_t loc); + virtual Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual Node* accept(Visitor& v) override; }; - -#endif diff --git a/src/InPort.cpp b/src/InPort.cpp deleted file mode 100644 index c9e7a29..0000000 --- a/src/InPort.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "Header.h" - -Value *InPort::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - vector args; - - Int8 prt(atoi(port.c_str())); - Value *v = prt.generate(func, block, allocblock); - //v = Coercion::Convert(v, Type::getInt8Ty(global_context)); - args.push_back(v); - - ArrayRef argsRef(args); - return CallInst::Create(analogRead, argsRef, "", block); -} - diff --git a/src/InPort.h b/src/InPort.h deleted file mode 100644 index 9871392..0000000 --- a/src/InPort.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __INPORT_H__ -#define __INPORT_H__ -#include "Node.h" -#include "Int8.h" - -class InPort: public Node { -private: - string port; -public: - InPort(const char *p): port(p) {} - - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); - -}; - -#endif diff --git a/src/Injections.h b/src/Injections.h new file mode 100644 index 0000000..de0f0d6 --- /dev/null +++ b/src/Injections.h @@ -0,0 +1,23 @@ + +#pragma once + +#include + +enum BindScope {bs_singleton, bs_transient}; + +struct Injection { + string bind; + string to; + string singletonName; + BindScope scope; + SourceLocation loc; + + Injection(const string& bind, const string& to, + BindScope scope, const SourceLocation& loc): loc(loc) { + this->bind = bind; + this->to = to; + this->scope = scope; + if (this->scope == bs_singleton) + this->singletonName = "__var_injection_for_" + bind; + } +}; diff --git a/src/InlineAssembly.cpp b/src/InlineAssembly.cpp new file mode 100644 index 0000000..b217310 --- /dev/null +++ b/src/InlineAssembly.cpp @@ -0,0 +1,64 @@ + +#include +#include "InlineAssembly.h" +#include "FunctionImpl.h" + +Value *InlineAssembly::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + Function *llvmFunction = func->getLLVMFunction(); + + // Build a map with all argument names and the corresponding llvm::Argument* + // TODO: Include local symbols in the map + map argMap; + for (auto &Arg : llvmFunction->args()) { + argMap[Arg.getName().str()] = &Arg; + } + + bool isFirst = true; + std::string final_constraints; + std::vector ArgTypes; + std::vector Args; + + // constraints format supported: + // "r(arg_name_1)" + // "r(arg_name_1),r(arg_name_2),..." + regex constraint_regex(R"(([0-9a-zA-Z]+)\(([^)]+)\))"); + smatch match; + string::const_iterator searchStart(constraints.cbegin()); + + while (std::regex_search(searchStart, constraints.cend(), match, constraint_regex)) { + final_constraints += (isFirst ? "" : ",") + match[1].str(); + isFirst = false; + std::string argName = match[2].str(); + auto it = argMap.find(argName); + if (it != argMap.end()) { + llvm::Argument* arg = it->second; + ArgTypes.push_back(arg->getType()); + Args.push_back(arg); + } else { + yyerrorcpp(string_format("Parameter '%s' for assembly constraint not found.", + argName.c_str()), this); + } + searchStart = match.suffix().first; + } + + // TODO: Add output constraint when there's r = asm(...) in the language + // constraints = (isFirst ? "=r" : "=r," + constraints); + // returnType = detect! + // FunctionType *asmFuncType = FunctionType::get(returnType, ArgTypes, false); + FunctionType *asmFuncType = FunctionType::get(Type::getVoidTy(global_context), ArgTypes, false); + + InlineAsm *asmcall = InlineAsm::get(asmFuncType, assembly, final_constraints, true, false, InlineAsm::AD_ATT); + Error err = asmcall->verify(asmFuncType, constraints); + if (err) { + /* disabled due to false alerts + std::string error_message; + raw_string_ostream OS(error_message); + OS << err; + OS << " constraints: " << new_constraints; + yywarncpp(error_message, this);*/ + } + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateCall(asmFuncType, asmcall, Args); +} diff --git a/src/InlineAssembly.h b/src/InlineAssembly.h new file mode 100644 index 0000000..8ce7bf3 --- /dev/null +++ b/src/InlineAssembly.h @@ -0,0 +1,14 @@ + +#pragma once + +#include "Node.h" + +class InlineAssembly: public Node { +private: + string assembly; + string constraints; +public: + InlineAssembly(const char *_asm, location_t loc): Node(loc), assembly(_asm) { } + InlineAssembly(const char *_asm, const char *cons, location_t loc): Node(loc), assembly(_asm), constraints(cons) { } + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; +}; diff --git a/src/Int1.cpp b/src/Int1.cpp index c5c65e8..6781a5a 100644 --- a/src/Int1.cpp +++ b/src/Int1.cpp @@ -1,12 +1,7 @@ -#include "Header.h" +#include "Int1.h" -Value *Int1::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) +Value *Int1::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt1Ty(global_context), number); + return ConstantInt::get(Type::getInt1Ty(global_context), value); } - -void Int1::accept(Visitor &v) { - v.visit(*this); -} - diff --git a/src/Int1.h b/src/Int1.h index f55868c..edfa329 100644 --- a/src/Int1.h +++ b/src/Int1.h @@ -1,18 +1,23 @@ #pragma once +#include "Node.h" + class Int1: public Node { - private: - char number; - public: - Int1(char n): number(n) {} - char getNumber() const { return number; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { - return true; - } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getInt1Ty(global_context); - } +private: + bool value; + +public: + Int1(bool v, location_t loc): Node(loc), value(v) {} + bool getValue() const { return value; } + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tbool; + } + }; diff --git a/src/Int16.cpp b/src/Int16.cpp index c6bfc73..244eade 100644 --- a/src/Int16.cpp +++ b/src/Int16.cpp @@ -1,11 +1,10 @@ -#include "Header.h" + #include "Int16.h" -Value *Int16::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt16Ty(global_context), number, IsSigned); +Value *Int16::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt16Ty(global_context), number, true); } -void Int16::accept(Visitor &v) { - v.visit(*this); +Value *UInt16::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt16Ty(global_context), number, false); } - diff --git a/src/Int16.h b/src/Int16.h index 18b8972..e53df30 100644 --- a/src/Int16.h +++ b/src/Int16.h @@ -1,22 +1,46 @@ -#ifndef __INT16_H__ -#define __INT16_H__ + +#pragma once + #include "Node.h" class Int16: public Node { private: short number; - bool IsSigned; + public: - Int16(short n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + Int16(short n, location_t loc): Node(loc), number(n) {} + short getNumber() const { return number; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getInt16Ty(global_context); + + virtual DataType getDataType() override { + return tint16; } + }; -#endif +class UInt16: public Node { +private: + unsigned short number; + +public: + UInt16(unsigned short n, location_t loc): Node(loc), number(n) {} + + unsigned short getNumber() const { return number; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tint16u; + } + +}; diff --git a/src/Int32.cpp b/src/Int32.cpp index 3d8a1bf..0dcfc54 100644 --- a/src/Int32.cpp +++ b/src/Int32.cpp @@ -1,9 +1,10 @@ -#include "Header.h" -Value *Int32::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt32Ty(global_context), number, IsSigned); +#include "Int32.h" + +Value *Int32::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt32Ty(global_context), number, true); } -void Int32::accept(Visitor &v) { - v.visit(*this); +Value *UInt32::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt32Ty(global_context), number, false); } diff --git a/src/Int32.h b/src/Int32.h index 5b4c520..2fddf56 100644 --- a/src/Int32.h +++ b/src/Int32.h @@ -1,22 +1,44 @@ -#ifndef __INT32_H__ -#define __INT32_H__ + +#pragma once + +#include "Node.h" class Int32: public Node { private: int number; - bool IsSigned; + public: - Int32(int n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + Int32(int n, location_t loc): Node(loc), number(n) {} + int getNumber() const { return number; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getInt32Ty(global_context); + + virtual DataType getDataType() override { + return tint32; } }; -#endif +class UInt32: public Node { +private: + unsigned int number; + +public: + UInt32(unsigned int n, location_t loc): Node(loc), number(n) {} + + unsigned int getNumber() const { return number; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tint32u; + } +}; diff --git a/src/Int64.cpp b/src/Int64.cpp index edbb58e..21663d8 100644 --- a/src/Int64.cpp +++ b/src/Int64.cpp @@ -1,10 +1,10 @@ -#include "Header.h" -Value *Int64::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt64Ty(global_context), number, IsSigned); -} +#include "Int64.h" -void Int64::accept(Visitor &v) { - v.visit(*this); +Value *Int64::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt64Ty(global_context), number, true); } +Value *UInt64::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt64Ty(global_context), number, false); +} diff --git a/src/Int64.h b/src/Int64.h index 15536d5..907f857 100644 --- a/src/Int64.h +++ b/src/Int64.h @@ -1,21 +1,44 @@ -#ifndef __INT64_H__ -#define __INT64_H__ + +#pragma once + +#include "Node.h" class Int64: public Node { private: - int number; - bool IsSigned; + int64_t number; + public: - Int64(int n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} - int getNumber() const { return number; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + Int64(int64_t n, location_t loc): Node(loc), number(n) {} + + int64_t getNumber() const { return number; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getInt64Ty(global_context); + + virtual DataType getDataType() override { + return tint64; } }; -#endif +class UInt64: public Node { +private: + uint64_t number; + +public: + UInt64(uint64_t n, location_t loc): Node(loc), number(n) {} + + uint64_t getNumber() const { return number; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tint64u; + } +}; diff --git a/src/Int8.cpp b/src/Int8.cpp index 1545edd..bd95f32 100644 --- a/src/Int8.cpp +++ b/src/Int8.cpp @@ -1,12 +1,12 @@ -#include "Header.h" +#include "Int8.h" -Value *Int8::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) +Value *Int8::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt8Ty(global_context), number, IsSigned); + return ConstantInt::get(Type::getInt8Ty(global_context), number, true); } -void Int8::accept(Visitor &v) { - v.visit(*this); +Value *UInt8::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) +{ + return ConstantInt::get(Type::getInt8Ty(global_context), number, false); } - diff --git a/src/Int8.h b/src/Int8.h index efbc253..46f06dd 100644 --- a/src/Int8.h +++ b/src/Int8.h @@ -1,21 +1,42 @@ -#ifndef __INT8_H__ -#define __INT8_H__ + +#pragma once + +#include "Node.h" class Int8: public Node { - private: - char number; - bool IsSigned; - public: - Int8(char n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} - char getNumber() const { return number; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { - return true; - } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getInt8Ty(global_context); - } +private: + int8_t number; + +public: + Int8(int8_t n, location_t loc): Node(loc), number(n) { + dt = tint8; + } + + int8_t getNumber() const { return number; } + void setNumber(int8_t n) { number = n; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } }; -#endif +class UInt8: public Node { +private: + uint8_t number; + +public: + UInt8(uint8_t n, location_t loc): Node(loc), number(n) { + dt = tint8u; + } + + uint8_t getNumber() const { return number; } + void setNumber(uint8_t n) { number = n; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } +}; \ No newline at end of file diff --git a/src/Interface.cpp b/src/Interface.cpp new file mode 100644 index 0000000..5f0a7b4 --- /dev/null +++ b/src/Interface.cpp @@ -0,0 +1,53 @@ + +#include "Interface.h" +#include "UserType.h" +#include "FunctionImpl.h" +#include "FunctionDecl.h" +#include "Program.h" + +void Interface::createDataType() { + StructType *intftype = StructType::create(global_context, getName()); + dt = buildTypes->addDataType(this, intftype); + buildTypes->setInterface(dt, true); + if (dt == BuildTypes::undefinedType) { + yyerrorcpp("Type " + name + " alread defined.", this); + yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); + } else { + program->getDispatcher()->notifyInterface(dt); + } +} + +Value *Interface::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + // set function parameters + for(Node *n : node_children) { + FunctionDecl *fd = dynamic_cast(n); + if (fd) { + fd->setPrefixName(getName()); + fd->addThisArgument(dt); + fd->generate(func, block, allocblock); + } + } + + return NULL; +} + +bool Interface::validateImplementation(UserType *ut) { + bool result = true; + for(const auto & [key, func_decl] : getSymbols()) { + auto symb = ut->findSymbol(key, false); + FunctionImpl *fimpl = dynamic_cast(symb); + if (!symb) { + yyerrorcpp(string_format("Type %s doesn't implement %s.", ut->getName().c_str(), + key.c_str()), ut); + yywarncpp(string_format("%s is defined here.", key.c_str()), func_decl); + result = false; + } else if (!fimpl) { + yyerrorcpp(key + " must be a function.", symb); + result = false; + } else { + fimpl->validateImplementation(dynamic_cast(func_decl)); + } + } + return result; +} diff --git a/src/Interface.h b/src/Interface.h new file mode 100644 index 0000000..50430c3 --- /dev/null +++ b/src/Interface.h @@ -0,0 +1,29 @@ + +#pragma once + +#include "Node.h" + +class Interface: public NamedNode { +private: + void createDataType(); + int nextConcreteTypeId = 0; + +public: + Interface(const string& name, location_t loc) : NamedNode(name, loc) { + createDataType(); + } + + Interface(const string& name, vector stmts, location_t loc): + NamedNode(name, std::move(stmts), loc) { + createDataType(); + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + bool validateImplementation(UserType *ut); + + int getNextConcreteId() { + nextConcreteTypeId++; + return nextConcreteTypeId-1; + } +}; diff --git a/src/Language.l b/src/Language.l index cc633ad..541fa60 100644 --- a/src/Language.l +++ b/src/Language.l @@ -1,23 +1,29 @@ %{ - -#include "Header.h" -#include "bison.hpp" +#include "HeaderGlobals.h" +#include +#include "Language_gen_y.hpp" extern void unescape(char *s); +void update_loc(location_t *yylloc, int lineno, int leng, char *text); -extern int yycolno; -extern int yycolnew; -#define YY_USER_ACTION yycolno = yycolnew; yycolnew += yyleng; - +#define YY_USER_ACTION update_loc(yylloc, yylineno, yyleng, yytext); %} +%option noinput nounput noyywrap %option yylineno +%option reentrant bison-locations +%option prefix="MAIN" + %x COMMENT +A [a-zA-Z_] +D [0-9] +ID {A}({A}|{D})* +EXP ([Ee][-+]?[0-9]+)? + %% -[ \t\r] { /* ignore spaces */ } -[\n] { yycolnew = 0; yycolno = 0; } +[ \t\r\n] { /* ignore spaces */ } "/*" { yymore(); BEGIN COMMENT; } [^*] { yymore(); } "*"/[^/] { yymore(); } @@ -28,21 +34,31 @@ extern int yycolnew; "register" { return TOK_REGISTER; } "volatile" { return TOK_VOLATILE; } "const" { return TOK_CONST; } -"void" { return TOK_VOID; } -"bool" { return TOK_FBOOL; } -"char" { return TOK_FCHAR; } -"int8" { return TOK_FINT8; } -"int16" { return TOK_FINT16; } -"int32" { return TOK_FINT32; } -"int64" { return TOK_FINT64; } -"float" { return TOK_FFLOAT; } -"double" { return TOK_FDOUBLE; } -"long" { return TOK_FLONG; } -"unsigned" { return TOK_FUNSIGNED; } "return" { return TOK_RETURN; } "true" { return TOK_TRUE; } "false" { return TOK_FALSE; } "at" { return TOK_AT; } +"asm" { return TOK_ASM; } +"type" { return TOK_TYPE; } +"interface" { return TOK_INTF; } +"implements" { return TOK_IMPL; } +"use" { return TOK_USE; } + +"inline" { return TOK_INLINE; } +"noinline" { return TOK_NOINLINE; } +"weak" { return TOK_WEAK; } +"section" { return TOK_SECTION; } +"naked" { return TOK_NAKED; } +"signal" { return TOK_SIGNAL; } +"debugonly" { return TOK_DEBUGONLY; } +"noopt" { return TOK_NOOPT; } + +"bind" { return TOK_BIND; } +"to" { return TOK_TO; } +"singleton" { return TOK_SINGLETON; } +"transient" { return TOK_TRANSIENT; } + +"enum" { return TOK_ENUM; } "if" { return TOK_IF; } "else" { return TOK_ELSE; } @@ -50,33 +66,21 @@ extern int yycolnew; "while" { return TOK_WHILE; } "loop" { return TOK_LOOP; } -"print" { return TOK_PRINT; } - -"in"[0-9]+ { yylval.port = strndup(yytext+2, yyleng-2); - return TOK_IN; - } - -"out"[0-9]+ { yylval.port = strndup(yytext+3, yyleng-3); - return TOK_OUT; - } - -"stepper"[0-2]+ { yylval.nint = atoi(strndup(yytext+7, yyleng-7)); - return TOK_STEPPER; - } - -"servo" { return TOK_SERVO; } - "quando" { return TOK_QUANDO; } "esta" { return TOK_ESTA; } -"delay" { return TOK_DELAY; } - "and" { return TOK_AND; } "or" { return TOK_OR; } -"!" { return '!'; } -"<" { return '<'; } -">" { return '>'; } +"<<" { return TOK_LSHIFT; } +">>" { return TOK_RSHIFT; } + +"==" { return EQ_OP; } +"!=" { return NE_OP; } +"<=" { return LE_OP; } +">=" { return GE_OP; } +"<" { return LT_OP; } +">" { return GT_OP; } "[" { return '['; } "]" { return ']'; } @@ -98,53 +102,97 @@ extern int yycolnew; "&" { return '&'; } "^" { return '^'; } "~" { return '~'; } -"<<" { return TOK_LSHIFT; } -">>" { return TOK_RSHIFT; } +"!" { return '!'; } ":" { return ':'; } +"." { return '.'; } "," { return ','; } ";" { return ';'; } -[a-zA-Z_][a-zA-Z0-9_]* { yylval.ident = strndup(yytext, yyleng); +{ID} { yylval->ident = strndup(yytext, yyleng); return TOK_IDENTIFIER; } -[0-9]+\.[0-9]+ { char *aux = strndup(yytext, yyleng); - yylval.nfloat = strtof(aux, NULL); +{ID}(\.{ID})+ { yylval->ident = strndup(yytext, yyleng); + return TOK_XIDENTIFIER; + } + +[0-9]+\.[0-9]+{EXP} { char *aux = strndup(yytext, yyleng); + yylval->nfloat = strtof(aux, NULL); free(aux); return TOK_FLOAT; } -[0-9]+\.[0-9]+D { char *aux = strndup(yytext, yyleng); - yylval.ndouble = strtod(aux, NULL); +[0-9]+\.[0-9]+{EXP}D { char *aux = strndup(yytext, yyleng); + yylval->ndouble = strtod(aux, NULL); free(aux); return TOK_DOUBLE; } -[0-9]+\.[0-9]+LD { char *aux = strndup(yytext, yyleng); - yylval.nldouble = strtold(aux, NULL); +[0-9]+\.[0-9]+{EXP}LD { char *aux = strndup(yytext, yyleng); + yylval->nldouble = strtold(aux, NULL); free(aux); return TOK_LDOUBLE; } "0x"[0-9a-fA-F]+ { char *aux = strndup(yytext, yyleng); - yylval.nint = strtoll(aux, NULL, 16); + yylval->nint = strtoll(aux, NULL, 16); free(aux); return TOK_INTEGER; } +"0x"[0-9a-fA-F]+[Uu] { char *aux = strndup(yytext, yyleng); + yylval->unint = strtoull(aux, NULL, 16); + free(aux); + return TOK_UINTEGER; } + "0b"[0-1]+ { char *aux = strndup(yytext+2, yyleng-2); - yylval.nint = strtoll(aux, NULL, 2); + yylval->unint = strtoull(aux, NULL, 2); free(aux); - return TOK_INTEGER; } + return TOK_UINTEGER; } -[0-9]+ { char *aux = strndup(yytext, yyleng); - yylval.nint = strtoll(aux, NULL, 10); +[0-9]+{EXP}[Uu] { char *aux = strndup(yytext, yyleng-1); + yylval->unint = (uint64_t)strtod(aux, NULL); + free(aux); + return TOK_UINTEGER; } + +[0-9]+{EXP} { char *aux = strndup(yytext, yyleng); + yylval->nint = (int64_t)strtod(aux, NULL); free(aux); return TOK_INTEGER; } -\"([^\\\"]|\\.)*\" { yylval.str = strndup(yytext+1, yyleng-2); - unescape(yylval.str); +\"([^\\\"]|\\.)*\" { yylval->str = strndup(yytext+1, yyleng-2); + unescape(yylval->str); return TOK_STRING; } +'\\?.' { char *aux = strndup(yytext+1, yyleng-2); + unescape(aux); + yylval->nint = aux[0]; + free(aux); + return TOK_CHAR; } + /* deixar por último. Caractere não reconhecido pelo alfabeto. */ -. { yyerror("lexical error, caractere nao pertence ao alfabeto da linguagem:"); } +. { yyerror(yylloc, NULL, string_format(COLOR_RED "lexical error:" COLOR_RED " unknown char '%c'.", yytext[0]).c_str()); } %% +void update_loc(location_t *loc, int lineno, int leng, char *text) { + loc->first_line = loc->last_line; + loc->first_column = loc->last_column; + if (loc->last_line == 0) { // first call + loc->last_line = lineno; + loc->last_column += leng; + } else if (loc->last_line == lineno) + loc->last_column += leng; + else { + loc->last_line = lineno; + loc->last_column = text + leng - strrchr(text, '\n'); + } +} + +#ifdef __MINGW64__ +char *strndup(const char *s, size_t n) { + size_t len = strnlen(s, n); + char *newstr = (char*)malloc(len+1); + if (!newstr) + return NULL; + newstr[len] = '\0'; + return (char*)memcpy(newstr, s, len); +} +#endif diff --git a/src/Language.y b/src/Language.y index 30ed9e4..d41044b 100644 --- a/src/Language.y +++ b/src/Language.y @@ -1,356 +1,504 @@ -%{ -#include -#include -#include "Header.h" -#include "2018arm/nodeh_ext.h" - -class Node; -class Stmts; - -Node* getNodeForIntConst(int64_t i); -std::vector vectorglobal; - -extern int errorsfound; +%name-prefix="MAIN" +//%define api.prefix {MAIN} // not working in Bison 3.8.2 +%define parse.error verbose -%} +%code provides { + #define YY_DECL int MAINlex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) + YY_DECL; + void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); + Node* get_compound_node(Node *load, char op, Node *right); +} -%define parse.error verbose +%type globals type_stmts enum_items interface_decls +%type stmts stmts_rec elseblock +%type global register interface type type_stmt use +%type function function_decl function_impl returnblock +%type enum enum_item interface_impl +%type simplevar_decl call_or_cast complexvar_set +%type expr factor stmt condblock whileblock +%type TOK_AND TOK_OR event +%type bind asminline compound_left +%type type_impls -%token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST -%token TOK_IF TOK_ELSE -%token TOK_LOOP TOK_WHILE -%token TOK_PRINT -%token TOK_IN TOK_OUT TOK_STEPPER TOK_SERVO -%token TOK_DELAY TOK_AND TOK_OR -%token TOK_IDENTIFIER TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE -%token TOK_FINT8 TOK_FINT16 TOK_FINT32 TOK_FINT64 -%token TOK_FFLOAT TOK_FDOUBLE TOK_FCHAR TOK_FLONG TOK_FUNSIGNED TOK_FBOOL - -%token TOK_QUANDO TOK_ESTA -%token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT - -%union { - char *port; - char *ident; - char *str; - int64_t nint; - float nfloat; - double ndouble; - long double nldouble; - Node *node; - Stmts *stmt; - ArrayElement ae; - ArrayElements *aes; - MatrixElement me; - MatrixElements *mes; - FunctionParam fp; - FunctionParams *fps; - ParamsCall *pc; - LanguageDataType dt; -} - -%type term term2 expr factor stmt gstmt condblock elseblock whileblock logicexpr -%type logicterm logicfactor TOK_AND TOK_OR printstmt fe eventblock unary -%type funcblock returnblock registerstmt cast %type element -%type elements relements -%type funcparam -%type funcparams -%type paramscall +%type elements relements array %type melement -%type matrix rmatrix -%type stmts gstmts -%type TOK_OUT TOK_IN -%type TOK_INTEGER +%type melements matrix + +%type function_params +%type function_param +%type paramscall + +%type TOK_IDENTIFIER TOK_XIDENTIFIER ident_or_xident +%type TOK_CHAR +%type TOK_INTEGER qualifier bind_scope +%type TOK_UINTEGER %type TOK_FLOAT %type TOK_DOUBLE %type TOK_LDOUBLE -%type TOK_IDENTIFIER %type TOK_STRING -%type TOK_STEPPER -%type
type_f registertype - -%precedence IFX -%precedence TOK_ELSE -%start programa +%type function_attributes +%type function_attribute + +/* operator precedences */ +%left TOK_OR +%left TOK_AND +%left '|' +%left '^' +%left '&' +%left EQ_OP NE_OP +%left LT_OP GT_OP LE_OP GE_OP +%left TOK_LSHIFT TOK_RSHIFT +%left '+' '-' +%left '*' '/' '%' +%right UMINUS '!' '~' +/*%left '(' ')'*/ %% -programa : gstmts { Program p($1); - // interruptions setup - for(AttachInterrupt *a : vectorglobal) { - $1->prepend(a); - } - - /*std::fstream fs; - fs.open("ast", std::fstream::out); - PrintAstVisitor(fs).visit(p); - fs.close();*/ - if (errorsfound == 0) - p.generate(); - }; - ; - -gstmts : gstmts gstmt { $1->append($2); } - | gstmt { $$ = new Stmts($1); } - ; +programa : %empty + +programa : globals { + for(auto stmt : *($globals)) { + program->addChild(stmt); + } +}; + +globals : globals global { + if ($global) { + $1->push_back($global); + } +} + +globals : global { + $$ = new vector(); + if ($global) { + $global->setLocation(@global); + $$->push_back($global); + } +} + +global : use + | interface + | type + | register + | function + | event + | enum + | simplevar_decl ';' + | qualifier simplevar_decl ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } + | bind + +use : TOK_USE TOK_IDENTIFIER ';' { + parseUseFile($2, @TOK_USE); + $$ = NULL; +} + +use : TOK_USE TOK_XIDENTIFIER ';' { + parseUseFile($2, @TOK_USE); + $$ = NULL; +} + +enum : TOK_ENUM TOK_IDENTIFIER[id] '{' enum_items '}' { + $$ = new Enum($id, std::move(*$enum_items), @id); +} + +enum_items : enum_items[items] ',' enum_item { + $items->push_back($enum_item); + $$ = $1; +} + +enum_items : enum_item { + $$ = new vector(); + $$->push_back($enum_item); +} + +enum_item : TOK_IDENTIFIER[id] '=' TOK_INTEGER[intg] { + $$ = new NamedConst($id, new Int8($intg, @id)); +} + +enum_item : TOK_IDENTIFIER[id] '=' '-' TOK_INTEGER[intg] { + $$ = new NamedConst($id, new Int8($intg * -1, @id)); +} -gstmt : TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($1, $3, qnone); } - | TOK_CONST TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qconst); } - | TOK_VOLATILE TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qvolatile); } - | TOK_IDENTIFIER '=' relements ';' { $$ = new Array($1, $3); } - | TOK_IDENTIFIER '=' rmatrix ';' { $$ = new Matrix($1, $3);} - | registerstmt ';' { $$ = $1; } - | fe { $$ = $1; } - | error ';' { /* error recovery until next ';' */ - $$ = new Int8(0); // evita falha de segmentacao - }; - -fe : funcblock { $$ = $1; } - | eventblock { $$ = $1; } - ; - -funcblock : type_f TOK_IDENTIFIER '(' funcparams ')' ';' { - $$ = new FunctionDeclExtern($1, $2, $4); - } - | type_f TOK_IDENTIFIER '(' funcparams ')' '{' stmts '}' { - $$ = new FunctionDecl($1, $2, $4, $7); - } - ; - -eventblock : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}' { - char funcname[100]; +enum_item : TOK_IDENTIFIER[id] '=' TOK_UINTEGER[intg] { + $$ = new NamedConst($id, new UInt8($intg, @id)); +} + +enum_item : TOK_IDENTIFIER[id] { + $$ = new NamedConst($id, @id); +} + +function : function_decl | function_impl + +function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' function_attributes[fa] ';' { + FunctionDecl *func = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params, @id); + func->setAttributes($fa); + $$ = func; +} + +function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' function_attributes[fa] '{' stmts '}'[ef] { + FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, + std::move(*$stmts), @id, @ef); + func->setAttributes($fa); + $$ = func; +} + +function_attributes: function_attributes[fas] ',' function_attribute[fa] { + $fas->addAttribute($fa); + $$ = $fas; +} + +function_attributes : function_attribute[fa] { + $$ = new FunctionAttributes(); + $$->addAttribute($fa); +} + +function_attributes : %empty { + $$ = new FunctionAttributes(); +} + +function_attribute + : TOK_WEAK { $$ = new FunctionAttribute(fa_weak, ""); } + | TOK_INLINE { $$ = new FunctionAttribute(fa_inline, ""); } + | TOK_NOINLINE { $$ = new FunctionAttribute(fa_noinline, ""); } + | TOK_NAKED { $$ = new FunctionAttribute(fa_naked, ""); } + | TOK_SIGNAL { $$ = new FunctionAttribute(fa_signal, ""); } + | TOK_DEBUGONLY { $$ = new FunctionAttribute(fa_debugonly, ""); } + | TOK_NOOPT { $$ = new FunctionAttribute(fa_noopt, ""); } + | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } + +event : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { + /*char funcname[100]; snprintf(funcname, 100, "__callback_int_p%d_e%d", (int)$2, (int)$4); vectorglobal.push_back(new AttachInterrupt($2, funcname, $4)); FunctionParams *fps = new FunctionParams(); - $$ = new FunctionDecl(tvoid, funcname, fps, $6); + $$ = new FunctionImpl(tvoid, funcname, fps, $6, @ef);*/ + return 0; } ; -stmts : stmts stmt { $1->append($2); - $$ = $1; } - | stmt { $$ = new Stmts($1); } - ; - -stmt : gstmt { $$ = $1; } - | TOK_OUT '=' expr ';' { $$ = new OutPort($1, $3); } - | TOK_IDENTIFIER '(' paramscall ')' ';' { $$ = new FunctionCall($1, $3); } - | TOK_IDENTIFIER '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '+', new Int8(1))); } - | TOK_IDENTIFIER '-' '-' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '-', new Int8(1))); } - | TOK_IDENTIFIER '+' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '+', $4)); } - | TOK_IDENTIFIER '-' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '-', $4)); } - | TOK_IDENTIFIER '*' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '*', $4)); } - | TOK_IDENTIFIER '/' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '/', $4)); } - | TOK_IDENTIFIER '|' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '|', $4)); } - | TOK_IDENTIFIER '&' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '&', $4)); } - | TOK_IDENTIFIER '^' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '^', $4)); } - | TOK_DELAY expr';' { $$ = new Delay($2); } - | condblock { $$ = $1; } - | whileblock { $$ = $1; } - | returnblock ';' { $$ = $1; } - | printstmt ';' { $$ = $1; } - | TOK_STEPPER expr ';' { $$ = new StepperGoto($1, $2); } - | TOK_SERVO expr ';' { $$ = new ServoGoto($2); } - | TOK_IDENTIFIER '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6);} - | TOK_IDENTIFIER '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9); } - -rmatrix : '{' matrix '}' { $$ = $2; } - ; - -matrix : matrix ',' melement { $1->append($3); - $$ = $1; } - | melement { MatrixElements *mes = new MatrixElements(); - mes->append($1); - $$ = mes; } - ; +qualifier : TOK_CONST { $$ = qconst; } + | TOK_VOLATILE { $$ = qvolatile; } +function_params: function_params ',' function_param { + $1 -> append($3); + $$ = $1; +} + +function_params: function_param { + FunctionParams *fps = new FunctionParams(); + fps->append($1); + $$ = fps; +} + +function_params: %empty { + FunctionParams *fps = new FunctionParams(); + $$ = fps; +} + +function_param : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] { + $$ = new Variable($id, buildTypes->getType($type, true), @type); +} + +function_param : TOK_IDENTIFIER[type] '[' ']' TOK_IDENTIFIER[id] { + $$ = new ParamArray($id, $type, @type); +} + +function_param : TOK_IDENTIFIER[type] '[' ']' '[' ']' TOK_IDENTIFIER[id] { + $$ = new ParamMatrix($id, $type, @type); +} + +register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT expr ';' { + $$ = new Pointer($name, buildTypes->getType($type, true), $5, @name); + $$->setQualifier(qvolatile); +} + +interface : TOK_INTF TOK_IDENTIFIER[id] '{' interface_decls[intf] '}' { + $$ = new Interface($id, std::move(*$intf), @id); +} -melement : relements ':' TOK_INTEGER { MatrixElement me {$1, (unsigned)$3}; - $$ = me; } - | relements { MatrixElement me {$1, 1}; - $$ = me; } - ; +interface : TOK_INTF TOK_IDENTIFIER[id] '{' '}' { + $$ = new Interface($id, @id); +} + +interface_decls : interface_decls function_decl { + $1->push_back($function_decl); + $$ = $1; +} + +interface_decls : function_decl { + $$ = new vector(); + $$->push_back($function_decl); +} + +interface_impl : TOK_IDENTIFIER[id] TOK_IMPL TOK_IDENTIFIER[intfname] '{' type_stmts '}' { + vector intf; + intf.push_back($intfname); + UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(intf), @id); + $$ = ut; +} + +type : TOK_TYPE TOK_IDENTIFIER[id] TOK_IMPL type_impls '{' type_stmts '}' { + UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(*$type_impls), @id); + $$ = ut; +} + +type : TOK_TYPE TOK_IDENTIFIER[id] '{' type_stmts '}' { + UserType *ut = new UserType($id, std::move(*$type_stmts), @id); + $$ = ut; +} + +type_impls : type_impls ',' TOK_IDENTIFIER { + $1->push_back($TOK_IDENTIFIER); + $$ = $1; +} + +type_impls : TOK_IDENTIFIER { + $$ = new vector(); + $$->push_back($1); +} + +type_stmts : type_stmts type_stmt { + if ($type_stmt) + $$->push_back($type_stmt); +} + +type_stmts : type_stmt { + $$ = new vector(); + if ($type_stmt) + $$->push_back($type_stmt); +} + +type_stmt : simplevar_decl ';' + | qualifier[q] simplevar_decl ';' { $simplevar_decl->setQualifier((DataQualifier)$q); $$ = $2; } + | function_impl + | interface_impl + | enum + +simplevar_decl : TOK_IDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array, @id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix, @id); } + +bind : TOK_BIND ident_or_xident[id] TOK_TO ident_or_xident[to] bind_scope[scope] ';' { + injections.insert({$to, new Injection($id, $to, BindScope($scope), @id)}); + $$ = NULL; +} + +bind_scope : TOK_SINGLETON { $$ = bs_singleton; } + | TOK_TRANSIENT { $$ = bs_transient; } + +array : '{' elements '}' { $$ = $elements; } +matrix : '{' melements '}' { $$ = $melements; } + +melements : melements ',' melement { + $1->append($3); + $$ = $1; +} + +melements : melement { + MatrixElements *mes = new MatrixElements(@melements); + mes->append($1); + $$ = mes; +} + +melement : relements ':' TOK_INTEGER { $$ = new MatrixElement($1, (unsigned)$3); } + | relements { $$ = new MatrixElement($1, 1);} relements : '{' elements '}' { $$ = $2; } - ; elements : elements ',' element { $1->append($3); $$ = $1; } - | element { ArrayElements *aes = new ArrayElements(); + | element { ArrayElements *aes = new ArrayElements(@element); aes->append($1); $$ = aes; } - ; - -element : factor ':' TOK_INTEGER { ArrayElement ae{$1, (unsigned)$3}; - $$ = ae; } - | factor { ArrayElement ae{$1, 1}; - $$ = ae; } - ; - -funcparams: funcparams ',' funcparam { - $1 -> append($3); - $$ = $1; - } - | funcparam { - FunctionParams *fps = new FunctionParams(); - fps->append($1); - $$ = fps; - } - | %empty { - FunctionParams *fps = new FunctionParams(); - $$ = fps; - } - ; - -funcparam : type_f TOK_IDENTIFIER { - FunctionParam fp{$2, $1}; - $$ = fp; - } - -type_f : TOK_VOID { $$ = tvoid; } - | TOK_FCHAR { $$ = tchar; } - | TOK_FBOOL { $$ = tbool; } - | TOK_FINT8 { $$ = tint8; } - | TOK_FINT16 { $$ = tint16; } - | TOK_FINT32 { $$ = tint32; } - | TOK_FINT64 { $$ = tint64; } - | TOK_FUNSIGNED TOK_FINT8 { $$ = tint8u; } - | TOK_FUNSIGNED TOK_FINT16 { $$ = tint16u; } - | TOK_FUNSIGNED TOK_FINT32 { $$ = tint32u; } - | TOK_FUNSIGNED TOK_FINT64 { $$ = tint64u; } - | TOK_FFLOAT { $$ = tfloat; } - | TOK_FDOUBLE { $$ = tdouble; } - | TOK_FLONG TOK_FDOUBLE { $$ = tldouble; } - ; - -paramscall : paramscall ',' expr {$1 -> append($3); - $$ = $1;} - | expr { ParamsCall *pc = new ParamsCall(); - pc->append($1); - $$ = pc;} - | %empty { ParamsCall *pc = new ParamsCall(); - $$ = pc; - } - ; + +element : expr ':' TOK_INTEGER { $$ = new ArrayElement($1, (unsigned)$3); } + | expr { $$ = new ArrayElement($1, 1); } + +asminline : TOK_ASM TOK_STRING { $$ = new InlineAssembly($2, @1); } + | TOK_ASM TOK_STRING ':' TOK_STRING { $$ = new InlineAssembly($2, $4, @1); } + +stmts : %empty { $$ = new vector(); } + | stmts_rec + +stmts_rec : stmts_rec stmt { + $1->push_back($stmt); +} +stmts_rec : stmt { + $$ = new vector(); + $$->push_back($stmt); + $stmt->setLocation(@stmt); +} + +compound_left : ident_or_xident[id] { + $$ = new Load($id, @id); +} + +compound_left : ident_or_xident[id] '[' expr ']' { + $$ = new LoadArray($id, $expr, @id); +} + +compound_left : ident_or_xident[id] '[' expr[e1] ']' '[' expr[e2] ']' { + $$ = new LoadMatrix($id, $e1, $e2, @id); +} + +stmt : compound_left[cl] '+' '+' ';' { $$ = get_compound_node($cl, '+', new Int8(1, @cl)); } + | compound_left[cl] '-' '-' ';' { $$ = get_compound_node($cl, '-', new Int8(1, @cl)); } + | compound_left[cl] '+' '=' expr ';' { $$ = get_compound_node($cl, '+', $expr); } + | compound_left[cl] '-' '=' expr ';' { $$ = get_compound_node($cl, '-', $expr); } + | compound_left[cl] '*' '=' expr ';' { $$ = get_compound_node($cl, '*', $expr); } + | compound_left[cl] '/' '=' expr ';' { $$ = get_compound_node($cl, '/', $expr); } + | compound_left[cl] '|' '=' expr ';' { $$ = get_compound_node($cl, '|', $expr); } + | compound_left[cl] '&' '=' expr ';' { $$ = get_compound_node($cl, '&', $expr); } + | compound_left[cl] '^' '=' expr ';' { $$ = get_compound_node($cl, '^', $expr); } + + | ident_or_xident '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6, @1);} + | ident_or_xident '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9, @1); } + + | asminline ';' { $$ = $1; } + | qualifier simplevar_decl ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } + | simplevar_decl ';' + | complexvar_set ';' + | returnblock ';' + | call_or_cast ';' + | condblock + | whileblock + +complexvar_set : TOK_XIDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } +complexvar_set : TOK_XIDENTIFIER[id] '=' array { $$ = new Array($id, $array, @id); } +complexvar_set : TOK_XIDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix, @id); } returnblock : TOK_RETURN expr { $$ = new Return($2); } - | TOK_RETURN logicexpr { $$ = new Return($2); } - ; +returnblock : TOK_RETURN { $$ = new Return(@1); } -condblock : TOK_IF '(' logicexpr ')' stmt %prec IFX { $$ = new If($3, $5, NULL); } - | TOK_IF '(' logicexpr ')' stmt elseblock { $$ = new If($3, $5, $6); } - | TOK_IF '(' logicexpr ')' '{' stmts '}' %prec IFX { $$ = new If($3, $6, NULL); } - | TOK_IF '(' logicexpr ')' '{' stmts '}' elseblock { $$ = new If($3, $6, $8); } - ; +/* + * Conditional + */ -elseblock : TOK_ELSE stmt { $$ = $2; } - | TOK_ELSE '{' stmts '}' { $$ = $3; } - ; +condblock : TOK_IF expr '{' stmts '}' { + $expr->setLocation(@expr); + $$ = new If($expr, std::move(*$stmts), @TOK_IF); +} +condblock : TOK_IF expr '{' stmts '}' elseblock { + $expr->setLocation(@expr); + $$ = new If($expr, std::move(*$stmts), std::move(*$elseblock), @TOK_IF); +} -whileblock : TOK_WHILE '(' logicexpr ')' '{' stmts '}' { $$ = new While($3, $6); } - | TOK_LOOP '{' stmts '}' { $$ = new Loop($3); } - ; +elseblock : TOK_ELSE '{' stmts '}' { $$ = $stmts; } +elseblock : TOK_ELSE condblock { + auto *nodes = new vector(); + nodes->push_back($condblock); + $$ = nodes; +} -logicexpr : logicexpr TOK_OR logicterm { $$ = new BinaryOp($1, TOK_OR, $3); } - | logicterm { $$ = $1; } - ; - -logicterm : logicterm TOK_AND logicfactor { $$ = new BinaryOp($1, TOK_AND, $3); } - | logicfactor { $$ = $1; } - ; - -logicfactor : '(' logicexpr ')' { $$ = $2; } - | expr '=''=' expr { $$ = new CmpOp($1, EQ_OP, $4); } - | expr '!''=' expr { $$ = new CmpOp($1, NE_OP, $4); } - | expr '<''=' expr { $$ = new CmpOp($1, LE_OP, $4); } - | expr '>''=' expr { $$ = new CmpOp($1, GE_OP, $4); } - | expr '<' expr { $$ = new CmpOp($1, LT_OP, $3); } - | expr '>' expr { $$ = new CmpOp($1, GT_OP, $3); } - ; - -expr : expr '+' term { $$ = new BinaryOp($1, '+', $3); } - | expr '-' term { $$ = new BinaryOp($1, '-', $3); } - | expr '|' term { $$ = new BinaryOp($1, '|', $3); } - | expr TOK_LSHIFT term { $$ = new BinaryOp($1, TOK_LSHIFT, $3); } - | expr TOK_RSHIFT term { $$ = new BinaryOp($1, TOK_RSHIFT, $3); } - | term { $$ = $1; } - ; - -term : term '*' term2 { $$ = new BinaryOp($1, '*', $3); } - | term '/' term2 { $$ = new BinaryOp($1, '/', $3); } - | term '%' term2 { $$ = new BinaryOp($1, '%', $3); } - | term '^' term2 { $$ = new BinaryOp($1, '^', $3); } - | term2 { $$ = $1; } - ; - -term2 : term2 '&' factor { $$ = new BinaryOp($1, '&', $3); } - | factor { $$ = $1; } - ; - -factor : '(' expr ')' { $$ = $2; } - | TOK_IDENTIFIER { $$ = new Load($1); } - | TOK_IDENTIFIER '[' expr ']' { $$ = new LoadArray($1, $3);} - | TOK_IDENTIFIER '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6);} - | TOK_TRUE { $$ = new Int1(1); } - | TOK_FALSE { $$ = new Int1(0); } - | TOK_INTEGER { $$ = getNodeForIntConst($1); } - | TOK_FLOAT { $$ = new Float($1); } - | TOK_DOUBLE { $$ = new Double($1); } - | TOK_LDOUBLE { $$ = new Float128($1); } - | TOK_IN { $$ = new InPort($1); } - | TOK_IDENTIFIER '(' paramscall ')' { $$ = new FunctionCall($1, $3); } - | unary { $$ = $1; } - ; +/* + * Repetition + */ -unary : '-' factor { $$ = new BinaryOp($2, '*', getNodeForIntConst(-1)); } - | '~' factor { $$ = new FlipOp($2); } - | cast { $$ = $1; } - ; +whileblock : TOK_WHILE expr '{' stmts '}' { + $expr->setLocation(@expr); + $$ = new While($expr, std::move(*$stmts), @TOK_WHILE); +} -cast : '(' type_f ')' factor { $$ = new Cast($2, $4); } - ; +whileblock : TOK_WHILE expr ';' { + $expr->setLocation(@expr); + $$ = new While($expr, @TOK_WHILE); +} -printstmt : TOK_PRINT TOK_STRING { $$ = new Print(new String($2)); } - | TOK_PRINT expr { $$ = new Print($2); } +whileblock : TOK_LOOP '{' stmts '}' { + $$ = new Loop(std::move(*$stmts), @TOK_LOOP); +} -registerstmt : TOK_REGISTER registertype TOK_IDENTIFIER TOK_AT expr { - $$ = new Pointer($3, $2, $5, true); - } - ; +/* + * Logic and Arithmetic + */ + +// logic +expr: expr[e1] TOK_AND expr[e2] { $$ = new BinaryOp($e1, TOK_AND, $e2); } +expr: expr[e1] TOK_OR expr[e2] { $$ = new BinaryOp($e1, TOK_OR, $e2); } +expr: expr[e1] EQ_OP expr[e2] { $$ = new CmpOp($e1, EQ_OP, $e2, @EQ_OP); } +expr: expr[e1] NE_OP expr[e2] { $$ = new CmpOp($e1, NE_OP, $e2, @NE_OP); } +expr: expr[e1] LE_OP expr[e2] { $$ = new CmpOp($e1, LE_OP, $e2, @LE_OP); } +expr: expr[e1] GE_OP expr[e2] { $$ = new CmpOp($e1, GE_OP, $e2, @GE_OP); } +expr: expr[e1] LT_OP expr[e2] { $$ = new CmpOp($e1, LT_OP, $e2, @LT_OP); } +expr: expr[e1] GT_OP expr[e2] { $$ = new CmpOp($e1, GT_OP, $e2, @GT_OP); } +expr: '!'[op] expr[e] { $$ = new CmpOp($e, EQ_OP, new Int1(0, @e), @op); } + +// arithmetic +expr: expr[e1] '+' expr[e2] { $$ = new BinaryOp($e1, '+', $e2); } +expr: expr[e1] '-' expr[e2] { $$ = new BinaryOp($e1, '-', $e2); } +expr: expr[e1] '|' expr[e2] { $$ = new BinaryOp($e1, '|', $e2); } +expr: expr[e1] '*' expr[e2] { $$ = new BinaryOp($e1, '*', $e2); } +expr: expr[e1] '/' expr[e2] { $$ = new BinaryOp($e1, '/', $e2); } +expr: expr[e1] '%' expr[e2] { $$ = new BinaryOp($e1, '%', $e2); } +expr: expr[e1] '^' expr[e2] { $$ = new BinaryOp($e1, '^', $e2); } +expr: expr[e1] '&' expr[e2] { $$ = new BinaryOp($e1, '&', $e2); } +expr: expr[e1] TOK_LSHIFT expr[e2] { $$ = new BinaryOp($e1, TOK_LSHIFT, $e2); } +expr: expr[e1] TOK_RSHIFT expr[e2] { $$ = new BinaryOp($e1, TOK_RSHIFT, $e2); } +expr: '-' expr[e] %prec UMINUS { $$ = new BinaryOp($e, '*', getNodeForIntConst(-1, @e)); } +expr: '~' expr[e] { $$ = new FlipOp($e); } +expr: factor + +factor : '(' expr[e] ')' { $$ = $e; } + | ident_or_xident { $$ = new Load($1, @1); } + | TOK_TRUE { $$ = new Int1(1, @1); } + | TOK_FALSE { $$ = new Int1(0, @1); } + | TOK_CHAR { $$ = new Char($1, @1); } + | TOK_INTEGER { $$ = getNodeForIntConst($1, @1); } + | TOK_UINTEGER { $$ = getNodeForUIntConst($1, @1); } + | TOK_FLOAT { $$ = new Float($1, @1); } + | TOK_DOUBLE { $$ = new Double($1, @1); } + | TOK_LDOUBLE { $$ = new Float128($1, @1); } + | TOK_STRING { $$ = new StringConst("conststr", $1, @1); } + | ident_or_xident[id] '[' expr ']' { $$ = new LoadArray($1, $3, @id);} + | ident_or_xident[id] '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6, @id);} + | call_or_cast + ; -registertype : TOK_FINT8 { $$ = tint8; } - | TOK_FINT16 { $$ = tint16; } - | TOK_FINT32 { $$ = tint32; } - | TOK_FINT64 { $$ = tint64; } - ; -%% +ident_or_xident: TOK_IDENTIFIER | TOK_XIDENTIFIER + +call_or_cast : ident_or_xident[id] '(' paramscall ')' { + if (strncmp("copy", $id, 4) == 0 && $paramscall->getNumParams() == 1) + $$ = new MemCopy($paramscall->getParamElement(0)); + else if (strncmp("bitcast", $id, 7) == 0 && $paramscall->getNumParams() == 2) { + Node *nodeTy = $paramscall->getParamElement(1); + Load *load = dynamic_cast(nodeTy); + if (load && buildTypes->getType(load->getName()) != BuildTypes::undefinedType) { + DataType dt = buildTypes->getType(load->getName()); + $$ = new BitCast($paramscall->getParamElement(0), dt); + } else { + $$ = new FunctionCall($id, $paramscall, @id); + } + } else { + $$ = new FunctionCall($id, $paramscall, @id); + } + $$->setLocation(@id); +} -extern int yylineno; -extern int yycolno; -extern char *yytext; -extern char *build_filename; - -int yyerror(const char *s) -{ - fprintf(stderr, "%s:%d:%d: %s\n", - build_filename, yylineno, yycolno, s); - errorsfound++; - return 0; -} - -Node* getNodeForIntConst(int64_t i) { - if (i >= SCHAR_MIN && i <= SCHAR_MAX) - return new Int8(i); - else if (i >= SHRT_MIN && i <= SHRT_MAX) - return new Int16(i); - else if (i >= INT_MIN && i <= INT_MAX) - return new Int32(i); - else - return new Int64(i); +paramscall : paramscall ',' expr { + $1->append($3); + $$ = $1; } -extern "C" int yywrap() { - return 1; +paramscall : expr { + ParamsCall *pc = new ParamsCall(); + pc->append($1); + $$ = pc; } +paramscall : %empty { $$ = new ParamsCall(); } + +%% + +Node *get_compound_node(Node *load, char op, Node *right) { + if (dynamic_cast(load)) + return new Scalar(load->getName(), new BinaryOp(load, op, right)); + else if (LoadArray *la = dynamic_cast(load)) + return new UpdateArray(load->getName(), la->getPosition(), new BinaryOp(load, op, right), load->getLoc()); + else if (LoadMatrix *lm = dynamic_cast(load)) + return new UpdateMatrix(load->getName(), lm->getPosition(), lm->getPosition2(), new BinaryOp(load, op, right), load->getLoc()); + else + assert(false && "Unknown load node."); +} \ No newline at end of file diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y new file mode 100644 index 0000000..77b54be --- /dev/null +++ b/src/LanguageHeader.y @@ -0,0 +1,63 @@ + +%locations +%define api.location.type {location_t} +%define api.pure full +%define parse.lac full +%param {yyscan_t scanner} + +%code top { + #include + #include + #define SCANNER_OR_VISITOR + #include "Header.h" +} + +%code provides { + #ifndef YYLTYPE + #define YYLTYPE location_t + #endif + #include "FlexDependencies.h" +} + +%token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST TOK_ASM +%token TOK_IF TOK_ELSE +%token TOK_LOOP TOK_WHILE +%token TOK_AND TOK_OR +%token TOK_IDENTIFIER TOK_XIDENTIFIER +%token TOK_CHAR TOK_UINTEGER +%token TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE +%token TOK_FINT8 TOK_FINT16 TOK_FINT32 TOK_FINT64 +%token TOK_FFLOAT TOK_FDOUBLE TOK_FCHAR TOK_FLONG TOK_FUNSIGNED TOK_FBOOL +%token TOK_TYPE TOK_INTF TOK_IMPL TOK_USE TOK_ENUM + +%token TOK_BIND TOK_TO TOK_SINGLETON TOK_TRANSIENT + +%token TOK_QUANDO TOK_ESTA +%token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT + +%token TOK_INLINE TOK_NOINLINE TOK_WEAK TOK_SECTION TOK_NAKED TOK_SIGNAL TOK_DEBUGONLY TOK_NOOPT + +%union { + char *ident; + char *str; + char ch; + int64_t nint; + uint64_t unint; + float nfloat; + double ndouble; + long double nldouble; + Node *node; + ArrayElements *aes; + MatrixElements *mes; + FunctionParams *fps; + FunctionAttributes *fattrs; + FunctionAttribute *fattr; + ParamsCall *pc; + vector *nodes; + vector *strings; + ArrayElement *ae; + MatrixElement *me; + Variable *fp; +} + +%start programa diff --git a/src/LanguageUse.y b/src/LanguageUse.y new file mode 100644 index 0000000..e56932a --- /dev/null +++ b/src/LanguageUse.y @@ -0,0 +1,442 @@ + +%name-prefix="USE" +//%define api.prefix {USE} // not working in Bison 3.8.2 +%define parse.error verbose + +// enable this to trace the parser. Also, set USEDebug=1 at Scanner.cpp. +%define parse.trace + +%code provides { + #define YY_DECL int USElex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) + YY_DECL; + void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); +} + +%type globals type_stmts enum_items interface_decls +%type stmts stmts_rec +%type global register interface type type_stmt use +%type function function_decl function_impl +%type enum enum_item const_expr expr unary interface_impl +%type simplevar_decl cast constructor +%type ignore_stmt ignore_param ignore +%type type_impls + +%type element +%type elements relements array +%type melement +%type melements matrix + +%type function_params +%type function_param + +%type TOK_IDENTIFIER TOK_XIDENTIFIER +%type TOK_INTEGER qualifier +%type TOK_UINTEGER +%type TOK_FLOAT +%type TOK_DOUBLE +%type TOK_LDOUBLE +%type TOK_CHAR + +%type function_attributes +%type function_attribute + +%printer { fprintf(yyo, "'%s'", $$); } +%printer { fprintf(yyo, "'%s'", $$ ? $$->getName().c_str() : ""); } + +%% + +programa : globals { + for(auto stmt : *($globals)) { + program->addChild(stmt); + } +} + +globals : globals global { + if ($global) { + $1->push_back($global); + } +} + +globals : global { + $$ = new vector(); + if ($global) { + $global->setLocation(@global); + $$->push_back($global); + } +} + +global : use + | interface + | type + | register + | function + | enum + | simplevar_decl ';' { $$ = NULL; } // don't export global vars + +global : qualifier simplevar_decl ';' { + if ($qualifier == qconst) + $$ = $simplevar_decl; + else + $$ = NULL; +} + +use : TOK_USE TOK_IDENTIFIER ';' { + parseUseFile($2, @TOK_USE); + $$ = NULL; +} + +use : TOK_USE TOK_XIDENTIFIER ';' { + parseUseFile($2, @TOK_USE); + $$ = NULL; +} + +enum : TOK_ENUM TOK_IDENTIFIER[id] '{' enum_items '}' { + $$ = new Enum($id, std::move(*$enum_items), @id); +} + +enum_items : enum_items[items] ',' enum_item { + $items->push_back($enum_item); + $$ = $1; +} + +enum_items : enum_item { + $$ = new vector(); + $$->push_back($enum_item); +} + +enum_item : TOK_IDENTIFIER[id] '=' TOK_INTEGER[intg] { + $$ = new NamedConst($id, new Int8($intg, @id)); +} + +enum_item : TOK_IDENTIFIER[id] '=' '-' TOK_INTEGER[intg] { + $$ = new NamedConst($id, new Int8($intg * -1, @id)); +} + +enum_item : TOK_IDENTIFIER[id] '=' TOK_UINTEGER[intg] { + $$ = new NamedConst($id, new UInt8($intg, @id)); +} + +enum_item : TOK_IDENTIFIER[id] { + $$ = new NamedConst($id, @id); +} + +function : function_decl | function_impl + +function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' function_attributes[fa] ';' { + FunctionDecl *func = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params, @id); + func->setAttributes($fa); + $$ = func; +} + +function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' function_attributes[fa] '{' stmts_rec '}'[ef] { + vector stmts; + FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, + std::move(stmts), @type, @ef); + func->setExternal(true); + func->setDeclaration(true); + func->setAttributes($fa); + $$ = func; +} + +function_attributes: function_attributes[fas] ',' function_attribute[fa] { + $fas->addAttribute($fa); + $$ = $fas; +} + +function_attributes : function_attribute[fa] { + $$ = new FunctionAttributes(); + $$->addAttribute($fa); +} + +function_attributes : %empty { + $$ = new FunctionAttributes(); +} + +function_attribute + : TOK_WEAK { $$ = new FunctionAttribute(fa_weak, ""); } + | TOK_INLINE { $$ = new FunctionAttribute(fa_inline, ""); } + | TOK_NOINLINE { $$ = new FunctionAttribute(fa_noinline, ""); } + | TOK_NAKED { $$ = new FunctionAttribute(fa_naked, ""); } + | TOK_SIGNAL { $$ = new FunctionAttribute(fa_signal, ""); } + | TOK_DEBUGONLY { $$ = new FunctionAttribute(fa_debugonly, ""); } + | TOK_NOOPT { $$ = new FunctionAttribute(fa_noopt, ""); } + | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } + +qualifier : TOK_CONST { $$ = qconst; } + | TOK_VOLATILE { $$ = qvolatile; } + +function_params: function_params ',' function_param { + $1 -> append($3); + $$ = $1; +} + +function_params: function_param { + FunctionParams *fps = new FunctionParams(); + fps->append($1); + $$ = fps; +} + +function_params: %empty { + FunctionParams *fps = new FunctionParams(); + $$ = fps; +} + +function_param : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] { + $$ = new Variable($id, buildTypes->getType($type, true), @type); +} + +function_param : TOK_IDENTIFIER[type] '[' ']' TOK_IDENTIFIER[id] { + $$ = new ParamArray($id, $type, @type); +} + +function_param : TOK_IDENTIFIER[type] '[' ']' '[' ']' TOK_IDENTIFIER[id] { + $$ = new ParamMatrix($id, $type, @type); +} + +register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT const_expr ';' { + $$ = new Pointer($name, buildTypes->getType($type, true), $5, @name); + $$->setQualifier(qvolatile); +} + +interface : TOK_INTF TOK_IDENTIFIER[id] '{' interface_decls[intf] '}' { + $$ = new Interface($id, std::move(*$intf), @id); +} + +interface : TOK_INTF TOK_IDENTIFIER[id] '{' '}' { + $$ = new Interface($id, @id); +} + +interface_decls : interface_decls function_decl { + $1->push_back($function_decl); + $$ = $1; +} + +interface_decls : function_decl { + $$ = new vector(); + $$->push_back($function_decl); +} + +interface_impl : TOK_IDENTIFIER[id] TOK_IMPL TOK_IDENTIFIER[intfname] '{' type_stmts '}' { + vector intf; + intf.push_back($intfname); + UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(intf), @id); + $$ = ut; +} + +type : TOK_TYPE TOK_IDENTIFIER[id] TOK_IMPL type_impls '{' type_stmts '}' { + UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(*$type_impls), @id); + ut->setDeclaration(true); + $$ = ut; +} + +type : TOK_TYPE TOK_IDENTIFIER[id] '{' type_stmts '}' { + UserType *ut = new UserType($id, std::move(*$type_stmts), @id); + ut->setDeclaration(true); + $$ = ut; +} + +type_impls : type_impls ',' TOK_IDENTIFIER { + $1->push_back($TOK_IDENTIFIER); + $$ = $1; +} + +type_impls : TOK_IDENTIFIER { + $$ = new vector(); + $$->push_back($1); +} + +type_stmts : type_stmts type_stmt { + if ($type_stmt) + $$->push_back($type_stmt); +} + +type_stmts : type_stmt { + $$ = new vector(); + if ($type_stmt) + $$->push_back($type_stmt); +} + +type_stmt : simplevar_decl ';' + | qualifier[q] simplevar_decl ';' { $simplevar_decl->setQualifier((DataQualifier)$q); $$ = $2; } + | function_impl + | interface_impl + | enum + +simplevar_decl : TOK_IDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array, @id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix, @id); } + +array : '{' elements '}' { $$ = $elements; } +matrix : '{' melements '}' { $$ = $melements; } + +melements : melements ',' melement { + $1->append($3); + $$ = $1; +} + +melements : melement { + MatrixElements *mes = new MatrixElements(@melements); + mes->append($1); + $$ = mes; +} + +melement : relements ':' TOK_INTEGER { $$ = new MatrixElement($1, (unsigned)$3); } + | relements { $$ = new MatrixElement($1, 1);} + +relements : '{' elements '}' { $$ = $2; } + +elements : elements ',' element { $1->append($3); + $$ = $1; } + | element { ArrayElements *aes = new ArrayElements(@element); + aes->append($1); + $$ = aes; } + +element : expr ':' TOK_INTEGER { $$ = new ArrayElement($1, (unsigned)$3); } + | expr { $$ = new ArrayElement($1, 1); } + +const_expr : TOK_INTEGER { $$ = getNodeForIntConst($1, @1); } + | TOK_UINTEGER { $$ = getNodeForUIntConst($1, @1); } + | TOK_CHAR { $$ = new Char($1, @1); } + | TOK_TRUE { $$ = new Int1(1, @1); } + | TOK_FALSE { $$ = new Int1(0, @1); } + | TOK_FLOAT { $$ = new Float($1, @1); } + | TOK_DOUBLE { $$ = new Double($1, @1); } + | TOK_LDOUBLE { $$ = new Float128($1, @1); } + | unary { $$ = $1; } + //TODO: Add other constant nodes here! + +unary : '-' const_expr { $$ = new BinaryOp($const_expr, '*', getNodeForIntConst(-1, @const_expr)); } + | '~' const_expr { $$ = new FlipOp($const_expr); } + ; + +expr : const_expr + | cast + | constructor + //TODO: Add other expr nodes here! + +cast : TOK_IDENTIFIER[id] '(' ignore_param ')' { + ParamsCall *pc = new ParamsCall(); + pc->append(new Node(@id)); + $$ = new FunctionCall($id, pc, @id); + $$->setLocation(@id); +} + +constructor : TOK_IDENTIFIER[id] '(' ')' { + ParamsCall *pc = new ParamsCall(); + pc->append(new Node(@id)); + $$ = new FunctionCall($id, pc, @id); + $$->setLocation(@id); +} + +ignore_param : ignore_p { $$ = NULL; } + | error { $$ = NULL; } + +/* put here any symbol that can start a expr. + * to be precise, the FIRST(expr) + */ +ignore_p : TOK_INTEGER { YYERROR; } + | TOK_IDENTIFIER { YYERROR; } + +stmts_rec : %empty { $$ = NULL; } + | stmts { $$ = NULL; } + +stmts : stmts ignore_stmt { $$ = NULL; } + | ignore_stmt { $$ = NULL; } + +ignore_stmt : ignore { $$ = NULL; } + | error '{' stmts '}' { $$ = NULL; } + | error ';' { $$ = NULL; } + +/* put here any symbol that can start a stmt (except globals). + * to be precise, the FIRST(stmt) of Language.y + */ +ignore : TOK_IDENTIFIER { YYERROR; } + | TOK_XIDENTIFIER { YYERROR; } + | TOK_WHILE { YYERROR; } + | TOK_RETURN { YYERROR; } + | TOK_CONST { YYERROR; } + | TOK_VOLATILE { YYERROR; } + | TOK_IF { YYERROR; } + | TOK_ELSE { YYERROR; } + | TOK_LOOP { YYERROR; } + | TOK_ASM { YYERROR; } + +%% + +/*static const char * +error_format_string (int argc) +{ + switch (argc) + { + default: // Avoid compiler warnings. + case 0: return "%@: syntax error"; + case 1: return "%@: syntax error: unexpected %u"; + // TRANSLATOR '%@' is a location in a file, '%u' is an + // "unexpectetoken", and '%0e', '%1e'... are expected tokens + // at this pot. + // + // For instan on the expression "1 + * 2", you'd get + // + // 1.5: syntaerror: expected - or ( or number or function or variable before * + case 2: return "%@: syntax error: expected %0e before %u"; + case 3: return "%@: syntax error: expected %0e or %1e before %u"; + case 4: return "%@: syntax error: expected %0e or %1e or %2e before %u"; + case 5: return "%@: syntax error: expected %0e or %1e or %2e or %3e before %u"; + case 6: return "%@: syntax error: expected %0e or %1e or %2e or %3e or %4e before %u"; + case 7: return "%@: syntax error: expected %0e or %1e or %2e or %3e or %4e or %5e before %u"; + case 8: return "%@: syntax error: expected %0e or %1e or %2e or %3e or %4e or %5e etc., before %u"; + } +} + +static int yyreport_syntax_error (const yypcontext_t *ctx, yyscan_t scanner) { + enum { ARGS_MAX = 6 }; + yysymbol_kind_t arg[ARGS_MAX]; + + int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX); + if (argsize < 0) + return argsize; + + const int too_many_expected_tokens = argsize == 0 && arg[0] != YYSYMBOL_YYEMPTY; + if (too_many_expected_tokens) + argsize = ARGS_MAX; + + const char *format = error_format_string (1 + argsize + too_many_expected_tokens); + + const YYLTYPE *loc = yypcontext_location (ctx); + while (*format) { + // %@: location. + if (format[0] == '%' && format[1] == '@') { + fprintf(stderr, "%s:%d:%d:", build_filename(), + loc->first_line, loc->first_column); + format += 2; + } + // %u: unexpected token. + else if (format[0] == '%' && format[1] == 'u') { + fputs (yysymbol_name (yypcontext_token (ctx)), stderr); + format += 2; + } + // %0e, %1e...: expected token. + else if (format[0] == '%' && isdigit ((unsigned char) format[1]) + && format[2] == 'e' && (format[1] - '0') < argsize) { + + int i = format[1] - '0'; + fputs (yysymbol_name (arg[i]), stderr); + format += 3; + } else { + fputc (*format, stderr); + ++format; + } + } + fputc ('\n', stderr); + + // Quote the source line. + { + fprintf (stderr, "%5d | %s\n", loc->first_line, uctx->line); + fprintf (stderr, "%5s | %*s", "", loc->first_column, "^"); + for (int i = loc->last_column - loc->first_column - 1; 0 < i; --i) + putc ('~', stderr); + putc ('\n', stderr); + } + + return 0; +}*/ diff --git a/src/Load.cpp b/src/Load.cpp index 89a04c5..634fb2b 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -1,58 +1,159 @@ -#include "Header.h" - -Type* Load::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { - auto rsym = search_symbol(ident, allocblock, block); - if (rsym) { - if (auto *lvalue = dyn_cast(rsym->value)) - return lvalue->getAllocatedType(); - else if (auto *lvalue = dyn_cast(rsym->value)) - return lvalue->getValueType(); - else - return rsym->pointerType; - } - return NULL; + +#include "Load.h" +#include "BuildTypes.h" +#include "FunctionImpl.h" +#include "Variable.h" +#include "Pointer.h" + +Node* Load::getIdentSymbol(bool showError) { + if (!identSymbol) { + identSymbol = ident.getSymbol(getScope(), false); + } + if (!identSymbol && showError) + yyerrorcpp("Symbol " + ident.getFullName() + " not found.", this); + return identSymbol; +} + +DataType Load::getDataType() { + if (dt == BuildTypes::undefinedType) { + if (getIdentSymbol()) + dt = identSymbol->getDataType(); + } + return dt; } -Value* Load::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - auto rsym = search_symbol(ident, allocblock, block); - if (rsym == NULL) { - yyerrorcpp("Variable " + ident + " not defined.", this); +Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + if (!identSymbol) { + identSymbol = ident.getSymbol(getScope(), false); + if (!identSymbol) { + identSymbol = ident.getSymbol(func, false); + //assert(false && "when this is executed?");//FIXME + } + } + + if (identSymbol && identSymbol->isConstExpr()) + return identSymbol->getLLVMValue(func); + + Variable *symbol = dynamic_cast(identSymbol); + if (!symbol) { + yyerrorcpp("Symbol " + ident.getFullName() + " not found.", this); return NULL; } - auto sym = rsym->value; - if (rsym->qualifier == qconst) - return sym; + dt = identSymbol->getDataType(); if (block == NULL && (allocblock == NULL || allocblock == global_alloc)) { // trying to load a variable to initialize a global one. // permitted only for const globals - if (rsym->qualifier != qconst) { - yyerrorcpp("Can't not use '" + ident + "' to define another var/const in global context.", this); + if (!symbol->hasQualifier(qconst)) { + yyerrorcpp("Can not use '" + ident.getFullName() + "' to define another var/const in global context.", this); return NULL; } } + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + Value *alloc = NULL; + if (ident.isComplex()) { + Identifier istem = ident.getStem(); + Node *stem = istem.getSymbol(getScope()); - LoadInst *ret = NULL; - bool vol = rsym->qualifier == qvolatile; - if (auto *lvalue = dyn_cast(sym)) - ret = new LoadInst(lvalue->getAllocatedType(), sym, ident, vol, block); - else if (auto *lvalue = dyn_cast(sym)) - ret = new LoadInst(lvalue->getValueType(), sym, ident, vol, block); - else if (rsym->pointerType != NULL) - ret = new LoadInst(rsym->pointerType, sym, ident, vol, block); - else { - printf("ERR: Going to return NULL!\n"); - } + // Pointers need a custom procedure: load the stem and get the + // requested bit value through bit shifting + Pointer *reg = dynamic_cast(stem); + if (reg && buildTypes->isComplex(reg->getDataType())) { + alloc = reg->getLLVMValue(NULL); + Type *req_eq_ty = Type::getIntNTy(global_context, buildTypes->bitWidth(reg->getDataType())); + Value *v = Builder->CreateLoad(req_eq_ty, alloc, reg->hasQualifier(qvolatile), "ptrvalue"); + /* this code does: + * v = symbol->value << pointerbits - field_start - field_width + * v = v >> pointer_bits - field_width + */ + int bs = buildTypes->bitWidth(reg->getDataType()) - buildTypes->bitWidth(symbol->getDataType()); + unsigned fieldStartBit = reg->getFieldStartBit(symbol); + if (bs - fieldStartBit > 0) + v = Builder->CreateShl(v, ConstantInt::get(req_eq_ty, bs - fieldStartBit)); + if (bs > 0) + v = Builder->CreateLShr(v, ConstantInt::get(req_eq_ty, bs)); + return Builder->CreateTrunc(v, buildTypes->llvmType(symbol->getDataType())); + } else if (symbol->isPseudoVar()) { + alloc = symbol->getLLVMValue(stem, func); + } else { + // not pointer and isComplex: two or more recursive levels: a.x.y + alloc = getRecursiveField(ident, getScope(), func); + } - return ret; + if (stem->hasQualifier(qvolatile)) + symbol->setQualifier(qvolatile); + + // when the new var will be a reference to expr; + // we change its scope to the scope of expr (stem) + // this is needed by injection + if (leftValue) + leftValue->setScope(stem, true); + } else { + alloc = symbol->getLLVMValue(func); + } + + if (!alloc) { + yyerrorcpp(string_format("Symbol %s is undefined at this point.", ident.getFullName().c_str()), this); + return NULL; // Caused by an error on previous statement that defines the symbol + } + + DataType sdt = symbol->getDataType(); + if (buildTypes->isComplex(sdt) || buildTypes->isArrayOrMatrix(sdt)) { + if (symbol->isPointerToPointer()) { + Type *ty = PointerType::getUnqual(buildTypes->llvmType(sdt)); + alloc = Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); + } + if (leftValue) + leftValue->setPointerToPointer(true); + return alloc; + } else { + Type *ty = buildTypes->llvmType(sdt); + return Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), ident.getFullName()); + } } -void Load::accept(Visitor &v) { - v.visit(*this); +bool Load::isConstExpr() { + Node *symbol = ident.getSymbol(getScope()); + return symbol && symbol->isConstExpr(); } -bool Load::isConstExpr(BasicBlock *block, BasicBlock *allocblock) { - RobSymbol *rsym = search_symbol(ident, block, allocblock); - return rsym && (dyn_cast(rsym->value) != NULL); +void Load::setLeftValue(Variable *symbol) { + leftValue = symbol; } + +Value* Load::getRecursiveField(Identifier &ident, Node *scope, FunctionImpl *func) { + list symbols; + Node *last = ident.getSymbol(scope, false, &symbols); + symbols.push_back(last); + + Node *first = symbols.front(); + symbols.pop_front(); + Value *alloc = first->getLLVMValue(func); + assert(alloc && "Can't get a field of an unallocated symbol."); + + Type *udt = buildTypes->llvmType(first->getDataType()); + if (first->isPointerToPointer()) { + alloc = Builder->CreateLoad(PointerType::getUnqual(udt), alloc, "deref"); + } + + for(auto &x : symbols) { + Variable *var = dynamic_cast(x); + if (var) { + int gepidx = var->getGEPIndex(); + if (var->isPointerToPointer()) { + alloc = Builder->CreateLoad(PointerType::getUnqual(udt), alloc, "deref"); + } + alloc = Builder->CreateStructGEP(udt, alloc, gepidx, x->getName()); + udt = buildTypes->llvmType(var->getDataType()); + } else { + yyerrorcpp(x->getName() + " is not a variable.", &ident); + break; + } + } + return alloc; +} \ No newline at end of file diff --git a/src/Load.h b/src/Load.h index 1ff2e8f..7d77b2e 100644 --- a/src/Load.h +++ b/src/Load.h @@ -1,21 +1,41 @@ -#ifndef __LOAD_H__ -#define __LOAD_H__ +#pragma once + #include "Node.h" +#include "Identifier.h" +#include "semantic/Visitor.h" class Load: public Node { private: - string ident; + Identifier ident; + Variable *leftValue = NULL; + Node *identSymbol = NULL; + public: - Load(const char *i): ident(i) {} + Load(const char* i, location_t loc): Node(loc), ident(i, loc) { } + Load(Identifier i): Node(i.getLoc()), ident(i.getFullName(), i.getLoc()) { } + Load(Node *n): Node(n->getLoc()), ident(n->getName(), n->getLoc()) { + identSymbol = n; + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual DataType getDataType() override; + + virtual bool isConstExpr() override; - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual void setLeftValue(Variable *symbol) override; - string getIdent() const { return ident; }; + virtual const string getName() const override { + return ident.getFullName(); + } - virtual void accept(Visitor& v) override; + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } - virtual Type* getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override; + Node* getIdentSymbol(bool showError = true); - bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; + static Value* getRecursiveField(Identifier &ident, Node *scope, FunctionImpl *func); + + friend class SymbolizeTree; }; -#endif diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index b91860c..cf001a1 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -1,59 +1,98 @@ -#include "Header.h" - -Type* LoadArray::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { - if (!rsym) - rsym = search_symbol(ident, allocblock, block); - if (rsym) { - Type *ty = NULL; - if (auto *aux = dyn_cast(rsym->value)) - ty = aux->getAllocatedType(); - else if (auto *aux = dyn_cast(rsym->value)) - ty = aux->getValueType(); - - if (ty->isArrayTy()) { - ArrayType *arrayTy = (ArrayType*)ty; - return arrayTy->getArrayElementType(); - } + +#include "Array.h" +#include "LoadArray.h" +#include "BuildTypes.h" +#include "FunctionImpl.h" +#include "Load.h" + +LoadArray::LoadArray(const string &i, Node *pos, location_t loc): BaseArrayOper(i, pos, NULL, loc) { + addChild(pos); +} + +DataType LoadArray::getDataType() { + if (dt == BuildTypes::undefinedType) { + Node *symbol = ident.getSymbol(getScope()); + if (symbol) { + if (getDimensions() == 1 && !buildTypes->isArray(symbol->getDataType())) { + yyerrorcpp("Symbol " + ident.getFullName() + " is not an array.", this); + setSemanticError(); + } else if (getDimensions() == 2 && !buildTypes->isMatrix(symbol->getDataType())) { + yyerrorcpp("Symbol " + ident.getFullName() + " is not a matrix.", this); + setSemanticError(); + } else + dt = buildTypes->getArrayElementType(symbol->getDataType()); + } else + setSemanticError(); } - return NULL; + return dt; } -Value *LoadArray::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - rsym = search_symbol(ident, allocblock, block); - /* TODO */ - if (rsym == NULL) { - yyerrorcpp("Variable " + ident + " not defined.", this); +Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + Node *symbol = ident.getSymbol(getScope()); + if (!symbol) return NULL; + + if (!buildTypes->isArrayOrMatrix(symbol->getDataType())) + return NULL; + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + Value *alloc = NULL; + if (ident.isComplex()) { + Identifier istem = ident.getStem(); + Node *stem = istem.getSymbol(getScope()); + alloc = Load::getRecursiveField(ident, getScope(), func); + + if (stem->hasQualifier(qvolatile)) + symbol->setQualifier(qvolatile); + } else { + alloc = symbol->getLLVMValue(func); } - auto sym = rsym->value; - - // sym type can be GlobalVariable or AllocInst - Type *ty = NULL; - if (auto *aux = dyn_cast(sym)) - ty = aux->getAllocatedType(); - else if (auto *aux = dyn_cast(sym)) - ty = aux->getValueType(); - - ArrayType *arrayTy = NULL; - if (ty->isArrayTy()) { - arrayTy = (ArrayType*)ty; - } - else { - yyerrorcpp("Symbol " + ident + " is not an array.", this); + + if (!alloc) { + // this is a compiler error + yyerrorcpp("Missing the array reference to gep.", this); return NULL; } - Node *indn = getLoadIndex(rsym, block, allocblock); + Node *indn = getElementIndex(symbol); Value *indice = indn->generate(func, block, allocblock); - if (!indice->getType()->isIntegerTy()){ - yyerrorcpp("Index to update " + ident + " elements should be of type integer.", this); + if (!indice || !indice->getType()->isIntegerTy()) { //TODO: replace by isIntegerDataType + yyerrorcpp("Index to access " + ident.getFullName() + " elements must be of type integer.", this); return NULL; } + if (!ident.isComplex() && symbol->isPointerToPointer()) { + Type *ty = PointerType::getUnqual(buildTypes->llvmType(symbol->getDataType())); + alloc = Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); + } + + Builder->SetInsertPoint(block); Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); - Value* indexList[2] = {zero, indice}; - GetElementPtrInst* ptr = GetElementPtrInst::Create(arrayTy, sym, ArrayRef(indexList), "", block); - LoadInst *ret = new LoadInst(ptr->getResultElementType(), ptr, ident, false, block); + Value *indexList[2] = {zero, indice}; + Value *ptr = Builder->CreateGEP(symbol->getLLVMType(), alloc, ArrayRef(indexList), "gep"); + + DataType elementDt = buildTypes->getArrayElementType(symbol->getDataType()); + Type *elemType = buildTypes->llvmType(elementDt); + if (buildTypes->isUserType(elementDt)) { + if (leftValue) { + leftValue->setPointerToPointer(true); + } + elemType = PointerType::getUnqual(elemType); + } + + LoadInst *ret = Builder->CreateLoad(elemType, ptr, ident.getFullName()); return ret; } +Node* BaseArrayOper::getElementIndex(Node *symbol) { + + // Get element + int rows = -1; + if (const Array *arr = dynamic_cast(symbol)) + rows = arr->getSize(); + + return Array::getElementIndex(position, NULL, ident.getFullName(), rows); +} diff --git a/src/LoadArray.h b/src/LoadArray.h index 24ab96e..4eaf47f 100644 --- a/src/LoadArray.h +++ b/src/LoadArray.h @@ -2,21 +2,50 @@ #pragma once #include "Node.h" +#include "Identifier.h" -class LoadArray: public Node { +class BaseArrayOper: public Node { protected: - string ident; + Identifier ident; Node *position; - RobSymbol *rsym = NULL; + Node *position2; + Variable *leftValue = nullptr; public: - LoadArray(const char *i, Node *pos): ident(i), position(pos) {} + BaseArrayOper(const string& i, Node *pos, Node *pos2, location_t loc): + Node(loc), ident(i, loc), position(pos), position2(pos2) {} + + virtual Node* getElementIndex(Node *symbol); - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + Node *getPosition() { + return position; + } + + Node *getPosition2() { + return position2; + } - virtual Type* getLLVMResultType(BasicBlock *block, BasicBlock *allocblock); + const string getIdent() const { + return ident.getFullName(); + } - virtual Node *getLoadIndex(RobSymbol *rsym, BasicBlock *block, BasicBlock *allocblock) { - return position; + const int getDimensions() { + return children().size(); + } + + virtual const string getName() const override { + return getIdent(); } + virtual void setLeftValue(Variable *symbol) override { + leftValue = symbol; + } +}; + +class LoadArray: public BaseArrayOper { +public: + LoadArray(const string& i, Node *pos, location_t loc); + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual DataType getDataType() override; }; diff --git a/src/LoadMatrix.h b/src/LoadMatrix.h index 787cd73..2d63e11 100644 --- a/src/LoadMatrix.h +++ b/src/LoadMatrix.h @@ -1,18 +1,39 @@ #pragma once #include "Node.h" +#include "Matrix.h" +#include "Array.h" +#include "LoadArray.h" +#include "Load.h" class LoadMatrix: public LoadArray { -private: - Node *position2; public: - LoadMatrix(const char *i, Node *pos_1, Node *pos_2): LoadArray(i, pos_1) { - this->position2 = pos_2; + LoadMatrix(const string &i, Node *p1, Node *p2, location_t loc): LoadArray(i, p1, loc) { + this->position2 = p2; + addChild(p2); } - virtual Node *getLoadIndex(RobSymbol *rsym, BasicBlock *block, BasicBlock *allocblock) override { - //Generate index of element - Node *mcols = getNodeForIntConst(rsym->matrixCols); - return new BinaryOp(new BinaryOp(position, '*', mcols), '+', position2); + virtual Node* getElementIndex(Node *symbol) override { + return getElementIndexMatrix(this, symbol); + } + + static Node* getElementIndexMatrix(BaseArrayOper *matrix, Node *symbol) { + // Get element + int rows = -1; + int cols = -1; + Node *mcols = NULL; + if (const Matrix *mx = dynamic_cast(symbol)) { + rows = mx->getRows(); + cols = mx->getCols(); + mcols = getNodeForIntConst(cols, matrix->getLoc()); + } else if (Node *s = symbol->findSymbol("cols", false)) { + mcols = new Load(s); + mcols->setScope(symbol); + } + + assert(mcols && "Missing the number of columns to compute the matrix element index."); + + return Array::getElementIndex(matrix->getPosition(), matrix->getPosition2(), + matrix->getIdent(), rows, cols, mcols); } }; diff --git a/src/Loop.cpp b/src/Loop.cpp index c0385aa..11b657c 100644 --- a/src/Loop.cpp +++ b/src/Loop.cpp @@ -1,20 +1,35 @@ -#include "Header.h" -Loop::Loop(Node *stms) : stmts(stms) { - node_children.reserve(1); - node_children.push_back(stms); +#include "Loop.h" +#include "FunctionImpl.h" + +Loop::Loop(vector &&stms, location_t loc) : Node(std::move(stms), loc) { } -Value *Loop::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - BasicBlock *bodyloop = BasicBlock::Create(global_context, "loop_body", func, 0); +Value *Loop::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + BasicBlock *bodyloop = BasicBlock::Create(global_context, "loop_body", + func->getLLVMFunction(), 0); + + RobDbgInfo.emitLocation(this); + + // go to loop + Builder->SetInsertPoint(block); + Builder->CreateBr(bodyloop); + // alloc instructions inside bodyloop should go to allocblock to prevent repeatedly allocation - Value *newb = stmts->generate(func, bodyloop, allocblock); - BranchInst::Create(bodyloop, bodyloop); - BranchInst::Create(bodyloop, block); - BasicBlock *endloop = BasicBlock::Create(global_context, "loop_end", func, 0); - return endloop; -} + Value *newb = generateChildren(func, bodyloop, allocblock); + + // identify last while body block + BasicBlock *endbody = bodyloop; + if (newb->getValueID() == Value::BasicBlockVal) + endbody = (BasicBlock*)newb; + + // if end block already has a terminator, don't generate branch + if (!((BasicBlock*)endbody)->getTerminator()) { + Builder->SetInsertPoint(endbody); + Builder->CreateBr(bodyloop); + } -void Loop::accept(Visitor& v) { - v.visit(*this); + BasicBlock *endloop = BasicBlock::Create(global_context, "loop_end", + func->getLLVMFunction(), 0); + return endloop; } diff --git a/src/Loop.h b/src/Loop.h index 4e6ca97..25579e2 100644 --- a/src/Loop.h +++ b/src/Loop.h @@ -4,12 +4,10 @@ #include "Node.h" class Loop: public Node { -private: - Node *stmts; public: - Loop(Node *stms); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; + Loop(vector &&stmts, location_t loc); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + }; #endif diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 840faf7..4e40f55 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -1,79 +1,47 @@ -#include "Header.h" - -Value *Matrix::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - - /* - * Matrix is generated as an array and accessed latter accordingly! - */ - - //Get Type of elements in Vector of Elements, and define as I. - Type* I = melements->getMatrixType(block, allocblock); - - // The matrix size - unsigned int lines = melements->getLineCount(); - unsigned int cols = melements->getColumnCount(); - ArrayType* arrayType = ArrayType::get(I, lines * cols); - - // Allocate elements. Supported formats: - // {{1:3}:3, {1:2,2}:2} - // {{1,1,1},{1,1,1},{1,1,1},{1,1,2},{1,1,2}} - bool allConst = true; - vector elementValues; - elementValues.reserve(lines * cols); - for(MatrixElement& i: melements->elements) { - unsigned elCount = i.count; - - for (int j=0; jelements) { - Node* elValue = k.value; - Value *val = elValue->generate(func, block, allocblock); - if (!val) - return NULL; - val = Coercion::Convert(val, I, block, elValue); - if (!dyn_cast(val)) - allConst = false; - for (int l=0; lgetRowCount(), this->getLoc())); + NamedConst *cols = new NamedConst("cols", getNodeForUIntConst(me->getColumnCount(), this->getLoc())); + addChild(rows); + addSymbol("rows", rows); + addChild(cols); + addSymbol("cols", cols); + + // fill arrayElements with matrix elements copy + for(auto &melem : melements->getElements()) { + for(int repeat = 0; repeat < melem->count; repeat++) + arrayElements->insertElements(melem->array); } +} - if (!allConst && (allocblock == NULL || allocblock == global_alloc)) { - // Load will produce an error informing the usage of other variables - // to define a new global variable - return NULL; - } +Node* Matrix::accept(Visitor& v) { + return v.visit(*this); +} - //Allocate matrix as a vector. - //Allocate array. - Value* var; - if (allocblock == global_alloc) { // when alloc is global - vector constantValues; - constantValues.reserve(elementValues.size()); - for(auto &a : elementValues) - constantValues.push_back(dyn_cast(a)); - ArrayRef constantRefs(constantValues); - GlobalVariable *gv = new GlobalVariable(*mainmodule, arrayType, - false, GlobalValue::ExternalLinkage, ConstantArray::get(arrayType, constantRefs), name); - var = gv; - } else { - var = new AllocaInst(arrayType, 0, name, allocblock); +void Matrix::createDataType() { + if (arrayType != NULL) + return; - Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); - StoreInst *store = NULL; - for(unsigned index = 0; index < elementValues.size(); index++) { - Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), index); - Value* indexList[2] = {zero, idx}; - GetElementPtrInst* gep = GetElementPtrInst::Create(arrayType, var, - ArrayRef(indexList), "", block); - store = new StoreInst(elementValues[index], gep, false, block); - } + //Get Type of elements in Vector of Elements, and define as I. + element_dt = melements->getMatrixType(); + dt = buildTypes->getArrayType(buildTypes->name(element_dt), + this->getLoc(), 2, true); + Type* I = buildTypes->llvmType(element_dt); + if (buildTypes->isComplex(element_dt)) { + // in rob, all matrices of user types (complex types) + // are matrices of references + I = PointerType::getUnqual(I); } - //Add array to table of symbols. - tabelasym[allocblock][name] = new RobSymbol(var); - tabelasym[allocblock][name]->matrixLines = lines; - tabelasym[allocblock][name]->matrixCols = cols; - - return var; + // The matrix type and size + rows = melements->getRowCount(); + cols = melements->getColumnCount(); + size = rows * cols; + arrayType = ArrayType::get(I, size); } diff --git a/src/Matrix.h b/src/Matrix.h index e350482..a4fbb54 100644 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -1,13 +1,42 @@ -#ifndef __Matrix_H__ -#define __Matrix_H__ -class Matrix: public Node { +#pragma once + +#include "Array.h" +#include "MatrixElements.h" +#include "Variable.h" + +class ParamMatrix: public ParamArray { +public: + ParamMatrix(const string& n, string element_dt_name, location_t loc): ParamArray(n, element_dt_name, loc) {} + + virtual int getDimensions() override { + return 2; + } +}; + +class Matrix: public Array { private: - string name; MatrixElements *melements; + unsigned int rows = 0; + unsigned int cols = 0; + +protected: + virtual void createDataType() override; + public: - Matrix(const char *n, MatrixElements *me) : name(n), melements(me) { } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); -}; + Matrix(const char *n, MatrixElements *me, location_t loc); + + std::vector const& getMatrixElements() { + return melements->getElements(); + } -#endif + Node* accept(Visitor& v) override; + + int getRows() const { + return rows; + } + + int getCols() const { + return cols; + } +}; diff --git a/src/MatrixElements.cpp b/src/MatrixElements.cpp index 24c9ffd..58a118c 100644 --- a/src/MatrixElements.cpp +++ b/src/MatrixElements.cpp @@ -1,24 +1,25 @@ -#include "Header.h" -MatrixElements::MatrixElements() {}; +#include "MatrixElements.h" -void MatrixElements::append(MatrixElement& m) { +MatrixElements::MatrixElements(location_t loc): location(loc) {}; + +void MatrixElements::append(MatrixElement *m) { elements.push_back(m); }; -unsigned MatrixElements::getLineCount() const { +unsigned MatrixElements::getRowCount() { unsigned r = 0; for(auto& e : elements) - r += e.count; + r += e->count; return r; }; -unsigned MatrixElements::getColumnCount() const { +unsigned MatrixElements::getColumnCount() { unsigned r = 0; unsigned biggest_r = 0; for(auto& e : elements) { - for (auto& i : e.array->elements) - r += i.count; + for (auto& i : e->array->getElements()) + r += i->count; if (biggest_r < r) biggest_r = r; r = 0; @@ -26,44 +27,14 @@ unsigned MatrixElements::getColumnCount() const { return biggest_r; } -Type *MatrixElements::getMatrixType(BasicBlock *block, BasicBlock *allocblock) const { - unsigned intsize = 0; - unsigned floatsize = 0; +DataType MatrixElements::getMatrixType() { + set types; for(auto& j : elements) { - for (auto& i : j.array->elements) { - Type *ty = i.value->getLLVMResultType(block, allocblock); - if (ty->isIntegerTy() && intsize < ty->getIntegerBitWidth()) - intsize = ty->getIntegerBitWidth(); - - if (floatsize < 32 && ty->isFloatTy()) - floatsize = 32; - else if (floatsize < 64 && ty->isDoubleTy()) - floatsize = 64; - else if (floatsize < 128 && ty->isFP128Ty()) - floatsize = 128; - } - } - if (intsize == 0 && floatsize == 0) { - yyerrorcpp("FIXME: matrix of non-consts.", NULL); - return NULL; - } - if (floatsize == 0) { - switch (intsize) { - case 1: return Type::getInt1Ty(global_context); - case 8: return Type::getInt8Ty(global_context); - case 16: return Type::getInt16Ty(global_context); - case 32: return Type::getInt32Ty(global_context); - default: return Type::getInt64Ty(global_context); - } - } else { - switch (floatsize) { - case 32: return Type::getFloatTy(global_context); - case 64: return Type::getDoubleTy(global_context); - default: return Type::getFP128Ty(global_context); - } + types.emplace(j->array->getArrayType()); } + return ArrayElements::getArrayConstType(types, &location); } -unsigned MatrixElements::getElementCount(int position) const { - return elements[position].count; +unsigned MatrixElements::getElementCount(int position) { + return elements[position]->count; } diff --git a/src/MatrixElements.h b/src/MatrixElements.h index 0d238a8..fcb64df 100644 --- a/src/MatrixElements.h +++ b/src/MatrixElements.h @@ -1,20 +1,29 @@ -#ifndef __MATRIX_ELEMENTS_H__ -#define __MATRIX_ELEMENTS_H__ -#include "Node.h" +#pragma once + +#include "ArrayElements.h" + +class MatrixElement { +public: + ArrayElements *array; + unsigned count; + MatrixElement(ArrayElements *array, unsigned count): array(array), count(count) {} +}; class MatrixElements { private: + std::vector elements; + SourceLocation location; public: - MatrixElements(); - std::vector elements; - void append(MatrixElement& m); + MatrixElements(location_t loc); + void append(MatrixElement *m); - unsigned getColumnCount() const; - unsigned getLineCount() const; - unsigned getElementCount(int position) const; - Type *getMatrixType(BasicBlock *block, BasicBlock *allocblock) const; + unsigned getColumnCount(); + unsigned getRowCount(); + unsigned getElementCount(int position); + DataType getMatrixType(); + + std::vector const& getElements() { + return elements; + } }; - -#endif - diff --git a/src/MemCopy.cpp b/src/MemCopy.cpp new file mode 100644 index 0000000..09779ef --- /dev/null +++ b/src/MemCopy.cpp @@ -0,0 +1,94 @@ + +#include "MemCopy.h" +#include "Load.h" +#include "BackLLVM.h" +#include "FunctionImpl.h" + +Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + // Get src value + Value *exprv = expr->generate(func, block, allocblock); + Type *exprvty = exprv->getType(); + dt = expr->getDataType(); + + // Compute the size of src + const DataLayout &dl = mainmodule->getDataLayout(); + Value *size; + Value *nelem = NULL; + + if (buildTypes->isArray(dt)) { + // Load the array size and compute the bytes to copy + DataType eldt = buildTypes->getArrayElementType(dt); + TypeSize eltsize = dl.getTypeAllocSize(buildTypes->llvmType(eldt)); + ConstantInt *elbytes = ConstantInt::get(Type::getInt32Ty(global_context), eltsize); + Load ld("size", this->getLoc()); + ld.setScope(expr); + nelem = ld.generate(func, allocblock, allocblock); + Builder->SetInsertPoint(allocblock); + size = Builder->CreateBinOp(Instruction::Mul, elbytes, nelem, "arrsize"); + } else if (buildTypes->isMatrix(dt)) { + // Load the matrix size and compute the bytes to copy + DataType eldt = buildTypes->getArrayElementType(dt); + TypeSize eltsize = dl.getTypeAllocSize(buildTypes->llvmType(eldt)); + ConstantInt *elbytes = ConstantInt::get(Type::getInt32Ty(global_context), eltsize); + Load ldrows("rows", this->getLoc()); + ldrows.setScope(expr); + Load ldcols("cols", this->getLoc()); + ldcols.setScope(expr); + Builder->SetInsertPoint(allocblock); + Value *nrows = ldrows.generate(func, allocblock, allocblock); + Value *ncols = ldcols.generate(func, allocblock, allocblock); + nelem = Builder->CreateBinOp(Instruction::Mul, nrows, ncols, "matrixelem"); + size = Builder->CreateBinOp(Instruction::Mul, elbytes, nelem, "matrixsize"); + } else { + TypeSize ts = dl.getTypeAllocSize(buildTypes->llvmType(dt)); + nelem = ConstantInt::get(Type::getInt8Ty(global_context), 1); + size = ConstantInt::get(Type::getInt32Ty(global_context), ts); + } + + // Prepare dest memory + Type *leftvty; + Value *dest; + if (leftGEP) + dest = leftGEP; + else + dest = leftValue->getLLVMValue(func); + + if (dest) { + leftvty = dest->getType(); + //FIXME: must check the alloc size for array and matrix + } else { + Builder->SetInsertPoint(allocblock); + if (buildTypes->isArrayOrMatrix(dt)) { + DataType eldt = buildTypes->getArrayElementType(dt); + dest = Builder->CreateAlloca(buildTypes->llvmType(eldt), dataAddrSpace, nelem, leftValue->getName()); + leftvty = PointerType::getUnqual(buildTypes->llvmType(dt)); + } else { + leftvty = buildTypes->llvmType(dt); + dest = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, nelem, leftValue->getName()); + } + + leftValue->setAlloca(dest); + leftValue->setDataType(dt); + + //FIXME: only work for constant symbols + leftValue->symbols = expr->getSymbols(); + + if (debug_info) + RobDbgInfo.declareVar(this, dest, allocblock); + } + + if (!dest || !expr || //!leftvty->isPointerTy() || + !exprvty->isPointerTy()) { + yyerrorcpp("Can not copy these operands.", this); + return NULL; + } + + Builder->SetInsertPoint(block); + Builder->CreateMemCpy(dest, Align(1), exprv, Align(1), size); + + return NULL; +} diff --git a/src/MemCopy.h b/src/MemCopy.h new file mode 100644 index 0000000..d54d49b --- /dev/null +++ b/src/MemCopy.h @@ -0,0 +1,49 @@ + +#pragma once + +#include "Node.h" +#include "Variable.h" +#include "semantic/Visitor.h" + +class Constructor: public Node { +protected: + Variable *leftValue = NULL; + Value *leftGEP = NULL; +public: + Constructor(location_t l): Node(l) {} + + virtual void setLeftValue(Variable *symbol) override { + leftValue = symbol; + } + + virtual void setLeftGEP(Value *gep) { + leftGEP = gep; + } +}; + +class MemCopy: public Constructor { +private: + Node *expr; + +public: + MemCopy(Node *expr): expr(expr), Constructor(expr->getLoc()) { + addChild(expr); + this->expr = expr; + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual const string getName() const override { + return leftValue->getName(); + } + + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } + + DataType getDataType() override { + return expr->getDataType(); + } + + friend class SymbolizeTree; +}; diff --git a/src/NamedConst.h b/src/NamedConst.h new file mode 100644 index 0000000..e795433 --- /dev/null +++ b/src/NamedConst.h @@ -0,0 +1,37 @@ + +#pragma once + +#include "Node.h" + +class NamedConst: public NamedNode { +protected: + Node *value = NULL; + +public: + NamedConst(const string& name, location_t loc) : NamedNode(name, loc) {} + + NamedConst(const string& name, Node *v) : NamedNode(name, v->getLoc()), value(v) { + dt = value->getDataType(); + } + + Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + return value->generate(NULL, NULL, NULL); + } + + virtual Value *getLLVMValue(Node *stem, FunctionImpl *gfunc = NULL) override { + return value->generate(NULL, NULL, NULL); + } + + virtual bool isConstExpr() override { + return true; + } + + virtual void setValue(Node *n) { + value = n; + dt = value->getDataType(); + } + + Node *getValue() { + return value; + } +}; diff --git a/src/Node.cpp b/src/Node.cpp index 5fcac5c..f1159b3 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -1,17 +1,160 @@ -#include "Header.h" -bool Node::isFunctionDecl() -{ - return false; -} +#include "Node.h" +#include "Int8.h" +#include "Int16.h" +#include "Int32.h" +#include "Int64.h" +#include "semantic/Visitor.h" Node::~Node() {} +Node::Node(vector &&children, location_t loc) : SourceLocation(loc), node_children(children) { +} + std::vector const& Node::children() const { return node_children; } -void Node::accept(Visitor& v) { - v.visit(*this); +Node* Node::accept(Visitor& v) { + return v.visit(*this); } +Node* Node::findMember(const string& name) { + // look for pseudo fields (array, matrix, register) + Node *m = findSymbol(name, false); + if (!m) { + // getDataType forces getting the dataType, case it was not queried yet + DataType this_dt = getDataType(); + if (this_dt == BuildTypes::undefinedType) + return m; + + // look for fields in the base type + const char *ut_name = buildTypes->name(this_dt); + Node *ut = findSymbol(ut_name); + if (!ut) + return NULL; + m = ut->findSymbol(name, false); + } + return m; +} + +Node* Node::findSymbol(const string& name, bool recursive) { + Node *current_scope = this; + do { + auto it = current_scope->symbols.find(name); + if (it != current_scope->symbols.end()) { + return it->second; + } else if (recursive) + current_scope = current_scope->scope; + } while (current_scope && recursive); + + return NULL; +} + +void Node::addChild(Node *n, bool prepend) { + if (prepend) + node_children.insert(node_children.begin(), n); + else + node_children.push_back(n); +} + +void Node::removeChild(Node *n) { + NamedNode *nn = dynamic_cast(n); + if (nn) + symbols.erase(nn->getName()); + auto it = find(node_children.begin(), node_children.end(), n); + if (*it) + node_children.erase(it); +} + +void Node::addSymbol(NamedNode *nm) { + addSymbol(nm->getName(), nm); +} + +void Node::addSymbol(const string& label, NamedNode *nm) { + // if the variable is already defined here or in a parent + // scope, don't add it again. + if (!findSymbol(label, true)) { + symbols[label] = nm; + } +} + +map const& Node::getSymbols() { + return symbols; +} + +void Node::setScope(Node *s, bool replace) { + if (scope != NULL && !replace) + assert(scope == NULL && "node already has a scope"); + scope = s; +} + +Value* Node::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return NULL; +} + +Value* Node::generateNewBlock(FunctionImpl *func, BasicBlock **block, BasicBlock *allocblock) { + Value *ret = generate(func, *block, allocblock); + + // Check if the last Instruction is in another block + // e.g. a block returned from boolean short-circuit evaluation + if (ret) { + Instruction* instr = dyn_cast(ret); + if (instr && instr->getParent() != allocblock) + *block = instr->getParent(); + } + + return ret; +} + +Value* Node::generateChildren(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + Node *ret = nullptr; + for(Node *n: children()) { + if (!ret) { + Value *b = n->generateNewBlock(func, &block, allocblock); + if (b) { + if (b->getValueID() == Value::BasicBlockVal) + block = (BasicBlock*)b; + + if (isa(b)) + ret = n; + } + } else { + // there's instructions after return: warn and don't generate + yywarncpp("Unreachable statement following return.", n); + yywarncpp("The return statement is here.", ret); + } + } + return block; +} + +Type* Node::getLLVMType() { + DataType aux = getDataType(); + Type *taux = buildTypes->llvmType(getDataType()); + if (buildTypes->isInterface(aux)) + return PointerType::getUnqual(taux); + else + return taux; +} + +Node* getNodeForUIntConst(uint64_t i, location_t loc) { + if (i <= UCHAR_MAX) + return new UInt8(i, loc); + else if (i <= USHRT_MAX) + return new UInt16(i, loc); + else if (i <= UINT_MAX) + return new UInt32(i, loc); + else + return new UInt64(i, loc); +} + +Node* getNodeForIntConst(int64_t i, location_t loc) { + if (i >= SCHAR_MIN && i <= SCHAR_MAX) + return new Int8(i, loc); + else if (i >= SHRT_MIN && i <= SHRT_MAX) + return new Int16(i, loc); + else if (i >= INT_MIN && i <= INT_MAX) + return new Int32(i, loc); + else + return new Int64(i, loc); +} diff --git a/src/Node.h b/src/Node.h index 56234a9..ae4c2a9 100644 --- a/src/Node.h +++ b/src/Node.h @@ -1,31 +1,130 @@ -#ifndef NODE_H -#define NODE_H + +#pragma once + +#include "SourceLocation.h" +#include "BuildTypes.h" class Visitor; +class NamedNode; +class UserType; +class FunctionImpl; +class Variable; class Node : public SourceLocation { protected: - std::vector node_children; + map symbols; + vector node_children; + DataType dt = BuildTypes::undefinedType; + set qualifiers; + Node *scope = nullptr; + bool pointerToPointer = false; + public: + Node(location_t l) : SourceLocation(l) {} + Node(vector &&children, location_t l); + virtual ~Node(); - virtual bool isFunctionDecl(); + virtual bool isConstExpr() { + return false; + } + + virtual Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value* generateNewBlock(FunctionImpl *func, BasicBlock **block, BasicBlock *allocblock); + + virtual Value* generateChildren(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); + + virtual std::vector const& children() const; + + virtual Node* accept(Visitor &); - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) { + virtual bool hasName() { return false; } + + virtual const string getName() const { + return ""; + } + + Node* getScope() { + return scope; + } + + virtual void setScope(Node *s, bool replace = false); + + virtual Node* findSymbol(const string& name, bool recursive = true); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) = 0; + virtual Node* findMember(const string& name); + + void addChild(Node *n, bool prepend = false); + void removeChild(Node *n); + + virtual map const& getSymbols(); + + virtual void addSymbol(const string& label, NamedNode *nm); + virtual void addSymbol(NamedNode *nm); + + void setDataType(DataType dt) { + this->dt = dt; + } + + virtual DataType getDataType() { + return dt; + } - virtual std::vector const& children() const; - virtual void accept(Visitor &); + virtual Type* getLLVMType(); - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { - /* this method should be overrided in descending classes - * that define vars/consts - */ + void setQualifier(DataQualifier dq) { + qualifiers.insert(dq); + } + + bool hasQualifier(DataQualifier dq) const { + return qualifiers.count(dq) == 1; + } + + virtual Value* getLLVMValue(Node *stem, FunctionImpl *gfunc = NULL) { return NULL; } + + virtual void setLeftValue(Variable *symbol) {} + + bool isPointerToPointer() { + return pointerToPointer; + } + + void setPointerToPointer(bool v) { + pointerToPointer = v; + } + + friend class UserType; + friend class Program; + friend class MemCopy; + friend class PropagateTypes; + friend class IdentifyVirtualDispatch; +}; + +class NamedNode: public Node { +protected: + string name; + +public: + NamedNode(const string &name, location_t loc) : Node(loc), name(name) {} + + NamedNode(const string &name, vector &&children, location_t loc) : + Node(std::move(children), loc), name(name) {} + + virtual const string getName() const override { + return name; + } + + void setName(const string& nname) { + name = nname; + } + + bool hasName() override { + return true; + } }; -#endif +extern Node* getNodeForIntConst(int64_t, location_t); +extern Node* getNodeForUIntConst(uint64_t, location_t); diff --git a/src/OutPort.cpp b/src/OutPort.cpp deleted file mode 100644 index 75e397e..0000000 --- a/src/OutPort.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "Header.h" - -OutPort::OutPort (const char *p, Node *e) : port(Int8(atoi(p))) { - expr = e; - node_children.reserve(2); - node_children.push_back(&port); - node_children.push_back(e); -} - -Value *OutPort::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - vector args; - - args.push_back(port.generate(func, block, allocblock)); - - Value *value = expr->generate(func, block, allocblock); - Value *nvalue = value; - if (value->getType()->isFloatTy()) - nvalue = new FPToSIInst(value, Type::getInt16Ty(global_context), "trunci", block); - - args.push_back(nvalue); - //Value *int8v = new TruncInst(value, Type::getInt8Ty(global_context), "", block); - //args.push_back(int8v); - - ArrayRef argsRef(args); - return CallInst::Create(analogWrite, argsRef, "", block); - } diff --git a/src/OutPort.h b/src/OutPort.h deleted file mode 100644 index aabea2b..0000000 --- a/src/OutPort.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __OUTPORT_H__ -#define __OUTPORT_H__ -#include "Node.h" -#include "Int16.h" -#include "Float.h" - -class OutPort: public Node { -private: - Int8 port; - Node *expr; -public: - OutPort (const char *p, Node *e); - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); -}; - -#endif diff --git a/src/ParamsCall.cpp b/src/ParamsCall.cpp index 22c4dc6..d4254aa 100644 --- a/src/ParamsCall.cpp +++ b/src/ParamsCall.cpp @@ -1,16 +1,18 @@ -#include "Header.h" + +#include "ParamsCall.h" ParamsCall::ParamsCall() {}; void ParamsCall::append(Node *n) { parameters.push_back(n); }; + +void ParamsCall::insert(int at, Node *pc) { + parameters.insert(parameters.begin() + at, pc); +} unsigned ParamsCall::getNumParams() const { - unsigned r = 0; - for(auto& i : parameters) - r += 1; - return r; + return parameters.size(); }; Node *ParamsCall::getParamElement(int position) const { diff --git a/src/ParamsCall.h b/src/ParamsCall.h index 575df1c..ad27ce0 100644 --- a/src/ParamsCall.h +++ b/src/ParamsCall.h @@ -9,9 +9,14 @@ class ParamsCall { public: ParamsCall(); void append(Node *pc); + void insert(int at, Node *pc); unsigned getNumParams() const; Node *getParamElement (int position) const; + + std::vector& getParameters() { + return parameters; + } }; #endif diff --git a/src/Pointer.cpp b/src/Pointer.cpp index 2b79559..aa34647 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -1,35 +1,50 @@ #include "Pointer.h" +#include "BackLLVM.h" +#include "HeaderGlobals.h" +#include "UserType.h" -Value *Pointer::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) +Pointer::Pointer(const char *name, DataType type, Node *address, location_t loc): + Variable(name, loc), address(address) { + dt = type; + addChild(address); +} + +Value *Pointer::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - auto sym = search_symbol(name); - if (sym != NULL) { + auto sym = findSymbol(name, true); + if (sym != NULL && sym != this) { yyerrorcpp("Register/pointer " + name + " already defined.", this); yyerrorcpp(name + " was first defined here.", sym); return NULL; } // generate code to produce the address - Value *addri = address->generate(func, block, allocblock); - if (addri == NULL) { + Value *addr = address->generate(func, block, allocblock); + if (addr == NULL) { yyerrorcpp("Unable to compute the address for '" + name + "' register.", this); return NULL; } - Value *addrp = NULL; - if (Constant *addrc = dyn_cast(addri)) - addrp = ConstantExpr::getIntToPtr(addrc, Type::getInt64PtrTy(global_context)); // FIXME: What is the method to get an opaque pointer type? - else - addrp = new IntToPtrInst(addri, Type::getInt64PtrTy(global_context), name, allocblock); - - Type *ty = robTollvmDataType[type]; - DataQualifier vol = isVolatile ? qvolatile : qnone; - tabelasym[allocblock][name] = new RobSymbol(addrp, vol, ty); - return addrp; -} + if (!buildTypes->isDefined(dt)) { + yyerrorcpp(string_format("The type %s is undefined.", + buildTypes->name(dt)), this); + return NULL; + } + + Type *targetPointerType = PointerType::getUnqual(buildTypes->llvmType(dt)); -void Pointer::accept(Visitor &v) { - v.visit(*this); + // In favor of faster and smaller code size, we return the pointer + // as a ConstantExpr. This limits pointer arithmetic. + Constant *addr_num = dyn_cast(addr); + assert(addr_num && "FIXME: global pointer defined without constant address."); + alloc = ConstantExpr::getIntToPtr(addr_num, targetPointerType); + return alloc; } +unsigned Pointer::getFieldStartBit(Node *field) { + Node *dtsymbol = findSymbol(buildTypes->name(getDataType())); + UserType *ut = dynamic_cast(dtsymbol); + assert(ut && "Can't get field start bit from a non-complex type."); + return ut->getFieldStartBit(field); +} diff --git a/src/Pointer.h b/src/Pointer.h index e00c7e1..8123910 100644 --- a/src/Pointer.h +++ b/src/Pointer.h @@ -1,19 +1,16 @@ -#ifndef __REGISTER_H__ -#define __REGISTER_H__ -#include "Header.h" +#pragma once -class Pointer: public Node { +#include "Variable.h" + +class Pointer: public Variable { private: - LanguageDataType type; Node *address; - string name; - bool isVolatile; + public: - Pointer(const char *name, LanguageDataType type, Node *address, bool isVolatile = false): - name(name), type(type), address(address), isVolatile(isVolatile) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; -}; + Pointer(const char *name, DataType type, Node *address, location_t loc); -#endif + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + unsigned getFieldStartBit(Node *symbol); +}; diff --git a/src/Print.cpp b/src/Print.cpp deleted file mode 100644 index a191945..0000000 --- a/src/Print.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "Header.h" - - Value *Print::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - vector args; - - Value *lexp = expr->generate(func, block, allocblock); - char cty1 = -1; - if (lexp != NULL) { - Type *ty1 = lexp->getType(); - if (ty1->isIntegerTy()) - cty1 = 0; - else if (ty1->isFloatTy()) - cty1 = 1; - else if (ty1->isArrayTy()) - cty1 = 2; - } - /* TODO */ - if (cty1 == -1) { - yyerrorcpp("Type not supported by print.", this); - return NULL; - } - - Int8 prt(cty1); - args.push_back(prt.generate(func, block, allocblock)); - - AllocaInst *ptr_aux = new AllocaInst(lexp->getType(), 0, "prntaux", block); - /*StoreInst *st = */ new StoreInst(lexp, ptr_aux, false, block); - CastInst *cinst = new BitCastInst(ptr_aux, PointerType::get(IntegerType::get(global_context, 8), 0), "bitcast", block); - args.push_back(cinst); - - ArrayRef argsRef(args); - return CallInst::Create(print, argsRef, "", block); - } - diff --git a/src/Print.h b/src/Print.h deleted file mode 100644 index e9dece1..0000000 --- a/src/Print.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __PRINT_H__ -#define __PRINT_H__ -#include "Node.h" - -class Print: public Node { -private: - Node *expr; -public: - Print(Node *e) : expr(e) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); -}; - -#endif diff --git a/src/PrintAstVisitor.cpp b/src/PrintAstVisitor.cpp deleted file mode 100644 index 9242b08..0000000 --- a/src/PrintAstVisitor.cpp +++ /dev/null @@ -1,132 +0,0 @@ - -#include "Header.h" -#include - -template char* get_typename(T& object) -{ - return abi::__cxa_demangle(typeid(object).name(), 0, 0, 0); -} - -PrintAstVisitorNode::PrintAstVisitorNode(std::ostream& _os) : os(_os) { -} - -PrintAstVisitorNode::~PrintAstVisitorNode() { -} - -bool PrintAstVisitorNode::before(Node const& n) { - this->os << "N" << std::hex << (long int)&n << - "[label=\"" << get_typename(n) << "\"];\n"; - return false; -} - -void PrintAstVisitorNode::visit_children(Node const& n) { - for (Node *c : n.children()) { - c->accept(*this); - - // print an edge between n and current child, - // using object pointer as an identifier - this->os << "N" << std::hex << (long int)&n << "--" << - "N" << std::hex << (long int)c << ";\n"; - } -} - -void PrintAstVisitorNode::visit(Node const& n) { - if (before(n)) { return; } - visit_children(n); - after(n); -} - -PrintAstVisitor::PrintAstVisitor(std::ostream& _os) : PrintAstVisitorNode(_os) { -} - -void PrintAstVisitor::visit(Program const& p) { - if (before(p)) { return; } - visit_children(p); - after(p); -} - -bool PrintAstVisitor::before(Program const& p) { - this->os << "graph {\nN" - << std::hex << (long int)&p - << "[label=\"" << get_typename(p) - << "\"];\n"; - return false; -} - -void PrintAstVisitor::after(Program const& p) { - this->os << "}\n"; -} - -void PrintAstVisitor::visit(Int8 const& n) { - this->os << "N" << std::hex << (long int)&n << - "[label=\"" << get_typename(n) << "(" << std::dec << (int)n.getNumber() << ")\"];\n"; -} - -void PrintAstVisitor::visit(Int16 const& n) { - this->os << "N" << std::hex << (long int)&n << - "[label=\"" << get_typename(n) << "(" << std::dec << n.getNumber() << ")\"];\n"; -} - -void PrintAstVisitor::visit(Int32 const& n) { - this->os << "N" << std::hex << (long int)&n << - "[label=\"" << get_typename(n) << "(" << std::dec << n.getNumber() << ")\"];\n"; -} - -void PrintAstVisitor::visit(While const& n) { - PrintAstVisitorNode::visit(n); -} - -const string PrintAstVisitor::getOperatorName(int op) { - switch (op) { - case EQ_OP: return "="; - case NE_OP: return "!="; - case LE_OP: return "<="; - case GE_OP: return ">="; - case LT_OP: return "<"; - case GT_OP: return ">"; - case '+' : return "+"; - case '-' : return "-"; - case '*' : return "*"; - case '/' : return "/"; - case '%' : return "%"; - case TOK_AND : return "and"; - case TOK_OR : return "or"; - default: return std::to_string(op); - } -} - -void PrintAstVisitor::visit(CmpOp const& n) { - this->os << "N" << std::hex << (long int)&n - << "[label=\"" << get_typename(n) << "(" << std::dec - << getOperatorName(n.getOperator()) << ")\"];\n"; - visit_children(n); -} - -void PrintAstVisitor::visit(BinaryOp const& n) { - this->os << "N" << std::hex << (long int)&n - << "[label=\"" << get_typename(n) << "(" << std::dec - << getOperatorName(n.getOperator()) << ")\"];\n"; - visit_children(n); -} - -void PrintAstVisitor::visit(Load const& n) { - this->os << "N" << std::hex << (long int)&n - << "[label=\"" << get_typename(n) << "(" << n.getIdent() << ")\"];\n"; - visit_children(n); -} - -void PrintAstVisitor::visit(Scalar const& n) { - this->os << "N" << std::hex << (long int)&n - << "[label=\"" << get_typename(n) << "(" << n.getIdent() << ")\"];\n"; - visit_children(n); -} - -void PrintAstVisitor::visit(Delay const& n) { - PrintAstVisitorNode::visit(n); -} - -void PrintAstVisitor::visit(If const& n) { - PrintAstVisitorNode::visit(n); -} - - diff --git a/src/PrintAstVisitor.h b/src/PrintAstVisitor.h deleted file mode 100644 index 393a4dc..0000000 --- a/src/PrintAstVisitor.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef __PRINT_AST_VISITOR_H__ -#define __PRINT_AST_VISITOR_H__ - -#include "Node.h" - -class PrintAstVisitorNode: public RecursiveVisitor { -protected: - std::ostream& os; -public: - PrintAstVisitorNode(std::ostream& _os); - virtual ~PrintAstVisitorNode(); - - virtual void visit_children(Node const& n); - virtual void visit(Node const& n) override; - virtual bool before(Node const& n) override; -}; - -class PrintAstVisitor: public PrintAstVisitorNode { -public: - PrintAstVisitor(std::ostream& _os); - - virtual void visit(Program const& p) override; - virtual void visit(Int8 const& n) override; - virtual void visit(Int16 const& n) override; - virtual void visit(Int32 const& n) override; - virtual void visit(While const& n) override; - - const string getOperatorName(int op); - virtual void visit(CmpOp const& n) override; - virtual void visit(BinaryOp const& n) override; - - virtual void visit(Load const& n) override; - virtual void visit(Scalar const& n) override; - virtual void visit(Delay const& n) override; - virtual void visit(If const& n) override; - - virtual bool before(Program const& p) override; - virtual void after(Program const& p) override; -}; - -#endif - diff --git a/src/Program.cpp b/src/Program.cpp index 0fdb795..932ce8e 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -1,121 +1,341 @@ -#include "Header.h" -Program::Program(Stmts *stmts) { - this->stmts = stmts; - node_children.reserve(1); - node_children.push_back(stmts); +#include +#include "Program.h" +#include "FunctionImpl.h" +#include "HeaderGlobals.h" +#include "BackLLVM.h" +#include "Interface.h" +#include "Pointer.h" +#include "UndefInit.h" +#include "Return.h" +#include "Load.h" +#include "BuildTypes.h" +#include "ConstructorCall.h" +#include "semantic/PrintAstVisitor.h" +#include "semantic/PropagateTypes.h" +#include "semantic/SymbolizeTree.h" +#include "semantic/VirtualDispatchPasses.h" + +Program::Program() : Node({0,0,0,0}) { + mainmodule = new Module(this->getFile(), global_context); + Builder = make_unique>(global_context); + + if (debug_info) { + mainmodule->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); + mainmodule->addModuleFlag(Module::Warning, "Dwarf Version", 4); + DBuilder = make_unique(*mainmodule); + RobDbgInfo.cunit = DBuilder->createCompileUnit(dwarf::DW_LANG_C11, + DBuilder->createFile(this->getFile(), std::filesystem::current_path().string()), + "Robcmp", false, "", 0); + + // global scope + RobDbgInfo.push_file(RobDbgInfo.cunit->getFile()); + RobDbgInfo.push_scope(RobDbgInfo.cunit); + } + + buildTypes = make_unique(currentTarget().pointerType, this); + global_alloc = BasicBlock::Create(global_context, "global"); + + dispatch = new Dispatch(); +} + +Program::~Program() { + delete dispatch; + delete mainmodule; +} + +Value *Program::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return NULL; +} + +void Program::generateInjectionGlobals(SourceLocation *sl) { + location_t loc = sl->getLoc(); + + // a function to init global vars for singleton injections + funcInitGlobals = new FunctionImpl((DataType)tvoid, "__injections_init", + new FunctionParams(), vector(), loc, loc, false); + funcInitGlobals->setScope(this); + funcInitGlobals->setAttributes(new FunctionAttributes(fa_inline)); + addSymbol(funcInitGlobals); + + for (auto &[key, itype] : injections) { + Identifier bind(itype->bind, loc); + + // injection validation + auto subTypeName = regex_replace(bind.getFullName(), regex("\\."), ":"); //internal types use : + Identifier bindSubtypes(subTypeName, loc); + Node *injectType = bindSubtypes.getSymbol(this, false); + if (!injectType) { + yyerrorcpp(string_format("Injection symbol %s not found.", + bind.getFullName().c_str()), &itype->loc); + continue; + } + + if (itype->scope == bs_singleton) { + string globalVarName = itype->singletonName; + if (!bind.isComplex()) { + Node *var = findSymbol(globalVarName); + if (!var) { + // alloc the global var + UndefInit *nc = new UndefInit(injectType->getDataType(), loc); + Scalar *svar = new Scalar(globalVarName, nc); + svar->setScope(this); + addSymbol(svar); + svar->generate(NULL, NULL, global_alloc); + var = svar; + + ConstructorCall *cc = new ConstructorCall(bind.getFullName(), loc); + Scalar *sc = new Scalar(globalVarName, cc); + cc->setScope(funcInitGlobals); + sc->setScope(funcInitGlobals); + funcInitGlobals->addChild(sc); + } + } + } + } } -void Program::declara_auxiliary_c_funcs() { - std::vector arg_types; - FunctionType *ftype; - - #ifdef ENABLE_ARDUINO - // analogRead - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - ftype = FunctionType::get(Type::getInt16Ty(global_context), - ArrayRef(arg_types), false); - analogRead = Function::Create(ftype, Function::ExternalLinkage, "analogRead", mainmodule); - analogRead->setCallingConv(CallingConv::C); - - // analogWrite or digitalWrite - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - arg_types.push_back(Type::getInt16Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - analogWrite = Function::Create(ftype, Function::ExternalLinkage, "analogWrite", mainmodule); - - // digitalWrite instead - /*arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - arg_types.push_back(Type::getInt8Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - analogWrite = Function::Create(ftype, Function::ExternalLinkage, "digitalWrite", mainmodule); +void Program::generateInjectionSetup(SourceLocation *sl) { + + location_t loc = sl->getLoc(); + + /* create a function for each injection, named :get_injection_for_[to]: + function :get_injection_for_[to] { + static instance = type() + return instance; + } */ + vector finjects; + for (auto &[key, itype] : injections) { + Identifier to(key, loc); + Identifier bind(itype->bind, loc); + + // injection validation + auto subTypeName = regex_replace(bind.getFullName(), regex("\\."), ":"); //internal types use : + Identifier bindSubtypes(subTypeName, loc); + Node *injectType = bindSubtypes.getSymbol(this, false); - analogWrite->setCallingConv(CallingConv::C); + DataType destinationTy = BuildTypes::undefinedType; + string destinationTyName; + UserType *bindUserTy = dynamic_cast(injectType); + if (!bindUserTy) { + yyerrorcpp(string_format("Bind symbol %s is not of a bindable type.", + bind.getFullName().c_str()), &itype->loc); + continue; + } else { + Node *nodeTo = to.getSymbol(this, false); + if (!nodeTo) { + yyerrorcpp(string_format("Injection destination %s not found.", + to.getFullName().c_str()), &itype->loc); + continue; + } else { + destinationTy = nodeTo->getDataType(); + destinationTyName = buildTypes->name(destinationTy); + if (!bindUserTy->implementsInterface(destinationTyName)) { + yyerrorcpp(string_format("Bind symbol %s does not implements %s.", + bind.getFullName().c_str(), destinationTyName.c_str()), bindUserTy); + continue; + } + } + } - // delay - arg_types.clear(); - arg_types.push_back(Type::getInt32Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - delay = Function::Create(ftype, Function::ExternalLinkage, "delay", mainmodule); - delay->setCallingConv(CallingConv::C); + // setup dispatcher to resolv from destinationTy to bindUserTy + program->getDispatcher()->addDataTypeImplementation(destinationTy, + bindUserTy->getDataType()); + // generate injection stuff - // delayMicroseconds - arg_types.clear(); - arg_types.push_back(Type::getInt32Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - delayMicroseconds = Function::Create(ftype, Function::ExternalLinkage, "delayMicroseconds", mainmodule); - delayMicroseconds->setCallingConv(CallingConv::C); + const string functionName = "__get_injection_for_" + to.getFullName(); + FunctionImpl *finject = new FunctionImpl(destinationTy, functionName, + new FunctionParams(), vector(), loc, loc, false); + finject->setReturnIsPointer(true); + finject->setScope(this); + finject->setAttributes(new FunctionAttributes(fa_inline)); + + if (itype->scope == bs_singleton) { + string globalVarName = itype->singletonName; + Load *load = new Load(Identifier(globalVarName, loc)); + Return *ret = new Return(load); + ret->setScope(finject); + load->setScope(finject); + finject->addChild(ret); + finjects.push_back(finject); + + } else { // bs_transient + assert(false && "TODO: implement bs_transient scope."); + } + } + + for(auto *finject : finjects) + finject->generate(NULL, NULL, global_alloc); + + funcInitGlobals->generate(NULL, NULL, global_alloc); +} + +void Program::declareBuiltins() { + + // typeid function + FunctionParams *typeid_params = new FunctionParams(); + typeid_params->append(new Variable("object", tobject, this->getLoc())); + FunctionDecl *typeid_decl = new FunctionDecl(tint8u, "typeid", typeid_params, this->getLoc()); + typeid_decl->setLinkage(GlobalValue::LinkOnceODRLinkage); + addChild(typeid_decl); + addSymbol(typeid_decl); +} + +void Program::generateBuiltins() { + auto SavedLoc = Builder->getCurrentDebugLocation(); + Builder->SetCurrentDebugLocation(DebugLoc()); + + // generate the typeid declaration + Node *decl = findSymbol("typeid"); + Value *typeidValue = decl->generate(NULL, NULL, global_alloc); + Function *typeidFunc = dyn_cast(typeidValue); + + // generate the typeid implementation + BasicBlock *body = BasicBlock::Create(global_context, "", typeidFunc); + Builder->SetInsertPoint(body); + auto& Arg = *typeidFunc->args().begin(); + Arg.addAttr(Attribute::ReadOnly); + auto *CmpVoid = Builder->CreateCmp(FCmpInst::ICMP_EQ, &Arg, + ConstantPointerNull::get(PointerType::getUnqual(Arg.getType()))); - // init - ftype = FunctionType::get(Type::getVoidTy(global_context), false); - init = Function::Create(ftype, Function::ExternalLinkage, "init", mainmodule); - init->setCallingConv(CallingConv::C); - #endif - - #ifdef ENABLE_PRINT - // print - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - arg_types.push_back(PointerType::get(IntegerType::get(global_context, 8), 0)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - print = Function::Create(ftype, Function::ExternalLinkage, "print", mainmodule); - print->setCallingConv(CallingConv::C); - #endif - - /* Not necessary anymore. Stay as an example - AttributeSet print_func_attrs; - print_func_attrs = - print_func_attrs.addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::NoUnwind) - .addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::StackProtect) - .addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::UWTable) - .addAttribute(global_context, 1, Attribute::ZExt); - print->setAttributes(print_func_attrs); */ - - // i16divse) - /*arg_types.clear(); - arg_types.push_back(Type::getInt16Ty(global_context)); - arg_types.push_back(Type::getInt16Ty(global_context)); - ftype = FunctionType::get(Type::getInt16Ty(global_context), - ArrayRef(arg_types), false); - i16div = Function::Create(ftype, Function::ExternalLinkage, "i16div", mainmodule); - i16div->setCallingConv(CallingConv::C);*/ + // if pointer is not set, return zero/void + BasicBlock *returnVoid = BasicBlock::Create(global_context, "", typeidFunc); + Builder->SetInsertPoint(returnVoid); + Builder->CreateRet(ConstantInt::get(typeidFunc->getReturnType(), 0)); + + // else, return the object typeid + BasicBlock *returnTypeid = BasicBlock::Create(global_context, "", typeidFunc); + Builder->SetInsertPoint(returnTypeid); + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); + Value *indexList[2] = {zero, zero}; + Type *idType = Type::getInt8Ty(global_context); + Value *idValue = Builder->CreateLoad(typeidFunc->getReturnType(), &Arg); + Builder->CreateRet(idValue); + + Builder->SetInsertPoint(body); + Builder->CreateCondBr(CmpVoid, returnVoid, returnTypeid); + + Builder->SetCurrentDebugLocation(SavedLoc); } -Value *Program::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - return NULL; +extern bool parseIsCompleted; + +void Program::doSemanticAnalysis() { + parseIsCompleted = true; + + declareBuiltins(); + + // instrumentation passes + SymbolizeTree st; + st.visit(*this); + + IdentifyVirtualDispatch ivd; + ivd.visit(*this); + + PropagateTypes pt; + pt.visit(*this); + + ivd.applyIdentifiedChanges(); + + buildTypes->generateDebugInfoForTypes(); + + /*std::fstream fs; + fs.open("ast", std::fstream::out); + PrintAstVisitor(fs).visit(*this); + fs.close();*/ } void Program::generate() { - // conversion between robcmp data types to llvm data types - robTollvmDataType[tvoid] = Type::getVoidTy(global_context); - robTollvmDataType[tbool] = Type::getInt1Ty(global_context); - robTollvmDataType[tchar] = Type::getInt8Ty(global_context); - robTollvmDataType[tint8] = Type::getInt8Ty(global_context); - robTollvmDataType[tint16] = Type::getInt16Ty(global_context); - robTollvmDataType[tint32] = Type::getInt32Ty(global_context); - robTollvmDataType[tint64] = Type::getInt64Ty(global_context); - robTollvmDataType[tint8u] = Type::getInt8Ty(global_context); - robTollvmDataType[tint16u] = Type::getInt16Ty(global_context); - robTollvmDataType[tint32u] = Type::getInt32Ty(global_context); - robTollvmDataType[tint64u] = Type::getInt64Ty(global_context); - robTollvmDataType[tfloat] = Type::getFloatTy(global_context); - robTollvmDataType[tdouble] = Type::getDoubleTy(global_context); - robTollvmDataType[tldouble] = Type::getFP128Ty(global_context); - - mainmodule = new Module(build_filename, global_context); - global_alloc = BasicBlock::Create(global_context, "global"); + generateBuiltins(); + + // find the main function + auto mainFuncIt = symbols.find("main"); + if (mainFuncIt == symbols.end()) + mainFuncIt = symbols.find("__main"); + Node *mainFunc = mainFuncIt->second; + + if (mainFunc) + generateInjectionGlobals(mainFunc); + + // build types and global vars first + map already_generated; + for(auto n: children()) { + if (dynamic_cast(n) || + dynamic_cast(n) || + dynamic_cast(n) || + dynamic_cast(n)) { + n->generate(NULL, NULL, global_alloc); + already_generated[n] = true; + } + } + + for(auto n: children()) { + if (n == mainFunc || already_generated[n]) + continue; + n->generate(NULL, NULL, global_alloc); + } + + if (mainFunc && injections.size() > 0) { + generateInjectionSetup(mainFunc); + FunctionCall *fc = new FunctionCall("__injections_init", new ParamsCall(), mainFunc->getLoc()); + fc->setScope(mainFunc); + mainFunc->addChild(fc, true); + } + + FunctionType *global_init_type = FunctionType::get(Type::getVoidTy(global_context), ArrayRef(), false); + Function *global_init = NULL; + if (mainFunc && global_alloc->size() > 0) { + // create a function named :global_init to init global vars by calling their constructors + global_init = Function::Create(global_init_type, Function::ExternalLinkage, codeAddrSpace, + "__globals_init", mainmodule); + global_init->addFnAttr(Attribute::AlwaysInline); + global_init->setCallingConv(CallingConv::C); + + // clear debug information as we will move instructions to __globals_init + vector remove; + for (auto &a : *global_alloc) { + if (a.getOpcode() == Instruction::Call) { + CallInst *call = dyn_cast(&a); + if (call->getCalledFunction()->isDeclaration()) { + a.replaceAllUsesWith(UndefValue::get(call->getType())); + remove.push_back(call); + continue; + } + } + a.setDebugLoc(DebugLoc()); + } + for(auto *i : remove) { + i->dropAllReferences(); + i->removeFromParent(); + } + Builder->SetInsertPoint(global_alloc); + Builder->CreateRetVoid(); + global_init->insert(global_init->end(), global_alloc); + } + + if (mainFunc) { + // add naked attribute to main to prevent backend + // of emmiting prologue and epilogue, as it is the + // first call in the stack + /*if (currentTargetId != st_native) + if (FunctionImpl *fi = dynamic_cast(mainFunc)) + fi->getAttributes()->addAttribute(fa_naked);*/ + + mainFunc->generate(NULL, NULL, global_alloc); + + if (global_init) { + Function *mainf = mainmodule->getFunction("main"); + BasicBlock *entryBlock = &mainf->getEntryBlock(); + Builder->SetInsertPoint(entryBlock->end()->getPrevNode()); // before br + Builder->CreateCall(global_init_type, global_init); + } + } + + dispatch->generateDispatchFunctions(program); - // generate the program! - stmts->generate(NULL, NULL, global_alloc); + if (debug_info) + DBuilder->finalize(); } diff --git a/src/Program.h b/src/Program.h index 0516ecc..d4c5100 100644 --- a/src/Program.h +++ b/src/Program.h @@ -1,18 +1,30 @@ -#ifndef __PROGRAM_H__ -#define __PROGRAM_H__ + +#pragma once + #include "Node.h" +#include "Dispatch.h" class Program : public Node { -private: - Stmts *stmts; +protected: + Dispatch *dispatch; + FunctionImpl *funcInitGlobals = NULL; public: - Program(Stmts *stmts); - + Program(); + ~Program(); + void declara_auxiliary_c_funcs(); - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); - void generate(); - + Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); + void generate(); + void generateInjectionSetup(SourceLocation *sl); + void generateInjectionGlobals(SourceLocation *sl); + void declareBuiltins(); + void generateBuiltins(); + void doSemanticAnalysis(); + + Dispatch* getDispatcher() { + return dispatch; + } }; -#endif +extern Program* program; diff --git a/src/RecursiveVisitor.cpp b/src/RecursiveVisitor.cpp deleted file mode 100644 index 398b6d5..0000000 --- a/src/RecursiveVisitor.cpp +++ /dev/null @@ -1,13 +0,0 @@ - -#include "Header.h" - -void RecursiveVisitor::visit(Node const& n) { - if (before(n)) { return; } - - for (auto &c : n.children()) { - c->accept(*this); - } - - after(n); -} - diff --git a/src/RecursiveVisitor.h b/src/RecursiveVisitor.h deleted file mode 100644 index 3d28048..0000000 --- a/src/RecursiveVisitor.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __RECURSIVE_VISITOR_H__ -#define __RECURSIVE_VISITOR_H__ -#include "Node.h" - -class RecursiveVisitor: public Visitor { -public: - void visit(Node const& n) override; -}; - -#endif - - - diff --git a/src/Return.cpp b/src/Return.cpp index 2f4c2b0..52cf2a7 100644 --- a/src/Return.cpp +++ b/src/Return.cpp @@ -1,9 +1,15 @@ -#include "Header.h" - Value *Return::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - IRBuilder<> builder(block); - Value *ret = node->generate(func, block, allocblock); - Type *retty = func->getReturnType(); - ret = Coercion::Convert(ret, retty, block, this); - return builder.CreateRet(ret); +#include "Return.h" +#include "FunctionImpl.h" + +Value *Return::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + Value *retvalue = NULL; + if (value()) { + retvalue = value()->generate(func, block, allocblock); + if (Instruction *ins = dyn_cast(retvalue)) + block = ins->getParent(); } + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateRet(retvalue); +} diff --git a/src/Return.h b/src/Return.h index 4bfed58..7490b77 100644 --- a/src/Return.h +++ b/src/Return.h @@ -1,15 +1,28 @@ -#ifndef __RETURN_H__ -#define __RETURN_H__ + +#pragma once + #include "Node.h" +#include "semantic/Visitor.h" class Return: public Node { -private: - Node *node; public: - Return(Node *n) { - this->node = n; + Return(location_t loc): Node(loc) { + dt = tvoid; + } + + Return(Node *n): Node(n->getLoc()) { + addChild(n); } - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); -}; -#endif + Node *value() { + if (node_children.empty()) + return NULL; + return node_children[0]; + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + Node* accept(Visitor& v) override { + return v.visit(*this); + } +}; diff --git a/src/RobSymbol.h b/src/RobSymbol.h deleted file mode 100644 index be9beef..0000000 --- a/src/RobSymbol.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __ROBSYMBOL_H__ -#define __ROBSYMBOL_H__ - -class RobSymbol: public SourceLocation { -public: - Value* value; - Type* pointerType; - DataQualifier qualifier; - unsigned int matrixLines; - unsigned int matrixCols; - - RobSymbol(Value *v, DataQualifier qualifier = qnone, Type *pointerType = NULL): - value(v), qualifier(qualifier), pointerType(pointerType) { - matrixLines = matrixCols = 0; - } -}; - -#endif diff --git a/src/Scalar.cpp b/src/Scalar.cpp index d32cad2..f980586 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -1,58 +1,193 @@ -#include "Header.h" -Scalar::Scalar(const char *n, Node *e, DataQualifier qualifier) : - name(n), expr(e), qualifier(qualifier) { - node_children.reserve(1); - node_children.push_back(e); +#include "Scalar.h" +#include "FunctionImpl.h" +#include "BackLLVM.h" +#include "HeaderGlobals.h" +#include "Pointer.h" +#include "Load.h" + +Scalar::Scalar(Identifier ident, Node *e) : + Variable(ident.getFullName(), ident.getLoc()) { + addChild(e); } -Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Scalar::Scalar(const string& ident, Node *e): Variable(ident, e->getLoc()) { + addChild(e); +} - auto symbol = search_symbol(name, allocblock, block); +Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - // variable doesn't exists - if (symbol == NULL) { - Value *ret, *leftv; - Value *exprv = expr->generate(func, block, allocblock); - if (!exprv) - return NULL; + Node *isymbol = ident.getSymbol(getScope()); + Variable *symbol = dynamic_cast(isymbol); + if (!symbol) + return NULL; + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + Pointer *reg = NULL; + Node *stem = NULL; + if (ident.isComplex()) { + Identifier istem = ident.getStem(); + stem = istem.getSymbol(getScope()); + + // Pointers need to load the stem, get its alloc + reg = dynamic_cast(stem); + if (reg && buildTypes->isComplex(reg->getDataType())) { + alloc = reg->getLLVMValue(NULL); + } else { + alloc = Load::getRecursiveField(ident, getScope(), func); + } + if (stem->hasQualifier(qvolatile)) + symbol->setQualifier(qvolatile); + } + + // set the allocated left value to: + // - a constructor initializing a user type field + // - a load for a new variable + Node *expr = getExpr(); + expr->setLeftValue(symbol); + + Value *exprv = expr->generateNewBlock(func, &block, allocblock); + if (!exprv) + return NULL; + DataType exprv_dt = expr->getDataType(); + + if (hasQualifier(qconst)) + return exprv; + + // expr->generate changes the location and block + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + if (!alloc) + alloc = symbol->getLLVMValue(func); + + // variable not allocated + if (alloc == NULL) { + Value *ret = NULL; + setDataType(exprv_dt); + if (allocblock == global_alloc) { Constant *exprvc = dyn_cast(exprv); if (exprvc == NULL) return NULL; //TODO: semantic error, global const value can't be generated - if (qualifier == qconst) - ret = leftv = exprvc; + if (symbol->hasQualifier(qconst)) + ret = alloc = exprvc; else { - GlobalVariable *gv = new GlobalVariable(*mainmodule, exprvc->getType(), - false, GlobalValue::CommonLinkage, exprvc, name); - ret = leftv = gv; + Type *gty = buildTypes->llvmType(dt); + if (expr->isPointerToPointer()) { + setPointerToPointer(true); + gty = PointerType::getUnqual(gty); + } + GlobalVariable *gv = new GlobalVariable(*mainmodule, gty, hasQualifier(qconst), + GlobalValue::ExternalLinkage, exprvc, name); + ret = alloc = gv; + + if (debug_info) + RobDbgInfo.declareGlobalVar(expr, gv, allocblock); } } else { - leftv = new AllocaInst(exprv->getType(), 0, name, allocblock); - ret = new StoreInst(exprv, leftv, qualifier == qvolatile, block); + Builder->SetInsertPoint(allocblock); + alloc = Builder->CreateAlloca(exprv->getType(), dataAddrSpace, 0, name); + Builder->SetInsertPoint(block); + ret = Builder->CreateStore(exprv, alloc, symbol->hasQualifier(qvolatile)); + + if (debug_info) + RobDbgInfo.declareVar(this, alloc, allocblock); + + // the symbol is in another scope + if (alloc && this != symbol) + symbol->setAlloca(alloc); } - tabelasym[allocblock][name] = new RobSymbol(leftv, qualifier); return ret; - } else { - if (symbol->qualifier == qconst) { - yyerrorcpp("Constant '" + name + "' can not be changed.", this); + } else { // variable already allocated + + if (symbol->hasQualifier(qconst) && !func->isConstructor()) { + yyerrorcpp("Constant '" + symbol->getName() + "' can not be changed.", this); return NULL; } - // variable already exists - Type *leftvty = symbol->value->getType(); - qualifier = symbol->qualifier; - if (symbol->pointerType) - leftvty = symbol->pointerType; - Value *exprv = expr->generate(func, block, allocblock); - auto nvalue = Coercion::Convert(exprv, leftvty, block, expr); - return new StoreInst(nvalue, symbol->value, qualifier == qvolatile, block); + + DataType currdt = symbol->getDataType(); + enum PointerMode pm = symbol->getPointerMode(); + + if (buildTypes->isComplex(currdt)) { + if (pm == pm_unknown) { + symbol->setPointer(pm_pointer); + pm = pm_pointer; + + } else if (pm == pm_nopointer && !func->isConstructor() && + exprv->getType()->isPointerTy()) { + // as any complex type is passed by ref, one must deref it before assigning + // to leftv, using the copy operator. + yyerrorcpp("Use the copy operator to dereference the rvalue.", this); + return NULL; + } + } + + Type *currty = buildTypes->llvmType(currdt); + if (pm == pm_pointer) + currty = PointerType::getUnqual(currty); + + Builder->SetInsertPoint(allocblock == global_alloc ? global_alloc : block); + Value *nvalue = NULL; + + // Pointers need a custom procedure: load the stem, set the + // requested bit value through bit shifting, and store the new value + if (reg && buildTypes->isComplex(reg->getDataType())) { + /* this code does: + * symbol->value &= ~(0x11... << fieldStartBit) + * symbol->value |= (exprv << fieldStartBit) + */ + Type *req_eq_ty = Type::getIntNTy(global_context, buildTypes->bitWidth(reg->getDataType())); + Value *v = Builder->CreateLoad(req_eq_ty, alloc, reg->hasQualifier(qvolatile), "ptrvalue"); + + // Prepare the mask + unsigned bitWidth = buildTypes->bitWidth(symbol->getDataType()); + Constant *allone = Constant::getAllOnesValue(Type::getIntNTy(global_context, bitWidth)); + Value *ones = Builder->CreateZExt(allone, req_eq_ty); + + // Coerce the rvalue to the req size + exprv = Builder->CreateZExt(exprv, req_eq_ty); + exprv = Builder->CreateAnd(exprv, ones, "truncrval"); + + unsigned fieldStartBit = reg->getFieldStartBit(symbol); + if (fieldStartBit > 0) { + Constant *shiftl = ConstantInt::get(req_eq_ty, fieldStartBit); + ones = Builder->CreateShl(ones, shiftl); + exprv = Builder->CreateShl(exprv, shiftl, "shift"); + } + Value *mask = Builder->CreateNot(ones); + + // Apply mask, than or + Value *vaftermask = Builder->CreateAnd(v, mask, "mask"); + nvalue = Builder->CreateOr(vaftermask, exprv, "setbits"); + + } else { + nvalue = exprv; + } + + if (nvalue != alloc) { + const DataLayout &DL = mainmodule->getDataLayout(); + Align align = DL.getABITypeAlign(nvalue->getType()); + return Builder->CreateAlignedStore(nvalue, alloc, align, symbol->hasQualifier(qvolatile)); + } else + return nvalue; } } -void Scalar::accept(Visitor& v) { - v.visit(*this); +DataType Scalar::getDataType() { + if (dt == BuildTypes::undefinedType) { + if (ident.isComplex()) { + Node *symbol = ident.getSymbol(getScope(), false); + if (symbol) + dt = symbol->getDataType(); + } else + dt = getExpr()->getDataType(); + } + return dt; } diff --git a/src/Scalar.h b/src/Scalar.h index 641820b..fbe4635 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -1,21 +1,46 @@ -#ifndef __SCALAR_H__ -#define __SCALAR_H__ -#include "Node.h" -#include "Float.h" -class Scalar: public Node { +#pragma once + +#include "Variable.h" +#include "semantic/Visitor.h" + +class Scalar: public Variable { private: - string name; - Node *expr; - DataQualifier qualifier; + bool used = false; + public: - Scalar(const char *n, Node *e, DataQualifier qualifier = qnone); + Scalar(const string& ident, Node *e); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + Scalar(Identifier ident, Node *e); - string getIdent() const { return name; }; + virtual Node *getExpr() override { + return node_children[0]; + } - virtual void accept(Visitor& v) override; -}; + virtual void setExpr(Node *expr) override { + node_children[0] = expr; + dt = expr->getDataType(); + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return hasQualifier(qconst) && getExpr()->isConstExpr(); + } -#endif + virtual DataType getDataType() override; + + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } + + void setUsed(bool value) { + used = value; + } + + bool isUsed() { + return used; + } + + friend class SymbolizeTree; +}; diff --git a/src/Scanner.cpp b/src/Scanner.cpp new file mode 100644 index 0000000..20b3565 --- /dev/null +++ b/src/Scanner.cpp @@ -0,0 +1,207 @@ + +#include "SourceLocation.h" +#include "Scanner.h" +#include "Program.h" +#include "FlexDependencies.h" +#include "Language_gen_y.hpp" + +extern Program *program; + +int errorsfound = 0; + +vector includeDirs; +vector buildStack; +stack useStack; +vector buildStackScanner; +int buildStackCurrent; +bool parseIsCompleted = false; +extern bool build_dependencies; + +int USElex(YYSTYPE *yylval_param, location_t *yylloc_param, yyscan_t yyscanner) { + return MAINlex(yylval_param, yylloc_param, yyscanner); +} + +int MAINlex_init(yyscan_t* scanner); +void MAINset_in(FILE *_in_str, yyscan_t yyscanner); +int MAINlex_destroy(yyscan_t yyscanner); +int USEparse(yyscan_t scanner); + +void yyerror(location_t *loc, yyscan_t scanner, const char *s) { + fprintf(stderr, ":%d:%d: %s\n", + loc->first_line, loc->first_column, s); + errorsfound++; +} + +void USEerror(location_t *loc, yyscan_t scanner, const char *s) { + SourceLocation l(*loc); + yyerrorcpp(s, &l, false); +} + +void MAINerror(location_t *loc, yyscan_t scanner, const char *s) { + SourceLocation l(*loc); + yyerrorcpp(s, &l, false); +} + +void yyerrorcpp(const string& s, SourceLocation *n, bool semantic) { + if (n->hasSemanticError()) + return; + + string e; + if (semantic) + e = COLOR_RED "semantic error: " COLOR_RESET + s; + else { + e = regex_replace(s, regex("syntax error[,:]?"), COLOR_RED "syntax error:" COLOR_RESET); + } + + fprintf(stderr, "%s:%d:%d: %s\n", + n->getFile().c_str(), n->getLineNo(), n->getColNo(), e.c_str()); + errorsfound++; + n->setSemanticError(); +} + +void yywarncpp(const string& s, SourceLocation *n) { + string e = COLOR_BLUE "warning: " COLOR_RESET + s; + fprintf(stderr, "%s:%d:%d %s\n", + n->getFile().c_str(), n->getLineNo(), n->getColNo(), e.c_str()); +} + +bool parseFile(const string& source) { + + filesystem::path file_path(source); + buildStack.push_back(file_path); + buildStackCurrent = 0; + + // search for use files in the path of build_filename; + // next in the working dir; next in the -I dirs (right from left) + includeDirs.push_back(file_path.parent_path()); + includeDirs.push_back("./"); + + FILE *f = fopen(file_path.string().c_str(), "r"); + if (f == NULL) { + cerr << string_format(file_not_found, file_path.string().c_str()); + return false; + } + + yyscan_t scanner; + MAINlex_init(&scanner); + buildStackScanner.push_back(scanner); + MAINset_in(f, scanner); + + if (program == NULL) + program = new Program(); + + MAINparse(scanner); + + MAINlex_destroy(scanner); + fclose(f); + + return true; +} + +FILE *findFile(string file_name, filesystem::path& file_path) { + FILE *f = NULL; + + // test current dir + filesystem::path test_path = file_name; + f = fopen(test_path.string().c_str(), "r"); + if (f) { + file_path = test_path; + return f; + } + + // include the dir of the current file + if (useStack.size() > 0) + includeDirs.push_back(useStack.top().parent_path()); + + for(auto dirit = rbegin(includeDirs); dirit != rend(includeDirs); ++dirit) { + filesystem::path test_path(*dirit); + test_path /= file_name; + f = fopen(test_path.string().c_str(), "r"); + if (f) { + file_path = test_path; + break; + } + } + + if (useStack.size() > 0) + includeDirs.pop_back(); + + return f; +} + +bool parseUseFile(const string& use, location_t loc, bool isPath) { + + // search for and open {use}.rob file + string file_name; + if (isPath) + file_name = use; + else { + const string sep{filesystem::path::preferred_separator}; + string use_file = regex_replace(use, regex("\\."), sep); + file_name = use_file + ".rob"; + } + filesystem::path file_path; + FILE *f = findFile(file_name, file_path); + + if (f == NULL) { + SourceLocation s(loc); + yyerrorcpp(string_format(file_not_found, file_name.c_str()), &s); + return false; + } + + auto it = find(buildStack.begin(), buildStack.end(), file_path); + if (it != buildStack.end()) { + // circular dependency + //#define PRINT_DEPENDENCY_LOOP + #ifdef PRINT_DEPENDENCY_LOOP + SourceLocation sl(loc); + yywarncpp(string_format("circular dependency for %s", file_path.c_str()), &sl); + while (it != buildStack.end()) { + fprintf(stderr, "\t%s ->\n", it->c_str()); + it++; + } + fprintf(stderr, "\t%s\n", file_path.c_str()); + #endif + fclose(f); + return true; + } + + int buildStackBackup = buildStackCurrent; + buildStack.push_back(file_path); + useStack.push(file_path); + buildStackCurrent = buildStack.size()-1; + + yyscan_t scanner; + MAINlex_init(&scanner); + buildStackScanner.push_back(scanner); + + MAINset_in(f, scanner); + //extern int USEdebug; + //USEdebug = 1; + if (build_dependencies) { + if (debug_info) { + string bPath = buildStack[buildStackCurrent]; + DIFile *file = DBuilder->createFile(bPath, std::filesystem::current_path().string()); + RobDbgInfo.push_file(file); + } + + MAINparse(scanner); + + if (debug_info) + RobDbgInfo.pop_file(); + } else + USEparse(scanner); + + MAINlex_destroy(scanner); + fclose(f); + + buildStackCurrent = buildStackBackup; + buildStackScanner.pop_back(); + //buildStack.pop_back(); + useStack.pop(); + + return true; +} + +int MAINget_lineno(yyscan_t yyscanner); +int MAINget_column(yyscan_t yyscanner); diff --git a/src/Scanner.h b/src/Scanner.h new file mode 100644 index 0000000..a6a9acf --- /dev/null +++ b/src/Scanner.h @@ -0,0 +1,25 @@ + +#pragma once + +#include +#include +#include + +#include "SourceLocation.h" + +using namespace std; + +static const char *file_not_found = "No such file or directory '%s'."; + +typedef void* yyscan_t; +extern int errorsfound; +extern vector includeDirs; + +void yyerror(location_t *loc, yyscan_t scanner, const char *s); +void USEerror(location_t *loc, yyscan_t scanner, const char *s); +void MAINerror(location_t *loc, yyscan_t scanner, const char *s); +void yyerrorcpp(const string& s, SourceLocation *n, bool semantic); +void yywarncpp(const string& s, SourceLocation *n); + +bool parseFile(const string &source); +bool parseUseFile(const string& use, location_t loc, bool isPath = false); diff --git a/src/SourceLocation.h b/src/SourceLocation.h index 345035b..5c49de6 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -1,24 +1,59 @@ #pragma once -extern int yylineno; -extern int yycolno; +#include "HeaderExternals.h" + +typedef struct { + int first_line; + int first_column; + int last_line; + int last_column; +} location_t; + +extern int buildStackCurrent; +extern vector buildStack; class SourceLocation { protected: - int lineno; - int colno; + location_t sloc; + int fileNo; + bool semanticError = false; + public: - SourceLocation() { - lineno = yylineno; - colno = yycolno; + SourceLocation(location_t l) { + fileNo = buildStackCurrent; + sloc = l; } - virtual int getLineNo() { - return lineno; + virtual int getLineNo() const { + return sloc.first_line; + } + + virtual int getColNo() const { + return sloc.first_column; + } + + virtual void setLocation(location_t l) { + sloc = l; + } + + virtual void setLocation(SourceLocation *s) { + sloc = s->sloc; + } + + virtual location_t getLoc() { + return sloc; + } + + virtual const string getFile() const { + return buildStack[fileNo]; + } + + bool hasSemanticError() const { + return semanticError; } - virtual int getColNo() { - return colno; + void setSemanticError() { + semanticError = true; } }; diff --git a/src/Stmts.cpp b/src/Stmts.cpp deleted file mode 100644 index 47ccc92..0000000 --- a/src/Stmts.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "Header.h" - - Stmts::Stmts(Node *s) { - this->stmts.push_back(s); - } - - std::vector const& Stmts::children() const { - return stmts; - } - - void Stmts::append(Node *s) { - stmts.push_back(s); - } - - void Stmts::prepend(Node *s) { - // put after function declarations - auto last_func = stmts.begin(); - auto iterator = stmts.begin(); - while (iterator != stmts.end()) { - if ((*iterator)->isFunctionDecl()) - last_func = iterator; - iterator = std::next(iterator); - } - last_func = std::next(last_func); - stmts.insert(last_func, s); - } - - Value *Stmts::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - for(Node *n: stmts) { - Value *b = n->generate(func, block, allocblock); - if (b && b->getValueID() == Value::BasicBlockVal) - block = (BasicBlock*)b; - } - return block; - } diff --git a/src/Stmts.h b/src/Stmts.h deleted file mode 100644 index 433ff8e..0000000 --- a/src/Stmts.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __STMTS_H__ -#define __STMTS_H__ -#include "Node.h" - -class Stmts: public Node { -private: - std::vector stmts; -public: - Stmts(Node *s); - - virtual std::vector const& children() const override; - - void append(Node *s); - - void prepend(Node *s); - - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; -}; - -#endif diff --git a/src/String.cpp b/src/String.cpp deleted file mode 100644 index 8f5250c..0000000 --- a/src/String.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "Header.h" - - Value *String::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantDataArray::getString(global_context, str, true);; - } diff --git a/src/String.h b/src/String.h deleted file mode 100644 index 8513e41..0000000 --- a/src/String.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __STRING_H__ -#define __STRING_H__ -#include "Node.h" - -class String: public Node { -private: - string str; -public: - String(const char *s): str(s) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); -}; - -#endif diff --git a/src/StringConst.cpp b/src/StringConst.cpp new file mode 100644 index 0000000..ea8dff1 --- /dev/null +++ b/src/StringConst.cpp @@ -0,0 +1,60 @@ + +#include "StringConst.h" +#include "BackLLVM.h" +#include "NamedConst.h" + +StringConst::StringConst(const string& name, const string& str, location_t loc) : + Array(name, loc), str(str) { + NamedConst *nc = new NamedConst("size", getNodeForUIntConst(str.size(), loc)); + addChild(nc); + addSymbol(nc); +} + +Value* StringConst::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + Builder->SetInsertPoint(allocblock); + + if (value) + return value; + + bool globalIsConstant = (allocblock != global_alloc); + if (globalIsConstant) { + // put the string content in a global + Constant *constant = ConstantDataArray::getString(global_context, str, false); + auto *gv = new GlobalVariable( + *mainmodule, constant->getType(), globalIsConstant, GlobalValue::PrivateLinkage, + constant, name); + gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); + + if (!leftValue || leftValue->hasQualifier(qconst)) { + // const a = "abcdef" or a call to func("abc") + // returns a pointer to the global constant gv + Constant *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); + Constant *indices[] = {zero, zero}; + value = ConstantExpr::getInBoundsGetElementPtr(gv->getValueType(), gv, indices); + } else { + // an initialized local string variable, e.g.: + // a = "abcdef", alloc array and copy string const to it + Type* I = buildTypes->llvmType(tchar); + auto arrayType = ArrayType::get(I, str.size()); + + // alloc array + Builder->SetInsertPoint(allocblock); + auto alloc = Builder->CreateAlloca(arrayType, dataAddrSpace, 0, leftValue->getName()); + if (debug_info) { + RobDbgInfo.emitLocation(this); + RobDbgInfo.declareVar(leftValue, alloc, allocblock); + } + leftValue->setAlloca(alloc); + + // copy string to the new array + Builder->SetInsertPoint(block); + Builder->CreateMemCpy(alloc, Align(1), gv, Align(1), str.size()); + value = alloc; + } + } else { + value = Builder->CreateGlobalString(str, name, 0, mainmodule, false); + leftValue->setAlloca(value); + } + + return value; +} diff --git a/src/StringConst.h b/src/StringConst.h new file mode 100644 index 0000000..c8e97f5 --- /dev/null +++ b/src/StringConst.h @@ -0,0 +1,42 @@ + +#pragma once + +#include "Array.h" +#include "HeaderGlobals.h" + +class StringConst: public Array { +protected: + string str; + Value *value = NULL; + Variable *leftValue = NULL; +public: + StringConst(const string& name, const string& str, location_t loc); + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual DataType getDataType() override { + if (dt == BuildTypes::undefinedType) + dt = buildTypes->getArrayType(buildTypes->name(tchar), getLoc(), 1, true); + return dt; + } + + virtual DataType getElementDataType() override { + return tchar; + } + + virtual int getSize() const override { + return str.size(); + } + + virtual Type *getLLVMType() override { + return buildTypes->llvmType(dt); + } + + virtual bool isConstExpr() override { + return true; + } + + void setLeftValue(Variable *symbol) override { + leftValue = symbol; + } +}; diff --git a/src/UndefInit.h b/src/UndefInit.h new file mode 100644 index 0000000..ce07549 --- /dev/null +++ b/src/UndefInit.h @@ -0,0 +1,21 @@ + +#pragma once + +#include "BuildTypes.h" +#include "HeaderGlobals.h" +#include "Node.h" + +class UndefInit: public Node { +public: + UndefInit(DataType dt, location_t loc): Node(loc) { + this->dt = dt; + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + return UndefValue::get(buildTypes->llvmType(dt)); + } + + virtual bool isConstExpr() override { + return true; + } +}; diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index 6b2eedf..d10a75b 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -1,45 +1,72 @@ -#include "Header.h" - -Value *UpdateArray::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - auto rsym = search_symbol(ident, allocblock, block); - /* TODO */ - if (rsym == NULL) { - yyerrorcpp("Variable " + ident + " not defined.", this); - return NULL; - } - auto sym = rsym->value; - - // sym type can be GlobalVariable or AllocInst - Type *ty = NULL; - if (auto *aux = dyn_cast(sym)) - ty = aux->getAllocatedType(); - else if (auto *aux = dyn_cast(sym)) - ty = aux->getValueType(); - - ArrayType *arrayTy = NULL; - if (ty->isArrayTy()) { - arrayTy = (ArrayType*)ty; - } - else { - yyerrorcpp("Symbol " + ident + " is not an array.", this); - return NULL; - } - - Node *indn = getUpdateIndex(rsym, block, allocblock); - Value *indice = indn->generate(func, block, allocblock); - if (!indice->getType()->isIntegerTy()){ - yyerrorcpp("Index to update " + ident + " elements should be of type integer.", this); - return NULL; - } - - Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); - - Value* indexList[2] = {zero, indice}; - GetElementPtrInst* ptr = GetElementPtrInst::Create(arrayTy, sym, ArrayRef(indexList), "", block); - Value *val = expr->generate(func, block, allocblock); - val = Coercion::Convert(val, arrayTy->getArrayElementType(), block, this); - StoreInst *store = new StoreInst(val, ptr, false, block); - - return store; + +#include "UpdateArray.h" +#include "FunctionImpl.h" +#include "HeaderGlobals.h" +#include "Load.h" + +UpdateArray::UpdateArray(const string &i, Node *pos, Node *expr, location_t loc): + BaseArrayOper(i, pos, NULL, loc) { + this->expr = expr; + addChild(pos); + addChild(expr); +} + +DataType UpdateArray::getElementDataType() { + if (element_dt == BuildTypes::undefinedType) { + Node *symbol = ident.getSymbol(getScope()); + if (symbol && buildTypes->isArrayOrMatrix(symbol->getDataType())) + element_dt = buildTypes->getArrayElementType(symbol->getDataType()); + } + return element_dt; } +Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + Node *symbol = ident.getSymbol(getScope()); + if (!symbol) + return NULL; + + if (!buildTypes->isArrayOrMatrix(symbol->getDataType())) { + yyerrorcpp("Symbol " + ident.getFullName() + " is not an array or matrix.", this); + return NULL; + } + + Builder->SetInsertPoint(block); + Value *sym = NULL; + if (ident.isComplex()) + sym = Load::getRecursiveField(ident, getScope(), func); + else + sym = symbol->getLLVMValue(func); + + // sym type can be GlobalVariable or AllocInst + Type *ty = NULL; + if (auto *aux = dyn_cast(sym)) + ty = aux->getAllocatedType(); + else if (auto *aux = dyn_cast(sym)) + ty = aux->getValueType(); + + Node *indn = getElementIndex(symbol); + Value *indice = indn->generateNewBlock(func, &block, allocblock); + if (!indice || !indice->getType()->isIntegerTy()){ + yyerrorcpp("Index to update " + ident.getFullName() + " elements must be of type integer.", this); + return NULL; + } + + Value *val = expr->generateNewBlock(func, &block, allocblock); + ArrayType *arrayTy = (ArrayType*)buildTypes->llvmType(symbol->getDataType()); + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + if (symbol->isPointerToPointer()) { + Type *ty = PointerType::getUnqual(buildTypes->llvmType(symbol->getDataType())); + sym = Builder->CreateLoad(ty, sym, symbol->hasQualifier(qvolatile), "deref"); + } + + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); + Value *indexList[2] = {zero, indice}; + Value *ptr = Builder->CreateGEP(arrayTy, sym, ArrayRef(indexList), "gep"); + StoreInst *store = Builder->CreateStore(val, ptr, false); + + return store; +} diff --git a/src/UpdateArray.h b/src/UpdateArray.h index fd6a34f..21c18cc 100644 --- a/src/UpdateArray.h +++ b/src/UpdateArray.h @@ -2,18 +2,29 @@ #pragma once #include "Node.h" +#include "LoadArray.h" +#include "semantic/Visitor.h" -class UpdateArray: public Node { +class UpdateArray: public BaseArrayOper { protected: - string ident; - Node *position; + DataType element_dt = BuildTypes::undefinedType; Node *expr; public: - UpdateArray(const char *i, Node *pos, Node *expr): ident(i), position(pos), expr(expr) {} + UpdateArray(const string &i, Node *pos, Node *expr, location_t loc); - virtual Node *getUpdateIndex(RobSymbol *rsym, BasicBlock *block, BasicBlock *allocblock) { - return position; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual DataType getElementDataType(); + + virtual Node* accept(Visitor& v) override { + return v.visit(*this); } - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + void setExpr(Node *n) { + expr = n; + } + + Node *getExpr() { + return expr; + } }; diff --git a/src/UpdateMatrix.h b/src/UpdateMatrix.h index afea498..6952c18 100644 --- a/src/UpdateMatrix.h +++ b/src/UpdateMatrix.h @@ -2,18 +2,18 @@ #pragma once #include "Node.h" +#include "UpdateArray.h" +#include "LoadMatrix.h" class UpdateMatrix: public UpdateArray { -private: - Node *position2; public: - UpdateMatrix(const char *i, Node *pos1, Node *pos2, Node *expr) : UpdateArray(i, pos1, expr) { - this->position2 = pos2; - } + UpdateMatrix(const string &i, Node *p1, Node *p2, Node *expr, location_t loc) : + UpdateArray(i, p1, expr, loc) { + this->position2 = p2; + addChild(p2); + } - virtual Node *getUpdateIndex(RobSymbol *rsym, BasicBlock *block, BasicBlock *allocblock) override { - //Generate index of element - Node *mcols = getNodeForIntConst(rsym->matrixCols); - return new BinaryOp(new BinaryOp(position, '*', mcols), '+', position2); + virtual Node* getElementIndex(Node *symbol) override { + return LoadMatrix::getElementIndexMatrix(this, symbol); } }; diff --git a/src/UserType.cpp b/src/UserType.cpp new file mode 100644 index 0000000..0651708 --- /dev/null +++ b/src/UserType.cpp @@ -0,0 +1,297 @@ + +#include "UserType.h" +#include "FunctionAttributes.h" +#include "HeaderGlobals.h" +#include "Identifier.h" +#include "Interface.h" +#include "FunctionImpl.h" +#include "FunctionDecl.h" +#include "FunctionParams.h" +#include "ConstructorCall.h" +#include "Variable.h" +#include "Enum.h" +#include "Load.h" +#include "BackLLVM.h" +#include "Int8.h" +#include "Scalar.h" +#include "Program.h" +#include "semantic/PropagateTypes.h" +#include "semantic/Visitor.h" + +class ParentScalar: public Scalar { +public: + ParentScalar(DataType parentDt, location_t loc) : + Scalar(Identifier("parent", loc), NULL) { + Load *load = new Load("_parent", loc); + load->setDataType(parentDt); + load->setScope(this); + setExpr(load); + dt = parentDt; + pointer = pm_pointer; + } + virtual DataType getDataType() override { + return dt; + } + virtual Type* getLLVMType() override { + return PointerType::getUnqual(global_context); + } +}; + +void UserType::setNestedParent() { + for(auto child : this->children()) { + if (UserType *ut = dynamic_cast(child)) { + ut->setParent(this); + } + } +} + +void UserType::createTempDataType() { + if (dt == BuildTypes::undefinedType) { + // create an undefined type to use in recursive subtypes + dt = buildTypes->getType(getTypeName(), true); + } +} + +bool UserType::createDataType() { + + if (buildTypes->isDefined(dt)) + return true; + + int idx = 0; + unsigned startBit = 0; + std::vector elements; + + // if needed, add typeid as the first field + if (implements.size() > 0) { + // the typeid field is needed if any implemented interface is unbound + // (not injected) and at least one of its methods was invoked + bool intfInvoked = false; + for(auto &intf : implements) { + DataType dt = buildTypes->getType(intf); + intfInvoked |= program->getDispatcher()->isIntfInvoked(dt); + } + + if (intfInvoked) { + typeId = new UInt8(0, getLoc()); // zero is changed below + Scalar *sc = new Scalar("typeid", typeId); + sc->setScope(this); + addChild(sc, true); + addSymbol(sc); + } + } + + // Process nested types + // They can add child to this instance, so we first identify nested UserTypes + vector nested; + for(auto child : this->children()) { + if (UserType *ut = dynamic_cast(child)) + nested.push_back(ut); + } + for(auto ut : nested) { + // internal user type: + // add a var in the internal type to store a reference to his parent + ParentScalar *s = new ParentScalar(dt, ut->getLoc()); + s->setScope(ut); + ut->addChild(s); + ut->addSymbol(s); + ut->createDataType(); + + // create a new var in the parent to store the intf implementation + ConstructorCall *cc = new ConstructorCall(ut->getTypeName(), ut->getLoc()); + Variable *v = new Scalar(ut->getName(), cc); + v->dt = ut->getDataType(); + cc->setScope(v); + v->setScope(this); + addChild(v); + + // replace the v->getName() symbol with its var and + symbols[v->getName()] = v; + + // add the nested type to the program root + program->addSymbol(ut->getTypeName(), ut); + } + + for(auto child : this->children()) { + Variable *v = dynamic_cast(child); + if (v && !v->isConstExpr()) { + if (PropagateTypes::isUndefined(v, false)) { + return false; + } else if (buildTypes->isInterface(v->getDataType())) { + v->setPointer(pm_pointer); + v->setPointerToPointer(true); + } else if (v->getPointerMode() == pm_unknown) + v->setPointer(pm_nopointer); + + Type *llvmType = v->getLLVMType(); + assert(llvmType && "Can not construct a type without its LLVM type."); + if (!llvmType) + return false; + + elements.push_back(llvmType); + v->setGEPIndex(idx++); + + //FIXME: Fix for data alignment on non-packed structure/type + startBits[v->getName()] = startBit; + if (llvmType->isPointerTy()) + startBit += buildTypes->getTargetPointerBitWidth(); + else + startBit += buildTypes->bitWidth(v->getDataType()); + } + } + bitWidth = startBit; + + StructType *uttype = StructType::create(global_context, ArrayRef(elements), getTypeName()); + dt = buildTypes->addDataType(this, uttype, bitWidth); + if (parent) + buildTypes->setInternal(dt, true); + + if (dt == BuildTypes::undefinedType) { + yyerrorcpp("Type " + getTypeName() + " alread defined.", this); + yywarncpp(getTypeName() + " was first defined here.", buildTypes->location(dt)); + return false; + } + + if (typeId) { + Node *intfsymbol = program->findSymbol(implements[0]); + if (Interface *intf = dynamic_cast(intfsymbol)) + typeId->setNumber(intf->getNextConcreteId()); + } + + return true; +} + +void UserType::setThisArgToFunctions() { + /* set function parameters before generate + * A function can call others that are still not generated + * and request their type info. So, here we set all needed + * info to pre-generate their type. + */ + for(auto & [key, stmt] : getSymbols()) { + if (FunctionImpl *f = dynamic_cast(stmt)) { + f->setPrefixName(getTypeName()); + f->addThisArgument(dt); + f->setExternal(declaration); + } + } +} + +Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + if (!createDataType()) + return NULL; + + // semantic analysis + for(auto n : implements) { + Node *inode = findSymbol(n); + Interface *intf = dynamic_cast(inode); + if (!intf) { + yyerrorcpp("Interface " + n + " not defined.", this); + return NULL; + } + if (!intf->validateImplementation(this)) + return NULL; + } + + // get vars + vector fields; + for(auto & [key, stmt] : getSymbols()) { + if (Variable *c = dynamic_cast(stmt)) { + if (!c->isConstExpr()) + fields.push_back(c); + } + } + + // add parent fields to the function so that it can use them without prefix + for(auto & [key, stmt] : getSymbols()) { + if (FunctionImpl *f = dynamic_cast(stmt)) { + for(auto &field : fields) + f->addSymbol(dynamic_cast(field)); + } + } + + // generate user types and enums + for(auto* stmt : node_children) { + if (UserType *ut = dynamic_cast(stmt)) { + ut->setDeclaration(declaration); + ut->generate(func, block, allocblock); + } else if (Enum *en = dynamic_cast(stmt)) { + en->generate(func, block, allocblock); + } + } + + // generate functions + for(auto & [key, stmt] : getSymbols()) { + if (FunctionImpl *f = dynamic_cast(stmt)) { + f->generate(func, block, allocblock); + } + } + + // check if parent was not used and remove it + bool parentUsed = true; + if (parent) { + NamedNode *sparent = symbols["parent"]; + Scalar *parentscalar = dynamic_cast(sparent); + parentUsed = parentscalar && parentscalar->isUsed(); + if (!parentUsed && parentscalar) { + auto parentf = find(fields.begin(), fields.end(), parentscalar); + if (*parentf) + fields.erase(parentf); + removeChild(parentscalar); + unusedParents.insert(getTypeName()); + } + } + + // generate init function/constructor + FunctionParams *fp = new FunctionParams(); + FunctionBase *finit; + if (declaration) { + finit = new FunctionDecl((DataType)tvoid, "init", fp, getLoc()); + } else { + finit = new FunctionImpl((DataType)tvoid, "init", fp, + std::move(fields), getLoc(), getLoc(), true); + } + finit->addThisArgument(dt); + if (parent) { + if (parentUsed) { + finit->addParentArgument(parent->getDataType()); + } + // nested user types can be inlined in the parent init + finit->getAttributes()->addAttribute(fa_inline); + } + finit->setPrefixName(getTypeName()); + finit->setExternal(declaration); + finit->setConstructor(true); + finit->generate(func, block, allocblock); + + addChild(finit); + addSymbol(finit); + return NULL; +} + +Node* UserType::accept(Visitor& v) { + return v.visit(*this); +} + +unsigned UserType::getFieldStartBit(Node *field) { + return startBits[field->getName()]; +} + +const string UserType::getTypeName() const { + if (parent) + return parent->getName() + ":" + getName(); + else + return getName(); +} + +void UserType::addSymbol(NamedNode *nm) { + // addSymbol is overrided here because UserType has its + // own scope and shouldn't call findSymbol recursivelly + const string& label = nm->getName(); + auto it = symbols.find(label); + if (it != symbols.end()) { + yyerrorcpp(string_format("Symbol %s already declared for this type.", label.c_str()), nm); + yywarncpp("The first declaration is here.", it->second); + } + else + symbols[nm->getName()] = nm; +} diff --git a/src/UserType.h b/src/UserType.h new file mode 100644 index 0000000..e03f883 --- /dev/null +++ b/src/UserType.h @@ -0,0 +1,81 @@ + +#pragma once + +#include "Node.h" +#include "Int8.h" + +class Visitor; + +class UserType: public NamedNode { +private: + vector implements; + map startBits; + bool declaration = false; + UserType *parent = NULL; + unsigned bitWidth = 0; + UInt8 *typeId = NULL; + + bool createDataType(); + void setNestedParent(); + void createTempDataType(); + void setThisArgToFunctions(); + +public: + + UserType(const string name, vector &&stmts, location_t loc): + NamedNode(name, std::move(stmts), loc) { + setNestedParent(); + createTempDataType(); + } + + UserType(const string name, vector &&stmts, vector &&implements, location_t loc): + NamedNode(name, std::move(stmts), loc), implements(std::move(implements)) { + setNestedParent(); + createTempDataType(); + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + Node* accept(Visitor& v) override; + + unsigned getFieldStartBit(Node *field); + + void setDeclaration(bool d) { + declaration = d; + } + + UserType* getParent() { + return parent; + } + + void setParent(UserType *ut) { + parent = ut; + } + + virtual const string getTypeName() const; + + virtual void addSymbol(NamedNode *nm) override; + + unsigned getBitWidth() { + return bitWidth; + } + + bool implementsInterface(const string& intf) { + return std::find(implements.begin(), implements.end(), intf) != implements.end(); + } + + const vector& implementedIntfs() { + return implements; + } + + int getConcreteId() { + if (typeId) { + //assert(typeId && "Typeid field is not set."); + return typeId->getNumber(); + } else { + return -1; + } + } + + friend class PropagateTypes; +}; diff --git a/src/Variable.cpp b/src/Variable.cpp new file mode 100644 index 0000000..08af555 --- /dev/null +++ b/src/Variable.cpp @@ -0,0 +1,68 @@ + +#include "Variable.h" +#include "FunctionImpl.h" +#include "Scalar.h" + +Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { + int gepidx = getGEPIndex(); + if (gepidx != -1) { + Value *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); + Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), gepidx); + Value* indexList[2] = {zero, idx}; + + FunctionImpl *func = dynamic_cast(stem); + if (func && func->getThisArg()) { + // generating a function of a type: get the gep on _this or _parent parameters + DataType thisDt = func->getThisArgDt(); + Type *thisTy = buildTypes->llvmType(thisDt); + Value *thisptr = Builder->CreateLoad(PointerType::getUnqual(thisTy), func->getThisArg(), "derefthis"); + + if (!stem->getScope() || this->getScope() == stem->getScope()) { + // the var is being accessed in global scope (!stem->getScope()) or + // in a method of the type itself. Thus, we gep the field in _this argument + return Builder->CreateStructGEP(thisTy, thisptr, gepidx, "gep" + getName()); + + } else if (symbols.find("parent") != symbols.end()) { + // the symbol being accessed has a parent (acessing a nested type var or method) + // Thus, we access parent in _this and gep the field + DataType parentDt = this->getScope()->getDataType(); + Type *parentTy = buildTypes->llvmType(parentDt); + NamedNode *parent = symbols["parent"]; + Scalar *parentscalar = dynamic_cast(parent); + parentscalar->setUsed(true); + int idxParentInThis = static_cast(parent)->getGEPIndex(); + Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, idxParentInThis, "gepthis"); + Value *parentptr = Builder->CreateLoad(PointerType::getUnqual(parentTy), parentAlloc, "derefparent"); + return Builder->CreateStructGEP(parentTy, parentptr, gepidx, "gep" + getName()); + + } else { + // stem is a nested type and the var is in the parent scope. + // Thus, we access parent in stem and gep the field + Node *nestedType = stem->getScope(); + auto nestedSymbols = nestedType->getSymbols(); + Node *parentField = nestedSymbols.find("parent")->second; + Scalar *parentFieldVar = dynamic_cast(parentField); + parentFieldVar->setUsed(true); + assert(parentField && "Parent field must exists and have a gepIndex!"); + int idxParentInThis = parentFieldVar->getGEPIndex(); + Type *parentTy = buildTypes->llvmType(parentFieldVar->getDataType()); + Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, idxParentInThis, "gepparent"); + Value *parentptr = Builder->CreateLoad(PointerType::getUnqual(parentTy), parentAlloc, "derefparent"); + return Builder->CreateStructGEP(parentTy, parentptr, gepidx, "gep" + getName()); + } + } else { + // accessing a var of a user type: get the gep in the scope (user type) of the scalar + Type *udt = buildTypes->llvmType(stem->getDataType()); + Value *ptr = stem->getLLVMValue(gfunc); + if (stem->isPointerToPointer()) { + ptr = Builder->CreateLoad(PointerType::getUnqual(udt), ptr, "deref"); + } + return Builder->CreateStructGEP(udt, ptr, gepidx, "gepu"); + } + } + + if (!alloc && isConstExpr()) + return generate(NULL, NULL, NULL); + + return alloc; +} diff --git a/src/Variable.h b/src/Variable.h new file mode 100644 index 0000000..13f0034 --- /dev/null +++ b/src/Variable.h @@ -0,0 +1,63 @@ + +#pragma once + +#include "Node.h" +#include "Identifier.h" + +enum PointerMode {pm_unknown, pm_pointer, pm_nopointer}; + +class Variable: public NamedNode { +protected: + Value *alloc = NULL; + Identifier ident; + int gepIndex = -1; + enum PointerMode pointer = pm_unknown; + bool pseudoVar = false; + +public: + Variable(const string &name, location_t loc): NamedNode(name, loc), ident(name, loc) {} + + Variable(const string &name, DataType dt, location_t loc): NamedNode(name, loc), ident(name, loc) { + this->dt = dt; + } + + virtual Value* getLLVMValue(Node *stem, FunctionImpl *gfunc = NULL) override; + + virtual void setGEPIndex(int idx) { + gepIndex = idx; + } + + int getGEPIndex() const { + return gepIndex; + } + + void setPointer(enum PointerMode v) { + pointer = v; + } + + enum PointerMode getPointerMode() { + return pointer; + } + + void setAlloca(Value *alloc) { + this->alloc = alloc; + } + + virtual Node *getExpr() { + return NULL; + } + + virtual void setExpr(Node *e) {} + + Identifier& getIdent() { + return ident; + } + + void setPseudoVar(bool value) { + pseudoVar = value; + } + + bool isPseudoVar() { + return pseudoVar; + } +}; diff --git a/src/Visitor.cpp b/src/Visitor.cpp deleted file mode 100644 index 43be0ee..0000000 --- a/src/Visitor.cpp +++ /dev/null @@ -1,3 +0,0 @@ - -#include "Header.h" - diff --git a/src/Visitor.h b/src/Visitor.h deleted file mode 100644 index eaeaa88..0000000 --- a/src/Visitor.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef __VISITOR_H__ -#define __VISITOR_H__ - -#include "Node.h" - -#define VISITOR_DECLARE(T) \ - virtual void visit(T const&) {}; \ - virtual void after(T const&) {}; \ - virtual bool before(T const&) { return false; } - -class Visitor { -public: - VISITOR_DECLARE(Node); - VISITOR_DECLARE(BinaryOp); - VISITOR_DECLARE(Capsule); - VISITOR_DECLARE(CmpOp); - VISITOR_DECLARE(Delay); - VISITOR_DECLARE(Float); - VISITOR_DECLARE(FunctionCall); - VISITOR_DECLARE(FunctionDecl); - VISITOR_DECLARE(Matrix); - VISITOR_DECLARE(If); - VISITOR_DECLARE(InPort); - VISITOR_DECLARE(Int16); - VISITOR_DECLARE(Int32); - VISITOR_DECLARE(Int8); - VISITOR_DECLARE(Load); - VISITOR_DECLARE(LoadArray); - VISITOR_DECLARE(OutPort); - VISITOR_DECLARE(Print); - VISITOR_DECLARE(Program); - VISITOR_DECLARE(Return); - VISITOR_DECLARE(Scalar); - VISITOR_DECLARE(Stmts); - VISITOR_DECLARE(String); - VISITOR_DECLARE(Array); - VISITOR_DECLARE(While); -}; - -#endif - diff --git a/src/While.cpp b/src/While.cpp index f8f5959..bb57aa6 100644 --- a/src/While.cpp +++ b/src/While.cpp @@ -1,38 +1,52 @@ -#include "Header.h" -While::While(Node *e, Node *stms) : expr(e), stmts(stms) { - node_children.reserve(2); - node_children.push_back(e); - node_children.push_back(stms); +#include "While.h" +#include "FunctionImpl.h" + +While::While(Node *e, location_t loc) : Node(loc), expr(e) { + addChild(e); + stmts = NULL; +} + +While::While(Node *e, vector &&ss, location_t loc) : While(e, loc) { + stmts = new Node(std::move(ss), loc); + addChild(stmts); } -Value *While::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - BasicBlock *condwhile = BasicBlock::Create(global_context, "while_cond", func, 0); - Value *exprv = expr->generate(func, condwhile, allocblock); +Value *While::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + Function *llvmf = func->getLLVMFunction(); + BasicBlock *condwhile = BasicBlock::Create(global_context, "while_cond", llvmf, 0); + + // go to condition + RobDbgInfo.emitLocation(expr); + Builder->SetInsertPoint(block); + Builder->CreateBr(condwhile); + + BasicBlock *endcondwhile = condwhile; + Value *exprv = expr->generateNewBlock(func, &endcondwhile, allocblock); + + // check condition + RobDbgInfo.emitLocation(expr); + Builder->SetInsertPoint(endcondwhile); + + BasicBlock *bodywhile = BasicBlock::Create(global_context, "while_body", llvmf, 0); + BasicBlock *endwhile = BasicBlock::Create(global_context, "while_end", llvmf, 0); + Builder->CreateCondBr(exprv, bodywhile, endwhile); - BasicBlock *bodywhile = BasicBlock::Create(global_context, "while_body", func, 0); - // alloc instructions inside bodywhile should go to allocblock to prevent repeatedly allocation - Value *newb = stmts->generate(func, bodywhile, allocblock); + Value *newb = NULL; + if (stmts) + newb = stmts->generateChildren(func, bodywhile, allocblock); - BasicBlock *endwhile = BasicBlock::Create(global_context, "while_end", func, 0); - - BranchInst::Create(condwhile, block); - BranchInst::Create(bodywhile, endwhile, exprv, condwhile); - // identify last while body block BasicBlock *endbody = bodywhile; - if (newb->getValueID() == Value::BasicBlockVal) + if (newb && newb->getValueID() == Value::BasicBlockVal) endbody = (BasicBlock*)newb; // if end block already has a terminator, don't generate branch - if (!((BasicBlock*)endbody)->getTerminator()) - BranchInst::Create(condwhile, endbody); + if (!endbody->getTerminator()) { + Builder->SetInsertPoint(endbody); + Builder->CreateBr(condwhile); + } return endwhile; } - -void While::accept(Visitor& v) { - v.visit(*this); -} - diff --git a/src/While.h b/src/While.h index f3b5f24..5c33ff5 100644 --- a/src/While.h +++ b/src/While.h @@ -1,5 +1,5 @@ -#ifndef __WHILE_H__ -#define __WHILE_H__ + +#pragma once #include "Node.h" @@ -7,10 +7,10 @@ class While: public Node { private: Node *expr; Node *stmts; + public: - While(Node *e, Node *stms); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; -}; + While(Node *e, location_t loc); + While(Node *e, vector &&stmts, location_t loc); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; -#endif +}; diff --git a/src/ZeroInit.h b/src/ZeroInit.h new file mode 100644 index 0000000..b9c66c4 --- /dev/null +++ b/src/ZeroInit.h @@ -0,0 +1,22 @@ + +#pragma once + +#include "BuildTypes.h" +#include "HeaderGlobals.h" +#include "Node.h" + +class ZeroInit: public Node { +public: + ZeroInit(DataType dt, location_t loc): Node(loc) { + this->dt = dt; + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + return ConstantAggregateZero::get(buildTypes->llvmType(dt)); + //return ConstantPointerNull::get(PointerType::getUnqual(buildTypes->llvmType(dt))); + } + + virtual bool isConstExpr() override { + return true; + } +}; diff --git a/src/main.cpp b/src/main.cpp index a9d06cf..48ae37c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,70 +1,124 @@ -#include #include +#include -#include "Header.h" +#include "BackLLVM.h" +#include "Scanner.h" +#include "Program.h" -int errorsfound = 0; -int yycolno = 0; -int yycolnew = 0; -extern int yyparse(); -extern FILE *yyin; -void print_llvm_ir(const char *target, char opt_level); -Function *AttachInterrupt::fattach = NULL; +Program *program = NULL; -// file name -char *build_filename; +int print_llvm_ir(char opt_level); +void setup_target_machine(char opt_level); +bool debug_info; +bool build_dependencies; char *build_outputfilename; +char *spec_filename; +FILE *specin = NULL; +int speclex_init(yyscan_t* scanner); +void specset_in(FILE *_in_str, yyscan_t yyscanner); +int speclex_destroy(yyscan_t yyscanner); +int specparse(yyscan_t scanner); + +#include +#include +#include +void SIGSEGV_handler(int sig) { + void *array[10]; + size_t size; + + // get void*'s for all entries on the stack + size = backtrace(array, 10); + + // print out all the frames to stderr + fprintf(stderr, "Error: signal %d:\n", sig); + backtrace_symbols_fd(array, size, STDERR_FILENO); + exit(1); +} + int main(int argc, char *argv[]) { + signal(SIGSEGV, SIGSEGV_handler); char optimization = 'z'; const char *targetarch = ""; build_outputfilename = NULL; + debug_info = false; + build_dependencies = false; if (argc <= 1) { - fprintf(stderr, "Syntax: %s -O{1,2,3,s,z} -a {", argv[0]); + fprintf(stderr, "Syntax: %s -a {", argv[0]); for(int t = 1; t < (sizeof(supportedTargets)/sizeof(TargetInfo)); t++) { if (t > 1) fprintf(stderr, ","); fprintf(stderr, "%s", supportedTargets[t].name); } - fprintf(stderr, "} -o output_file input_file\n"); + fprintf(stderr, "} -I {include_dir} -bdep -g -O{0,1,2,3,s,z,d} -o output.o -s in.spec input.rob\n"); return 1; } // Compila o arquivo passado como parâmetro + const char* buildFileName = NULL; + FILE *source = NULL; int i = 1; while (i < argc) { if (strncmp(argv[i], "-O", 2) == 0) { - if (strlen(argv[1]) > 2) + if (strlen(argv[i]) > 2) optimization = argv[i][2]; } - else if (strncmp(argv[i], "-a", 2) == 0) { + else if (strncmp(argv[i], "-a", 2) == 0) { // target arch targetarch = argv[++i]; } - else if (strncmp(argv[i], "-o", 2) == 0) { - build_outputfilename = argv[++i]; + else if (strncmp(argv[i], "-g", 2) == 0) { // debug + debug_info = true; } - else { - build_filename = argv[i]; - yyin = fopen(build_filename, "r"); - if (yyin == NULL) { - fprintf(stderr, "Could not open file %s.\n", build_filename); + else if (strncmp(argv[i], "-bdep", 5) == 0) { + build_dependencies = true; + } + else if (strncmp(argv[i], "-o", 2) == 0) { // output + if (i+1 < argc) + build_outputfilename = argv[++i]; + } + else if (strncmp(argv[i], "-I", 2) == 0) { // include dirs + if (i+1 < argc) + includeDirs.push_back(argv[++i]); + } + else if (strncmp(argv[i], "-s", 2) == 0) { + spec_filename = argv[++i]; + specin = fopen(spec_filename, "r"); + if (specin == NULL) { + fprintf(stderr, "Could not open specification file %s.\n", spec_filename); exit(1); } } + else { + buildFileName = argv[i]; + } i++; } - yyparse(); - if (yyin) - fclose(yyin); - if (errorsfound > 0) { - fprintf(stderr, "%d error(s) found.\n", errorsfound); - return errorsfound; + // set current target and basic build types + setTarget(targetarch); + + if (!buildFileName || !parseFile(buildFileName)) + exit(1); + + if (specin) { + if (!parseUseFile(spec_filename, {0,0,0,0}, true)) + exit(1); } - print_llvm_ir(targetarch, optimization); + setup_target_machine(optimization); + + program->doSemanticAnalysis(); + + if (errorsfound <= 0) + program->generate(); + + if (errorsfound <= 0) + errorsfound = print_llvm_ir(optimization); + + if (errorsfound > 0) + fprintf(stderr, "%d error(s) found.\n", errorsfound); - return 0; + return errorsfound; } diff --git a/src/out/.gitkeep b/src/out/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/passes/PassStripUnusedFields.h b/src/passes/PassStripUnusedFields.h new file mode 100644 index 0000000..b504573 --- /dev/null +++ b/src/passes/PassStripUnusedFields.h @@ -0,0 +1,181 @@ +#pragma once + +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Type.h" + +#include "BackLLVM.h" + +using namespace llvm; +using namespace std; + + +struct StripUnusedParentFieldsPass : PassInfoMixin { + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { + map modifiedTypes; + + for(auto& structName : unusedParents) { + StructType *oldTy = StructType::getTypeByName(M.getContext(), structName); + + if (!oldTy || oldTy->isOpaque() || oldTy->getNumElements() == 0) + continue; + + oldTy->setName(oldTy->getName().str() + ".discard"); + + // Prepare new element list without parent (last field) + ArrayRef elements = oldTy->elements(); + std::vector newElements(elements.begin(), elements.end() - 1); + + // Create the new StructType + StructType *newTy = StructType::create(oldTy->getContext(), newElements, + structName, oldTy->isPacked()); + + modifiedTypes[oldTy] = newTy; + } + + // identify structs that depends on the old type + for (StructType *S : M.getIdentifiedStructTypes()) { + if (S->isOpaque()) + continue; + + bool changed = false; + vector newElements; + for(int i = 0; i < S->getNumElements(); i++) { + auto element = modifiedTypes.find(S->getElementType(i)); + if (element != modifiedTypes.end()) { + newElements.push_back(element->second); + changed = true; + } else { + newElements.push_back(S->getElementType(i)); + } + } + + // change old structure name and create a new one + if (changed) { + string name = S->getName().str(); + S->setName(S->getName().str() + ".discard"); + StructType *newTy = StructType::create(S->getContext(), newElements, + name, S->isPacked()); + modifiedTypes[S] = newTy; + } + } + + for(auto& [oldty, newty] : modifiedTypes) { + replaceGlobals(M, oldty, newty); + replaceGEP(M, oldty, newty); + } + + return PreservedAnalyses::all(); + } + + void replaceGlobals(Module &M, Type *oldty, Type *newty) { + + // Find globals of the old type + std::vector toReplace; + for (GlobalVariable &GV : M.globals()) { + if (GV.getValueType() == oldty) { + toReplace.push_back(&GV); + } + } + + for (GlobalVariable *GV : toReplace) { + auto *newGV = new GlobalVariable(M, newty, GV->isConstant(), GV->getLinkage(), + GV->getInitializer(), GV->getName(), nullptr, GV->getThreadLocalMode(), GV->getAddressSpace() + ); + GV->replaceAllUsesWith(newGV); + GV->eraseFromParent(); + } + } + + void replaceGEP(Module &M, Type *oldty, Type *newty) { + std::vector toReplace; + //std::vector toReplaceStore; + std::vector toReplaceReturn; + + // Collect all GEPs using oldty + for (Function &F : M) { + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + if (auto *GEP = dyn_cast(&I)) { + if (GEP->getSourceElementType() == oldty) { + toReplace.push_back(GEP); + } + } /*else if (auto *Store = dyn_cast(&I)) { + auto *val = Store->getPointerOperand(); + if (isa(val)) { + auto *GEP = cast(val); + if (GEP->getSourceElementType() == oldty) { + GEP->print(errs()); + errs() << "\n"; + Store->print(errs()); + errs() << "\n"; + //toReplaceStore.push_back(Store); + } + } + }*/ + else if (auto *Return = dyn_cast(&I)) { + auto *val = Return->getReturnValue(); + if (!val) continue; + if (auto *CE = dyn_cast(val)) { + if (CE->getOpcode() == Instruction::GetElementPtr) { + const auto *GO = cast(CE); + if (GO->getSourceElementType() == oldty) { + toReplaceReturn.push_back(Return); + } + } + } + } + } + } + } + + auto createNewGEP = [](IRBuilder<> &B, Type *newty, GetElementPtrInst *GEP) { + Value *ptr = GEP->getPointerOperand(); + SmallVector indices(GEP->idx_begin(), GEP->idx_end()); + Value *newGEP = B.CreateGEP(newty, ptr, indices); + newGEP->setName(GEP->getName()); + return newGEP; + }; + + for (GetElementPtrInst *GEP : toReplace) { + IRBuilder<> B(GEP); + if (GEP->getSourceElementType() == nullptr) + continue; + auto *newGEP = createNewGEP(B, newty, GEP); + GEP->replaceAllUsesWith(newGEP); + GEP->eraseFromParent(); + } + + /*for (StoreInst *Store : toReplaceStore) { + IRBuilder<> B(Store); + auto *val = Store->getPointerOperand(); + auto *GEP = cast(val); + auto *newGEP = createNewGEP(B, newty, GEP); + + auto *newStore = B.CreateStore(Store->getValueOperand(), newGEP, Store->isVolatile()); + Store->replaceAllUsesWith(newStore); + Store->eraseFromParent(); + }*/ + + for (ReturnInst *Return : toReplaceReturn) { + IRBuilder<> B(Return); + + auto *val = Return->getReturnValue(); + auto *CE = dyn_cast(val); + const auto *GO = cast(CE); + + Value *ptr = CE->getOperand(0); + SmallVector indices(GO->idx_begin(), GO->idx_end()); + Value *newGEP = B.CreateGEP(newty, ptr, indices); + newGEP->setName(GO->getName()); + + auto *newReturn = B.CreateRet(newGEP); + Return->replaceAllUsesWith(newReturn); + Return->eraseFromParent(); + } + } +}; diff --git a/src/semantic/PrintAstVisitor.cpp b/src/semantic/PrintAstVisitor.cpp new file mode 100644 index 0000000..2ebb9c5 --- /dev/null +++ b/src/semantic/PrintAstVisitor.cpp @@ -0,0 +1,146 @@ + +#define SCANNER_OR_VISITOR +#include "Header.h" +#include +#include "Language_gen_y.hpp" +#include "Program.h" +#include "PrintAstVisitor.h" + +template char* get_typename(T& object) +{ + return abi::__cxa_demangle(typeid(object).name(), 0, 0, 0); +} + +bool PrintAstVisitor::before(Node& n) { + this->os << "N" << std::hex << (uint64_t)&n << + "[label=\"" << get_typename(n) << "\"];\n"; + return false; +} + +void PrintAstVisitor::after(Node& n) { +} + +void PrintAstVisitor::visit_children(Node& n) { + for (Node *c : n.children()) { + c->accept(*this); + + // print an edge between n and current child, + // using object pointer as an identifier + this->os << "N" << std::hex << (uint64_t)&n << "--" << + "N" << std::hex << (uint64_t)c << ";\n"; + } +} + +Node* PrintAstVisitor::visit(Node& n) { + if (before(n)) { return NULL; } + visit_children(n); + after(n); + return NULL; +} + +PrintAstVisitor::PrintAstVisitor(std::ostream& _os) : os(_os) { +} + +Node* PrintAstVisitor::visit(Program& p) { + if (before(p)) { return NULL; } + visit_children(p); + after(p); + return NULL; +} + +bool PrintAstVisitor::before(Program& p) { + this->os << "graph {\nN" + << std::hex << (uint64_t)&p + << "[label=\"" << get_typename(p) + << "\"];\n"; + return false; +} + +void PrintAstVisitor::after(Program& p) { + this->os << "}\n"; +} + +Node* PrintAstVisitor::visit(Int8& n) { + this->os << "N" << std::hex << (uint64_t)&n << + "[label=\"" << get_typename(n) << "(" << std::dec << (int)n.getNumber() << ")\"];\n"; + return NULL; +} + +Node* PrintAstVisitor::visit(Int16& n) { + this->os << "N" << std::hex << (uint64_t)&n << + "[label=\"" << get_typename(n) << "(" << std::dec << n.getNumber() << ")\"];\n"; + return NULL; +} + +Node* PrintAstVisitor::visit(Int32& n) { + this->os << "N" << std::hex << (uint64_t)&n << + "[label=\"" << get_typename(n) << "(" << std::dec << n.getNumber() << ")\"];\n"; + return NULL; +} + +const string PrintAstVisitor::getOperatorName(int op) { + switch (op) { + case EQ_OP: return "="; + case NE_OP: return "!="; + case LE_OP: return "<="; + case GE_OP: return ">="; + case LT_OP: return "<"; + case GT_OP: return ">"; + case TOK_AND : return "and"; + case TOK_OR : return "or"; + case TOK_LSHIFT: return "<<"; + case TOK_RSHIFT: return ">>"; + default: return string(1, (char)op); + } +} + +Node* PrintAstVisitor::visit(CmpOp& n) { + this->os << "N" << std::hex << (uint64_t)&n + << "[label=\"" << get_typename(n) << "(" << std::dec + << getOperatorName(n.getOperator()) << ")\"];\n"; + visit_children(n); + return NULL; +} + +Node* PrintAstVisitor::visit(BinaryOp& n) { + this->os << "N" << std::hex << (uint64_t)&n + << "[label=\"" << get_typename(n) << "(" << std::dec + << getOperatorName(n.getOperator()) << ")\"];\n"; + visit_children(n); + return NULL; +} + +Node* PrintAstVisitor::visit(Load& n) { + this->os << "N" << std::hex << (uint64_t)&n + << "[label=\"" << get_typename(n) << "(" << n.getName() << ")\"];\n"; + visit_children(n); + return NULL; +} + +Node* PrintAstVisitor::visit(Scalar& n) { + this->os << "N" << std::hex << (uint64_t)&n + << "[label=\"" << get_typename(n) << "(" << n.getName() << ")\"];\n"; + visit_children(n); + return NULL; +} + +Node* PrintAstVisitor::visit(NamedNode& n) { + this->os << "N" << std::hex << (uint64_t)&n + << "[label=\"" << get_typename(n) << "(" << n.getName() << ")\"];\n"; + visit_children(n); + return NULL; +} + +Node* PrintAstVisitor::visit(FunctionCall& n) { + this->os << "N" << std::hex << (uint64_t)&n + << "[label=\"" << get_typename(n) << "(" << n.getIdent().getFullName() << ")\"];\n"; + visit_children(n); + return NULL; +} + +Node* PrintAstVisitor::visit(CoercionBase& n) { + this->os << "N" << std::hex << (uint64_t)&n + << "[label=\"" << get_typename(n) << "(" << buildTypes->name(n.getDataType()) << ")\"];\n"; + visit_children(n); + return NULL; +} \ No newline at end of file diff --git a/src/semantic/PrintAstVisitor.h b/src/semantic/PrintAstVisitor.h new file mode 100644 index 0000000..ea5bf31 --- /dev/null +++ b/src/semantic/PrintAstVisitor.h @@ -0,0 +1,36 @@ + +#pragma once + +#include "Node.h" +#include "RecursiveVisitor.h" + +class PrintAstVisitor: public RecursiveVisitor { +protected: + std::ostream& os; +public: + PrintAstVisitor(std::ostream& _os); + + virtual Node* visit(Node& p) override; + void visit_children(Node& n); + bool before(Node& n) override; + void after(Node& n) override; + + virtual Node* visit(Program& p) override; + virtual Node* visit(Int8& n) override; + virtual Node* visit(Int16& n) override; + virtual Node* visit(Int32& n) override; + + const string getOperatorName(int op); + virtual Node* visit(CmpOp& n) override; + virtual Node* visit(BinaryOp& n) override; + + virtual Node* visit(Load& n) override; + virtual Node* visit(Scalar& n) override; + + virtual Node* visit(NamedNode& n) override; + virtual Node* visit(FunctionCall& n) override; + virtual Node* visit(CoercionBase& n) override; + + virtual bool before(Program& p) override; + virtual void after(Program& p) override; +}; diff --git a/src/semantic/PropagateTypes.cpp b/src/semantic/PropagateTypes.cpp new file mode 100644 index 0000000..7afffbe --- /dev/null +++ b/src/semantic/PropagateTypes.cpp @@ -0,0 +1,586 @@ + +#include "FlexDependencies.h" +#include "Language_gen_y.hpp" + +#include "PropagateTypes.h" +#include "ConstructorCall.h" +#include "Scalar.h" +#include "Program.h" + +void PropagateTypes::propagateChildren(Node& n, std::function lambda) { + for (auto it = n.node_children.begin(); it != n.node_children.end(); ++it) { + Node *replace = (*it)->accept(*this); + if (replace) { + *it = replace; + } + if (lambda) + lambda(**it); + } +} + +Node* PropagateTypes::coerceToUserTypes(Node *n, const DataType destTy) { + DataType ndt = n->getDataType(); + if (!buildTypes->isComplex(ndt) && !buildTypes->isArrayOrMatrix(ndt)) + return NULL; + + if (ndt != destTy) { + Node *utnode = n->getScope()->findSymbol(buildTypes->name(ndt)); + UserType *ut = dynamic_cast(utnode); + + if (ut && ut->implementsInterface(buildTypes->name(destTy))) { + program->getDispatcher()->addDataTypeImplementation(destTy, ndt); + return n; + } else if (buildTypes->isArrayOrMatrix(ndt)) { + if (buildTypes->isArrayCompatible(ndt, destTy)) + return n; + } else if (destTy == tobject && + (buildTypes->isComplex(ndt) || buildTypes->isInterface(ndt))) { + return n; + } + } + + return NULL; +} + +Node* PropagateTypes::coerceTo(Node *n, const DataType destTy, bool warns) { + if (isUndefined(n)) + return NULL; + + DataType valueTy = n->getDataType(); + if (valueTy == destTy) + return n; + + // can coerce only between numeric types + bool lIsNumeric = buildTypes->isNumericDataType(destTy); + bool rIsNumeric = buildTypes->isNumericDataType(valueTy); + if (!lIsNumeric || !rIsNumeric) { + Node *result = coerceToUserTypes(n, destTy); + if (!result) { + yyerrorcpp(string_format("Can not cast from '%s' to '%s'.", + buildTypes->name(valueTy), + buildTypes->name(destTy)), n); + return NULL; + } + } + + bool destUnsigned = buildTypes->isUnsignedDataType(destTy); + bool valueUnsigned = buildTypes->isUnsignedDataType(valueTy); + uint destBWidth = buildTypes->bitWidth(destTy); + uint valueBWidth = buildTypes->bitWidth(valueTy); + + // both sides integer + if (buildTypes->isIntegerDataType(destTy) && buildTypes->isIntegerDataType(valueTy)) { + + // if we have signed and unsigned operands, convert valueTy to destTy + if ((destUnsigned ^ valueUnsigned) && valueTy != tbool) { + // if value is constant, convert it to the dest type + bool valueIsConstant = n->isConstExpr(); + if (valueIsConstant) { + valueTy = valueUnsigned ? buildTypes->unsignedToSigned(valueTy) : + buildTypes->signedToUnsigned(valueTy); + } /*else if (warns) { + string name = n->getName(); + if (name == "") + name = "Value"; + if (destUnsigned) + yywarncpp(string_format("%s has been used as unsigned.", name.c_str()), n); + else + yywarncpp(string_format("%s has been used as signed.", name.c_str()), n); + }*/ + } + + // if destTy is larger, SExtended or ZExtended value + if (destBWidth > valueBWidth) { + Node *expand; + if (valueUnsigned) + expand = new ZExtInt(n, destTy); + else + expand = new SExtInt(n, destTy); + return expand; + + } else if (destBWidth < valueBWidth) { + if (n->isConstExpr()) { + // if the value is constant, check if the number of active bits + // fits in the dest bit width and prevent false trunc warnings + Value *nv = n->generate(NULL, NULL, NULL); + Constant *c = dyn_cast(nv); + unsigned bits = c->getUniqueInteger().getActiveBits(); + if (bits <= destBWidth) + warns = false; + } + if (warns) { + string name = n->getName(); + if (name == "") + name = "Value"; + yywarncpp(string_format("%s (%s) has been truncated to %s.", name.c_str(), + buildTypes->name(valueTy), buildTypes->name(destTy)), n); + } + return new TruncInt(n, destTy); + } + } + + // both sides float point + if (buildTypes->isFloatDataType(destTy) && buildTypes->isFloatDataType(valueTy)) { + + // if destTy is larger, Extended value + if (destBWidth > valueBWidth) + return new ExtendFloat(n, destTy); + else if (destBWidth < valueBWidth) { + if (warns) + yywarncpp(string_format("Value has been truncated to %s.", buildTypes->name(destTy)), n); + return new TruncFloat(n, destTy); + } + } + + bool isDestInteger = buildTypes->isIntegerDataType(destTy); + bool isDestFloat = buildTypes->isFloatDataType(destTy); + bool isValueInteger = buildTypes->isIntegerDataType(valueTy); + bool isValueFloat = buildTypes->isFloatDataType(valueTy); + + if (isDestInteger && isValueFloat) { + if (warns) + yywarncpp(string_format("Float value has been truncated to %s.", buildTypes->name(destTy)), n); + return new FloatToInt(n, destTy); + } else if (isValueInteger && isDestFloat) { + return new IntToFloat(n, destTy); + } + + return n; +} + +Value *ForcedCast::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + Node *converted = PropagateTypes::coerceTo(node, dt, false); + if (converted) + return converted->generate(func, block, allocblock); + else + return NULL; +}; + +DataType PropagateTypes::coerceArithOrCmp(Node &n, Node *lNode, Node *rNode) { + DataType returnTy = BuildTypes::undefinedType; + + if (isUndefined(lNode) || isUndefined(rNode)) { + n.setSemanticError(); + return returnTy; + } + + DataType lTy = lNode->getDataType(); + DataType rTy = rNode->getDataType(); + + // binary operations only between numeric types + bool lIsNumeric = buildTypes->isNumericDataType(lTy); + bool rIsNumeric = buildTypes->isNumericDataType(rTy); + if (!lIsNumeric || !rIsNumeric) { + yyerrorcpp("Non-numeric types are not supported by this operator.", &n); + return returnTy; + } + + if (buildTypes->isEnum(lTy)) + lTy = tint8; + if (buildTypes->isEnum(rTy)) + rTy = tint8; + + uint lBWidth = buildTypes->bitWidth(lTy); + uint rBWidth = buildTypes->bitWidth(rTy); + + // special cases for BinaryOp (left and right shift, or and and) + if (BinaryOp *bop = dynamic_cast(&n)) { + bool rIsSigned = buildTypes->isSignedDataType(rTy); + bool lIsSigned = buildTypes->isSignedDataType(lTy); + + if (bop->getOperator() == TOK_LSHIFT || bop->getOperator() == TOK_RSHIFT) { + // special case for left and right shift, preserve the left side type + // TODO: C standard promotes left operand to int32 + if (rTy != lTy) + n.node_children[1] = new IntCast(rNode, rIsSigned, lTy); + return lTy; + + } else if (bop->getOperator() == TOK_OR || bop->getOperator() == TOK_AND) { + // special case for or and and: convert to bool (int1) + if (lTy != tbool) + n.node_children[0] = new IntCast(lNode, rIsSigned, tbool); + if (rTy != tbool) + n.node_children[1] = new IntCast(rNode, rIsSigned, tbool); + return tbool; + } + } + + // both sides integer + if (buildTypes->isIntegerDataType(lTy) && buildTypes->isIntegerDataType(rTy)) { + bool lUnsigned = buildTypes->isUnsignedDataType(lTy); + bool rUnsigned = buildTypes->isUnsignedDataType(rTy); + + // if we have signed and unsigned operands + if (lUnsigned ^ rUnsigned) { + + if ((lUnsigned && lBWidth >= rBWidth) || + (rUnsigned && rBWidth >= lBWidth)) { + // Unsigned has equal or greater width: promote signed to unsigned + returnTy = lUnsigned ? lTy : rTy; + + } else if (!lUnsigned && lBWidth > rBWidth) { + // l is signed, has greater width, can hold r: promote r to l + returnTy = lTy; + + } else if (!rUnsigned && rBWidth > lBWidth) { + // r is signed, has greater width, can hold l: promote l to r + returnTy = rTy; + + } else { + // fallback: l or r is signed and smaller than unsigned: convert the + // signed to unsigned version of the wider type + returnTy = lBWidth > rBWidth ? lTy : rTy; // wider + if (buildTypes->isSignedDataType(returnTy)) + returnTy = buildTypes->signedToUnsigned(returnTy); + } + + } else { + // same signedness, return wider + returnTy = lBWidth > rBWidth ? lTy : rTy; + } + + if (lTy != returnTy) + n.node_children[0] = new IntCast(lNode, !lUnsigned, returnTy); + + if (rTy != returnTy) + n.node_children[1] = new IntCast(rNode, !rUnsigned, returnTy); + + return returnTy; + } + + // both sides float point + if (buildTypes->isFloatDataType(lTy) && buildTypes->isFloatDataType(rTy)) { + + // if sizes are distinct, the smaller float is extended + if (lBWidth != rBWidth) { + Node *convert = lBWidth < rBWidth ? lNode : rNode; + DataType newTy = lBWidth < rBWidth ? rTy : lTy; + ExpandFloat *ef = new ExpandFloat(convert, newTy); + n.node_children[lBWidth < rBWidth ? 0 : 1] = ef; + return newTy; + } + } + + // one side float and other side int + bool lIsInteger = buildTypes->isIntegerDataType(lTy); + bool lIsFloat = buildTypes->isFloatDataType(lTy); + bool rIsInteger = buildTypes->isIntegerDataType(rTy); + bool rIsFloat = buildTypes->isFloatDataType(rTy); + if (lIsInteger && rIsFloat || lIsFloat && rIsInteger) { + Node *convert = lIsInteger ? new IntToFloat(lNode, rTy) : new IntToFloat(rNode, lTy); + n.node_children[lIsInteger ? 0 : 1] = convert; + DataType newTy = lIsInteger ? rTy : lTy; + return newTy; + } + + // Coerce between char and int8/uint8 + if ((lTy == tchar && rTy == tint8u) || (lTy == tint8u && rTy == tchar)) + return lTy; + + if (lTy == rTy) { + return lTy; + } + + yyerrorcpp(string_format("FIXME: the pair %s and %s needs a coercion.", + buildTypes->name(lTy), buildTypes->name(rTy)), &n); + assert(returnTy != BuildTypes::undefinedType); + return returnTy; +} + +Node* PropagateTypes::visit(BinaryOp& n) { + propagateChildren(n); + n.dt = coerceArithOrCmp(n, n.lhsn(), n.rhsn()); + return NULL; +} + +Node* PropagateTypes::visit(CmpOp& n) { + propagateChildren(n); + coerceArithOrCmp(n, n.lexpn(), n.rexpn()); + return NULL; +} + +Node* PropagateTypes::visit(FunctionImpl& n) { + currentFunctionDt = n.getDataType(); + propagateChildren(n); + currentFunctionDt = BuildTypes::undefinedType; + return NULL; +} + +Node* PropagateTypes::visit(Return& n) { + if (!n.value()){ + n.dt = tvoid; + if (currentFunctionDt != tvoid) + yyerrorcpp(string_format("Return must be %s.", buildTypes->name(currentFunctionDt)), &n); + return NULL; + } else { + propagateChildren(n); + DataType valueDt = n.value()->getDataType(); + if (currentFunctionDt != valueDt) { + Node *converted = coerceTo(n.node_children[0], currentFunctionDt); + if (converted) { + n.node_children[0] = converted; + n.dt = converted->dt; + } + } else { + if (buildTypes->isComplex(valueDt)) { + // defer the pointer before returning + n.node_children[0] = new DeferPointer(n.value()); + } + n.dt = valueDt; + } + } + return NULL; +} + +Node* PropagateTypes::visit(FunctionCall& fc) { + propagateChildren(fc); + + // if the function name is the name of a primitive or complex type, + // replace the function call node by a more specific one + DataType dt = buildTypes->getType(fc.getName()); + + // if the function name is a UserType, its DataType is not created yet. + // Thus, we call findSymbol and getDataType to create it + if (dt == BuildTypes::undefinedType) { + Identifier typeName(fc.getName(), fc.getLoc()); + Node *symbol = typeName.getSymbol(&fc, false); + if (dynamic_cast(symbol)) + dt = symbol->getDataType(); + } + + if (dt != BuildTypes::undefinedType) { + + // if dt is the name of a primitive type and the call has only one + // argument, replace the function call node to a Cast one + unsigned p = fc.getParameters().size(); + if (buildTypes->isPrimitiveType(dt) && p == 1) { + Node *param = fc.getParameters()[0]; + ForcedCast *cast = new ForcedCast(param, dt); + return cast; + } + + // if dt is the name of a complex type and the call has no argument, + // replace the function call node to a ConstructorCall one + if (buildTypes->isComplex(dt) && p == 0) { + ConstructorCall *constructor = new ConstructorCall(fc.getName(), fc.getLoc()); + constructor->setScope(fc.getScope()); + return constructor; + } + } + + // coerce call arguments + Identifier calledIdent(fc.getName(), fc.getLoc()); + Node *calledSymbol = calledIdent.getSymbol(&fc, false); + FunctionBase *calledFunc = dynamic_cast(calledSymbol); + if (calledFunc && calledFunc->getNumCodedParams() == fc.getParameters().size()) { + auto calledFuncParam = calledFunc->getParameters().getParameters().begin(); + auto passedParam = fc.getParameters().begin(); + while (passedParam != fc.getParameters().end()) { + DataType call_dt = (*passedParam)->getDataType(); + DataType def_dt = (*calledFuncParam)->getDataType(); + if (call_dt != def_dt) { + Node *newParam = coerceTo((*passedParam), def_dt); + *passedParam = newParam; + } + calledFuncParam++; + passedParam++; + } + } + + return NULL; +} + +Node* PropagateTypes::visit(Matrix& n) { + PropagateTypes::visit((Variable&)n); + + // visit elements to propagate their types + for(MatrixElement *me : n.getMatrixElements()) { + for(ArrayElement *k: me->array->getElements()) { + Node *aux = k->value->accept(*this); + if (aux) + k->value = aux; + } + } + + // find the matrix and elements type + n.dt = n.getDataType(); + DataType edt = n.getElementDataType(); + + // visit elements to sext or zext their values + for(MatrixElement *me : n.getMatrixElements()) { + for(ArrayElement *k: me->array->getElements()) { + k->value = coerceTo(k->value, edt); + } + } + + return NULL; +} + +Node* PropagateTypes::visit(Array& n) { + PropagateTypes::visit((Variable&)n); + + // visit elements to propagate their types + for(ArrayElement *ae : n.getElements()) { + Node *aux = ae->value->accept(*this); + if (aux) + ae->value = aux; + } + + // find the array and elements type + n.getDataType(); + DataType edt = n.getElementDataType(); + + // visit elements to sext or zext their values + for(ArrayElement *ae : n.getElements()) { + ae->value = coerceTo(ae->value, edt); + } + + return NULL; +} + +Node* PropagateTypes::visit(UpdateArray& n) { + propagateChildren(n); + // find the array type, based on elements + DataType edt = n.getElementDataType(); + + // visit expr to sext or zext their values + n.setExpr(coerceTo(n.getExpr(), edt)); + + return NULL; +} + +Node* PropagateTypes::visit(UserType& n) { + // Visit variables first, to propagate their types + for (auto it = n.node_children.begin(); it != n.node_children.end(); ++it) { + if (Variable *v = dynamic_cast(*it)) { + Node *replace = (*it)->accept(*this); + if (replace) { + *it = replace; + } + } + } + + Node *firstDecl = n.getScope()->findSymbol(n.getTypeName()); + DataType sameNameDt = buildTypes->getType(n.getTypeName()); + if (!n.getParent() && sameNameDt != BuildTypes::undefinedType && buildTypes->isDefined(sameNameDt)) { + yyerrorcpp(string_format("The name %s is already used to define a type.", n.getName().c_str()), &n); + if (firstDecl) + yywarncpp(string_format("The type %s was defined here.", n.getName().c_str()), firstDecl); + } + + n.createDataType(); + n.setThisArgToFunctions(); + propagateChildren(n); + return NULL; +} + +Node* PropagateTypes::visit(Enum& n) { + n.getDataType(); + //propagateChildren(n); + return NULL; +} + +Node* PropagateTypes::visit(Variable& n) { + + propagateChildren(n); + + bool checkCoercion = false; + DataType destDt = BuildTypes::undefinedType; + + // Verify if a complex identifier exists + Identifier& id = n.getIdent(); + if (id.isComplex()) { + if (!id.getSymbol(&n, true)) + return NULL; + } + + Node *firstDecl = n.getScope()->findSymbol(n.getName()); + if (firstDecl && firstDecl != &n) { + DataType ndt = n.getDataType(); + destDt = firstDecl->getDataType(); + if (ndt != BuildTypes::undefinedType && + destDt != BuildTypes::undefinedType && + ndt != destDt) { + // the var was first defined as destDt. + // try to coherce the right hand side to match it + checkCoercion = true; + } + } + + Node *expr = n.getExpr(); + if (expr && (n.getDataType() != expr->getDataType())) { + // the variable type is distinct from the right hand side + // this can occur when using types, e.g. usertype.x = newvalue; + destDt = n.getDataType(); + checkCoercion = true; + } else if (!expr) { + // for array and matrix, getExpr returns null + expr = &n; + } + + if (checkCoercion) { + Node *result = NULL; + result = coerceTo(expr, destDt); + if (result) + n.setExpr(result); + } + + return NULL; +} + +Node* PropagateTypes::visit(Scalar& n) { + + Node *result = visit((Variable&)n); + + // although this should be done on SymbolizeTree, + // some type propagation in the tree changes symbols + // for scalars (e.g. FunctionCall -> ConstructorCall) + auto& exprSymbols = n.getExpr()->getSymbols(); + if (exprSymbols.size() > 0) + n.symbols = exprSymbols; + return NULL; +} + +Node* PropagateTypes::visit(Load& n) { + // skip the :parent field. For nested user types, + // the parameter doesn't exists at this point + if (n.getName() == "_parent") + return NULL; + + // although this should be done on SymbolizeTree, + // some type propagation in the tree changes symbols + // for scalars (e.g. FunctionCall -> ConstructorCall) + visit((Node&)n); + Node *identSymbol = n.getIdentSymbol(false); + if (identSymbol) + n.symbols = identSymbol->getSymbols(); + return NULL; +} + +Node* PropagateTypes::visit(MemCopy& n) { + // although this should be done on SymbolizeTree, + // some type propagation in the tree changes symbols + // for scalars (e.g. FunctionCall -> ConstructorCall) + visit((Node&)n); + if (n.children().size() > 0) + n.symbols = n.children()[0]->getSymbols(); + return NULL; +} + +Node* PropagateTypes::visit(BitCast& n) { + propagateChildren(n); + DataType dt = n.getDataType(); + int returnBitwidth = buildTypes->bitWidth(dt); + DataType st = n.getSourceType(); + int sourceBitwidth = buildTypes->bitWidth(st); + + if (returnBitwidth != sourceBitwidth) { + yyerrorcpp(string_format("Can not bitcast from '%s' to '%s'.", + buildTypes->name(st), + buildTypes->name(dt)), &n); + } + + return NULL; +} diff --git a/src/semantic/PropagateTypes.h b/src/semantic/PropagateTypes.h new file mode 100644 index 0000000..9856122 --- /dev/null +++ b/src/semantic/PropagateTypes.h @@ -0,0 +1,241 @@ + +#pragma once + +#include "Node.h" +#include "UserType.h" +#include "Matrix.h" +#include "Array.h" +#include "UpdateArray.h" +#include "BinaryOp.h" +#include "CmpOp.h" +#include "Return.h" +#include "FunctionImpl.h" +#include "FunctionCall.h" +#include "Enum.h" +#include "Load.h" +#include "MemCopy.h" +#include "BitCast.h" +#include "semantic/Visitor.h" + +class CoercionBase: public Node { +protected: + Node *node; + +public: + CoercionBase(Node *n, DataType newDt): Node(n->getLoc()) { + node = n; + dt = newDt; + addChild(n); + setScope(n->getScope()); + n->setScope(this, true); + } + + virtual bool isConstExpr() override { + return node->isConstExpr(); + } +}; + +class ExpandFloat: public CoercionBase { +public: + ExpandFloat(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateFPExt(v, buildTypes->llvmType(dt), "fpext"); + } +}; + +class IntCast: public CoercionBase { +private: + bool isSigned; +public: + IntCast(Node *n, bool isSigned, DataType newDt): + CoercionBase(n, newDt), isSigned(isSigned) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateIntCast(v, buildTypes->llvmType(dt), isSigned, "intcast"); + } + + Node* accept(Visitor& v) override { + return v.visit(*this); + } +}; + +class SExtInt: public CoercionBase { +public: + SExtInt(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateSExt(v, buildTypes->llvmType(dt), "sext"); + } +}; + +class ZExtInt: public CoercionBase { +public: + ZExtInt(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + if (!v) { + yyerrorcpp("There is no value to cast from (zext) ", node); + return NULL; + } else { + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateZExt(v, buildTypes->llvmType(dt), "zext"); + } + } +}; + +class TruncInt: public CoercionBase { +public: + TruncInt(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateTrunc(v, buildTypes->llvmType(dt), "trunc"); + } +}; + +class ExtendFloat: public CoercionBase { +public: + ExtendFloat(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateFPExt(v, buildTypes->llvmType(dt), "fpext"); + } +}; + +class TruncFloat: public CoercionBase { +public: + TruncFloat(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateFPTrunc(v, buildTypes->llvmType(dt), "trunc"); + } +}; + +class FloatToInt: public CoercionBase { +public: + FloatToInt(Node *n, DataType newDt): + CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + if (buildTypes->isUnsignedDataType(dt)) + return Builder->CreateFPToUI(v, buildTypes->llvmType(dt), "fptoui"); + else + return Builder->CreateFPToSI(v, buildTypes->llvmType(dt), "fptosi"); + } +}; + +class IntToFloat: public CoercionBase { +public: + IntToFloat(Node *n, DataType newDt): + CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + if (buildTypes->isUnsignedDataType(node->getDataType())) + return Builder->CreateUIToFP(v, buildTypes->llvmType(dt), "uitofp"); + else + return Builder->CreateSIToFP(v, buildTypes->llvmType(dt), "sitofp"); + } +}; + +class DeferPointer: public CoercionBase { +public: + DeferPointer(Node *n): + CoercionBase(n, n->getDataType()) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateLoad(buildTypes->llvmType(dt), v, false, "deref"); + } +}; + +class ForcedCast: public CoercionBase { +public: + ForcedCast(Node *n, DataType newDt): CoercionBase(n, newDt) {} + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; +}; + +class PropagateTypes: public Visitor { +protected: + DataType currentFunctionDt = BuildTypes::undefinedType; + +public: + PropagateTypes() {} + + void propagateChildren(Node& n, std::function lambda = NULL); + + Node *getChild(Node& n, int i) { + return n.node_children[i]; + } + + static bool isUndefined(Node *n, bool checkDefined = true) { + DataType dt = n->getDataType(); + if (dt == BuildTypes::undefinedType || + checkDefined && !buildTypes->isDefined(dt)) { + string name = n->getName(); + if (name != "") + yyerrorcpp(string_format("The type of %s is undefined.", name.c_str()), n); + else + yyerrorcpp("The type of the expression is undefined.", n); + return true; + } + return false; + } + + static Node *coerceTo(Node *n, const DataType destTy, bool warns = true); + static Node *coerceToUserTypes(Node *n, const DataType destTy); + DataType coerceArithOrCmp(Node& n, Node *left, Node *right); + + virtual Node* visit(Node& n) override { + propagateChildren(n); + return NULL; + } + + virtual Node* visit(CmpOp& n) override; + virtual Node* visit(BinaryOp& n) override; + + virtual Node* visit(Variable& n) override; + virtual Node* visit(Scalar& n) override; + virtual Node* visit(Load& n) override; + virtual Node* visit(MemCopy& n) override; + + virtual Node* visit(Array& n) override; + virtual Node* visit(Matrix& n) override; + virtual Node* visit(UpdateArray& n) override; + + virtual Node* visit(UserType &n) override; + virtual Node* visit(Enum &n) override; + + virtual Node* visit(Return& n) override; + virtual Node* visit(FunctionImpl& n) override; + virtual Node* visit(FunctionCall& n) override; + + virtual Node* visit(BitCast& n) override; +}; diff --git a/src/semantic/RecursiveVisitor.cpp b/src/semantic/RecursiveVisitor.cpp new file mode 100644 index 0000000..4191475 --- /dev/null +++ b/src/semantic/RecursiveVisitor.cpp @@ -0,0 +1,14 @@ + +#include "RecursiveVisitor.h" + +Node* RecursiveVisitor::visit(Node& n) { + if (before(n)) { return NULL; } + + for (auto &c : n.children()) { + c->accept(*this); + } + + after(n); + return NULL; +} + diff --git a/src/semantic/RecursiveVisitor.h b/src/semantic/RecursiveVisitor.h new file mode 100644 index 0000000..c2df0ef --- /dev/null +++ b/src/semantic/RecursiveVisitor.h @@ -0,0 +1,10 @@ + +#pragma once + +#include "Node.h" +#include "Visitor.h" + +class RecursiveVisitor: public Visitor { +public: + Node* visit(Node& n) override; +}; diff --git a/src/Semantic.cpp b/src/semantic/Semantic.cpp similarity index 71% rename from src/Semantic.cpp rename to src/semantic/Semantic.cpp index f5254cc..8ff20dd 100644 --- a/src/Semantic.cpp +++ b/src/semantic/Semantic.cpp @@ -1,4 +1,4 @@ -#include "Header.h" +#include "Semantic.h" Value *Semantic::Verification() { return NULL; diff --git a/src/Semantic.h b/src/semantic/Semantic.h similarity index 54% rename from src/Semantic.h rename to src/semantic/Semantic.h index 6b51deb..38f6ee0 100644 --- a/src/Semantic.h +++ b/src/semantic/Semantic.h @@ -1,9 +1,10 @@ -#ifndef __SEMANTIC_H__ -#define __SEMANTIC_H__ + +#pragma once + +#include "HeaderExternals.h" class Semantic { public: static Value *Verification(); }; -#endif diff --git a/src/semantic/SymbolizeTree.h b/src/semantic/SymbolizeTree.h new file mode 100644 index 0000000..2dd0e7c --- /dev/null +++ b/src/semantic/SymbolizeTree.h @@ -0,0 +1,79 @@ + +#pragma once + +#include "Node.h" +#include "UserType.h" +#include "Matrix.h" +#include "Array.h" +#include "UpdateArray.h" +#include "FunctionImpl.h" +#include "Scalar.h" +#include "Enum.h" +#include "semantic/Visitor.h" + +class SymbolizeTree: public Visitor { +public: + SymbolizeTree() {} + + virtual Node* visit(Node& n) override { + for(auto* c : n.children()) { + c->setScope(&n); + if (c->hasName()) { + n.addSymbol(dynamic_cast(c)); + } + } + for(auto* c : n.children()) { + c->accept(*this); + } + return NULL; + } + + virtual Node* visit(Array& n) override { + for(auto* c : n.children()) { + if (c->hasName()) { + n.addSymbol(dynamic_cast(c)); + } + } + for(ArrayElement *e : n.getElements()) { + e->value->setScope(&n); + e->value->accept(*this); + } + return NULL; + } + + virtual Node* visit(Matrix& n) override { + for(auto* c : n.children()) { + if (c->hasName()) { + n.addSymbol(dynamic_cast(c)); + } + } + for(MatrixElement *i: n.getMatrixElements()) { + for(ArrayElement *e: i->array->getElements()) { + e->value->setScope(&n); + e->value->accept(*this); + } + } + return NULL; + } + + virtual Node* visit(UpdateArray& n) override { + for(auto* c : n.children()) { + c->accept(*this); + } + // for operation assignment (eg. +=, -=, etc.), the indexes + // are used twice, in the load and in the attribution. + // so we check if they already has a scope before setting + for(auto* c : n.children()) { + if (!c->getScope()) { + c->setScope(&n); + } + } + return NULL; + } + + virtual Node* visit(Enum &n) override { + visit((Node&)n); + n.getDataType(); + return NULL; + } +}; diff --git a/src/semantic/VirtualDispatchPasses.cpp b/src/semantic/VirtualDispatchPasses.cpp new file mode 100644 index 0000000..1a74b28 --- /dev/null +++ b/src/semantic/VirtualDispatchPasses.cpp @@ -0,0 +1,68 @@ + +#include "VirtualDispatchPasses.h" +#include "FunctionCall.h" +#include "Program.h" +#include "UserType.h" +#include "BackLLVM.h" + +void IdentifyVirtualDispatch::propagateChildren(Node& n) { + for (auto* child : n.children()) { + child->accept(*this); + } +} + +Node* IdentifyVirtualDispatch::visit(Node& n) { + propagateChildren(n); + return NULL; +} + +Node* IdentifyVirtualDispatch::visit(FunctionCall& n) { + auto& ident = n.getIdent(); + + if (ident.isComplex()) { + // get the symbol containing the function being called + Identifier stem = ident.getStem(); + Node *stemSymbol = stem.getSymbol(n.getScope()); + + // get the complete hierarquical name + if (UserType *owner = dynamic_cast(stemSymbol->getScope())) { + auto full_name = regex_replace(owner->getTypeName(), regex(":"), "."); + full_name.append("."); + full_name.append(stem.getFullName()); + stem.changeIdentifier(full_name); + } + + // identify if exists an injection for the symbol + auto ij = injections.find(stem.getFullName()); + Node *ijsymbol = NULL; + if (ij != injections.end()) + ijsymbol = Identifier(ij->first, program->getLoc()).getSymbol(program); + + if (ijsymbol == stemSymbol) { + // change the call to the injected symbol if singleton + if (ij->second->scope == bs_singleton) { + string new_call = ident.getFullName(); + string to_replace = ident.getStem().getFullName(); + new_call.replace(new_call.find(to_replace), to_replace.length(), ij->second->singletonName); + identifiedCalls.push_back(CompileTimeInject{&n, new_call}); + } + } else { + // if no injection exists with that name, or the names refer to distinct symbols, + // then there's a call to a method of an unbound interface + // PropagateTypes didn't run at this point, so don't call getDataType here + if (stemSymbol->dt != BuildTypes::undefinedType && + buildTypes->isInterface(stemSymbol->dt)) { + program->getDispatcher()->addIntfInvocation(stemSymbol->dt); + } + } + } + return NULL; +} + +void IdentifyVirtualDispatch::applyIdentifiedChanges() { + for(auto &ic : identifiedCalls) { + //errs() << "Call to " << ic.fc->getIdent().getFullName() << + // " converted to " << ic.new_call << "\n"; + ic.fc->changeIdentifier(ic.new_call); + } +} \ No newline at end of file diff --git a/src/semantic/VirtualDispatchPasses.h b/src/semantic/VirtualDispatchPasses.h new file mode 100644 index 0000000..09c7e1b --- /dev/null +++ b/src/semantic/VirtualDispatchPasses.h @@ -0,0 +1,19 @@ + +#pragma once +#include "Visitor.h" + +struct CompileTimeInject { + FunctionCall *fc; + string new_call; +}; + +class IdentifyVirtualDispatch: public Visitor { + protected: + vector identifiedCalls; + public: + IdentifyVirtualDispatch() {} + void propagateChildren(Node& n); + virtual Node* visit(Node& n) override; + virtual Node* visit(FunctionCall& n) override; + void applyIdentifiedChanges(); +}; diff --git a/src/semantic/Visitor.h b/src/semantic/Visitor.h new file mode 100644 index 0000000..519ec0f --- /dev/null +++ b/src/semantic/Visitor.h @@ -0,0 +1,96 @@ + +#pragma once + +#include "Node.h" + +class BinaryOp; +class CmpOp; +class Delay; +class Float; +class FunctionCall; +class ConstructorCall; +class FunctionDecl; +class FunctionImpl; +class FunctionBase; +class Matrix; +class If; +class InPort; +class Int16; +class Int32; +class Int64; +class Int8; +class Load; +class LoadArray; +class OutPort; +class Print; +class Program; +class Return; +class Scalar; +class StringConst; +class Array; +class UpdateArray; +class While; +class Loop; +class UserType; +class Variable; +class NamedConst; +class MemCopy; +class Enum; +class BitCast; +class CoercionBase; + +#define VISITOR_DECLAREP(T, P) \ + virtual Node *visit(T& n) { return visit((P&)n); } \ + virtual void after(T&) {} \ + virtual bool before(T&) { return false; } \ + virtual Node *needs_replace(T&) { return NULL; } + +#define VISITOR_DECLARE(T) \ + virtual Node *visit(T& n) { return visit((Node&)n); } \ + virtual void after(T&) {} \ + virtual bool before(T&) { return false; } + +class Visitor { +public: + virtual Node *visit(Node&) { return NULL; } + virtual void after(Node&) {} + virtual bool before(Node&) { return false; } + + VISITOR_DECLARE(NamedNode) + VISITOR_DECLARE(BinaryOp) + VISITOR_DECLARE(CmpOp) + VISITOR_DECLARE(Delay) + VISITOR_DECLARE(Float) + VISITOR_DECLARE(FunctionCall) + VISITOR_DECLARE(ConstructorCall) + VISITOR_DECLARE(If) + VISITOR_DECLARE(InPort) + VISITOR_DECLARE(Int16) + VISITOR_DECLARE(Int32) + VISITOR_DECLARE(Int8) + VISITOR_DECLARE(Load) + VISITOR_DECLARE(LoadArray) + VISITOR_DECLARE(OutPort) + VISITOR_DECLARE(Print) + VISITOR_DECLARE(Program) + VISITOR_DECLARE(Return) + VISITOR_DECLARE(StringConst) + VISITOR_DECLARE(While) + VISITOR_DECLARE(Loop) + VISITOR_DECLAREP(Scalar, Variable) + VISITOR_DECLAREP(Variable, NamedNode) + VISITOR_DECLAREP(NamedConst, NamedNode) + VISITOR_DECLAREP(FunctionBase, NamedNode) + VISITOR_DECLAREP(FunctionDecl, FunctionBase) + VISITOR_DECLAREP(UserType, NamedNode) + VISITOR_DECLAREP(FunctionImpl, FunctionBase) + VISITOR_DECLAREP(Array, Variable) + VISITOR_DECLAREP(Matrix, Variable) + VISITOR_DECLARE(MemCopy) + VISITOR_DECLARE(Enum) + VISITOR_DECLARE(UpdateArray) + VISITOR_DECLARE(BitCast) + VISITOR_DECLARE(CoercionBase) + +}; + diff --git a/test/Exemplo_C.c b/test/Exemplo_C.c deleted file mode 100644 index ea63eaa..0000000 --- a/test/Exemplo_C.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -int main(){ - int a[150], i; - for (i = 0; i < 150; i++){ - a[i] = 0; - } -} diff --git a/test/Falhando.txt b/test/Falhando.txt deleted file mode 100644 index 0561a43..0000000 --- a/test/Falhando.txt +++ /dev/null @@ -1,11 +0,0 @@ -int func (bool a){ - if (a == true){ - print 1; - } - else { - print 2; - } - return 0; -} - -b = func(true); diff --git a/test/Falhando2.txt b/test/Falhando2.txt deleted file mode 100644 index 8db9f23..0000000 --- a/test/Falhando2.txt +++ /dev/null @@ -1,12 +0,0 @@ -int func (){ - a = true; - if (a == true){ - print 1; - } - else { - print 2; - } - return 0; -} - -b = func(); diff --git a/test/Fibonacci.c b/test/Fibonacci.c deleted file mode 100644 index 5df5e16..0000000 --- a/test/Fibonacci.c +++ /dev/null @@ -1,22 +0,0 @@ -#include - -int fibonacci (int n){ - if (n == 1) - return 1; - else - if (n == 2) - return 1; - else - { - return fibonacci(n - 1) + fibonacci(n - 2); - } - return 1; -} - -void main (){ - printf ("%d\n",fibonacci(1)); - printf ("%d\n",fibonacci(2)); - printf ("%d\n",fibonacci(3)); - printf ("%d\n",fibonacci(4)); - printf ("%d\n",fibonacci(5)); -} diff --git a/test/Fibonacci.txt b/test/Fibonacci.txt deleted file mode 100644 index c6c4cc5..0000000 --- a/test/Fibonacci.txt +++ /dev/null @@ -1,18 +0,0 @@ -int fibonacci (int n){ - if (n == 1) - return 1; - else - if (n == 2) - return 1; - else - { - return fibonacci(n - 1) + fibonacci(n - 2); - } - return 1; -} - -print (fibonacci(1)); -print (fibonacci(2)); -print (fibonacci(3)); -print (fibonacci(4)); -print (fibonacci(5)); diff --git a/test/Float_Vector.txt b/test/Float_Vector.txt deleted file mode 100644 index 2ab385d..0000000 --- a/test/Float_Vector.txt +++ /dev/null @@ -1,7 +0,0 @@ -vector = {3, 2, 5, 2, 1, 4.2, 5, 6, 8, 2, 1}; - -i = 0; -while (i < 10){ - print vector[i]; - i = i + 1; -} diff --git a/test/Float_Vector_R.txt b/test/Float_Vector_R.txt deleted file mode 100644 index 2634682..0000000 --- a/test/Float_Vector_R.txt +++ /dev/null @@ -1,7 +0,0 @@ -vector = {3:3, 4.2}; - -i = 0; -while (i < 4){ - print vector[i]; - i = i + 1; -} diff --git a/test/Funcionando.txt b/test/Funcionando.txt deleted file mode 100644 index 579dd8e..0000000 --- a/test/Funcionando.txt +++ /dev/null @@ -1,7 +0,0 @@ -a = true; - if (a == true){ - print 1; - } - else { - print 2; - } diff --git a/test/Int_Function.txt b/test/Int_Function.txt deleted file mode 100644 index 4fb19ee..0000000 --- a/test/Int_Function.txt +++ /dev/null @@ -1,5 +0,0 @@ -int quadrado(int a){ - return a * a; -} - -print quadrado(3); diff --git a/test/Int_Vector.txt b/test/Int_Vector.txt deleted file mode 100644 index d46d6fe..0000000 --- a/test/Int_Vector.txt +++ /dev/null @@ -1,7 +0,0 @@ -vector = {3, 2, 5, 2, 1, 4, 5, 6, 8, 2, 1}; - -i = 0; -while (i < 10){ - print vector[i]; - i = i + 1; -} diff --git a/test/Int_Vector_R.txt b/test/Int_Vector_R.txt deleted file mode 100644 index 7f765d9..0000000 --- a/test/Int_Vector_R.txt +++ /dev/null @@ -1,7 +0,0 @@ -vector = {3:3, 2:3, 1:3, 2}; - -i = 0; -while (i < 10){ - print vector[i]; - i = i + 1; -} diff --git a/test/Makefile b/test/Makefile deleted file mode 100644 index 07f0b0c..0000000 --- a/test/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) -ALLOBJS=$(patsubst %.ll,%.o,${ALL_LL}) -ALLASM=$(patsubst %.ll,%.s,${ALL_LL}) -ALLBIN=$(patsubst %.ll,%,${ALL_LL}) - -COMPILER_NAME=../robcmp - -all: ${ALL_LL} ${ALLASM} ${ALLOBJS} ${ALLBIN} - -clean: - rm -f ${ALLBIN} ${ALLASM} ${ALLOBJS} ${ALL_LL} - -out/%.ll : %.rob ${COMPILER_NAME} - ${COMPILER_NAME} -Os $< > $@ - -%.o : %.ll - llc $< -o $@ -filetype=obj - -%.s : %.ll - llc $< -o $@ -filetype=asm - -core.o : debug.c - clang debug.c -o core.o -c - -% : %.s core.o - clang core.o $< -o $@ -lncurses - diff --git a/test/NewNew.txt b/test/NewNew.txt deleted file mode 100644 index 364429b..0000000 --- a/test/NewNew.txt +++ /dev/null @@ -1,2 +0,0 @@ -var = 3; -print (var); diff --git a/test/NewSort.txt b/test/NewSort.txt deleted file mode 100644 index b56078c..0000000 --- a/test/NewSort.txt +++ /dev/null @@ -1,20 +0,0 @@ -a = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; -int Sort(int n){ - - return 0; -} - -Sort(16); -i = 0; -while (i < 16){ - c = a[i]; - print c; - i++; -} - -Sort(16); -i = 0; -while (i < 16){ - print c; - i++; -} diff --git a/test/New_Teste.txt b/test/New_Teste.txt deleted file mode 100644 index 2252290..0000000 --- a/test/New_Teste.txt +++ /dev/null @@ -1,18 +0,0 @@ -int function_name (int b){ - if (b >= 3) - print (b * 2); - else{ - print 1; - } - return b + 1; -} - -c = {3:5, 24:3}; -a = function_name(3); -print (a); - -i = 0; -while (i < 8){ - print (c[i]); - i = i+1; -} diff --git a/test/Remember b/test/Remember deleted file mode 100644 index c66600a..0000000 --- a/test/Remember +++ /dev/null @@ -1 +0,0 @@ -gcc -O2 debug.o nome.c -o exec -lncurses diff --git a/test/Sort.c b/test/Sort.c deleted file mode 100644 index dc1ace8..0000000 --- a/test/Sort.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -void sort (int a[], int n) -{ - int i, j, temp; - for ( i = 0; i < n - 1; ++i ) - for ( j = i + 1; j < n; ++j ) - if ( a[i] > a[j] ) { - temp = a[i]; - a[i] = a[j]; - a[j] = temp; - } -} - -int main (void) -{ - int i; - int array[16] = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; - void sort (int a[], int n); - for ( i = 0; i < 16; ++i ) - printf ("%i ", array[i]); - sort (array, 16); - for ( i = 0; i < 16; ++i ) - printf ("%i ", array[i]); - return 0; -} diff --git a/test/Sort.txt b/test/Sort.txt deleted file mode 100644 index b63f768..0000000 --- a/test/Sort.txt +++ /dev/null @@ -1,38 +0,0 @@ -a = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; -int sort (int n) -{ - t = 0; - s = 0; - temp = 0; - while (t < n - 1) - { - s = t + 1; - while (s < n) - { - if ( a[t] > a[s] ) { - temp = a[t]; - a[t] = a[s]; - a[s] = temp; - } - s++; - } - t++; - //print t; - } - return 0; -} - - -i = 0; -while (i < 16){ - print a[i]; - i++; -} -print "\n"; - -sort (16); -i = 0; -while(i < 16){ - print a[i]; - i++; -} diff --git a/test/Var_Vector_R.txt b/test/Var_Vector_R.txt deleted file mode 100644 index 83a074a..0000000 --- a/test/Var_Vector_R.txt +++ /dev/null @@ -1,8 +0,0 @@ -b = 3; -a = {b:4, 2}; - -i = 0; -while (i < 5){ - print (a[i]); - i = i + 1; -} diff --git a/test/abc.txt b/test/abc.txt deleted file mode 100644 index ad1274f..0000000 --- a/test/abc.txt +++ /dev/null @@ -1,7 +0,0 @@ -int b (){ - t = 0; - print t; - return 0; -} - -b(); diff --git a/test/atmega1284p/Makefile b/test/atmega1284p/Makefile new file mode 100644 index 0000000..787aa4b --- /dev/null +++ b/test/atmega1284p/Makefile @@ -0,0 +1,52 @@ +ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) +ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/atmega1284p.o + +ROBCMP=../../build/robcmp +INCLUDES=-I ../../lib + +ifndef OPT +#OPT=-g -O0 +OPT=-Oz +endif + +LD_FLAGS=-nostdlib -entry=main -L../../lib -Tatmega1284p.ld ../../lib/avr51.o +LD_FLAGS+=-Bstatic +LD_FLAGS+=--gc-sections +LD_FLAGS+=--lto=thin + +DEPENDS=${ROBCMP} Makefile +LINK_DEPENDS=out/atmega1284p.o + +all: out test + +out: + mkdir -p out + +out/atmega1284p.o : ../../lib/atmega1284p.rob ${DEPENDS} + ${ROBCMP} -a atmega1284p ${OPT} -o $@ $< + +out/atmega1284p.ll : ../../lib/atmega1284p.rob ${DEPENDS} + ${ROBCMP} -a atmega1284p ${OPT} $< > $@ + +.SECONDARY: +out/%.o : %.rob out/atmega1284p.o ${DEPENDS} + ${ROBCMP} -bdep -a atmega1284p ${OPT} ${INCLUDES} -o $@ $< + +out/%.ll : %.rob ${DEPENDS} + ${ROBCMP} -bdep -a atmega1284p ${OPT} ${INCLUDES} $< > $@ + +%.tt : %.rob ${DEPENDS} + @-./runtest.sh $< $(patsubst %.rob,out/%,$<) + +out/% : out/%.o ${LINK_DEPENDS} + # exchange here if ld.lld show relocation errors + ld.lld ${LD_FLAGS} $^ -o $@ + #avr-ld ${LD_FLAGS} $^ -o $@ + +test: ${ALL_TT} + +clean: + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} + diff --git a/test/atmega1284p/bitstruct-field-i5.rob b/test/atmega1284p/bitstruct-field-i5.rob new file mode 120000 index 0000000..8246bd7 --- /dev/null +++ b/test/atmega1284p/bitstruct-field-i5.rob @@ -0,0 +1 @@ +../atmega328p/bitstruct-field-i5.rob \ No newline at end of file diff --git a/test/atmega1284p/bsscheck.rob b/test/atmega1284p/bsscheck.rob new file mode 120000 index 0000000..3fe20d6 --- /dev/null +++ b/test/atmega1284p/bsscheck.rob @@ -0,0 +1 @@ +../atmega328p/bsscheck.rob \ No newline at end of file diff --git a/test/atmega1284p/bssinjcheck.rob b/test/atmega1284p/bssinjcheck.rob new file mode 120000 index 0000000..18ae991 --- /dev/null +++ b/test/atmega1284p/bssinjcheck.rob @@ -0,0 +1 @@ +../atmega328p/bssinjcheck.rob \ No newline at end of file diff --git a/test/atmega1284p/datacheck.rob b/test/atmega1284p/datacheck.rob new file mode 120000 index 0000000..016886b --- /dev/null +++ b/test/atmega1284p/datacheck.rob @@ -0,0 +1 @@ +../atmega328p/datacheck.rob \ No newline at end of file diff --git a/test/atmega1284p/float.rob b/test/atmega1284p/float.rob new file mode 120000 index 0000000..ba4a261 --- /dev/null +++ b/test/atmega1284p/float.rob @@ -0,0 +1 @@ +../atmega328p/float.rob \ No newline at end of file diff --git a/test/atmega1284p/globaldata.rob b/test/atmega1284p/globaldata.rob new file mode 120000 index 0000000..58624a6 --- /dev/null +++ b/test/atmega1284p/globaldata.rob @@ -0,0 +1 @@ +../atmega328p/globaldata.rob \ No newline at end of file diff --git a/test/atmega1284p/globals.rob b/test/atmega1284p/globals.rob new file mode 120000 index 0000000..fc74855 --- /dev/null +++ b/test/atmega1284p/globals.rob @@ -0,0 +1 @@ +../atmega328p/globals.rob \ No newline at end of file diff --git a/test/atmega1284p/itoa.rob b/test/atmega1284p/itoa.rob new file mode 120000 index 0000000..89cdfe3 --- /dev/null +++ b/test/atmega1284p/itoa.rob @@ -0,0 +1 @@ +../atmega328p/itoa.rob \ No newline at end of file diff --git a/test/atmega1284p/memcpycheck.rob b/test/atmega1284p/memcpycheck.rob new file mode 120000 index 0000000..4d0b1d5 --- /dev/null +++ b/test/atmega1284p/memcpycheck.rob @@ -0,0 +1 @@ +../atmega328p/memcpycheck.rob \ No newline at end of file diff --git a/test/atmega1284p/robcmp-simavr-debug b/test/atmega1284p/robcmp-simavr-debug new file mode 120000 index 0000000..c9994e3 --- /dev/null +++ b/test/atmega1284p/robcmp-simavr-debug @@ -0,0 +1 @@ +../../build/robcmp-simavr-debug \ No newline at end of file diff --git a/test/atmega1284p/runtest.sh b/test/atmega1284p/runtest.sh new file mode 120000 index 0000000..d72879e --- /dev/null +++ b/test/atmega1284p/runtest.sh @@ -0,0 +1 @@ +../atmega328p/runtest.sh \ No newline at end of file diff --git a/test/atmega1284p/runtrace.sh b/test/atmega1284p/runtrace.sh new file mode 120000 index 0000000..fc1aeb1 --- /dev/null +++ b/test/atmega1284p/runtrace.sh @@ -0,0 +1 @@ +../atmega328p/runtrace.sh \ No newline at end of file diff --git a/test/atmega1284p/uart.rob b/test/atmega1284p/uart.rob new file mode 120000 index 0000000..a97d855 --- /dev/null +++ b/test/atmega1284p/uart.rob @@ -0,0 +1 @@ +../atmega328p/uart.rob \ No newline at end of file diff --git a/test/atmega1284p/uartdata.rob b/test/atmega1284p/uartdata.rob new file mode 120000 index 0000000..60d70e6 --- /dev/null +++ b/test/atmega1284p/uartdata.rob @@ -0,0 +1 @@ +../atmega328p/uartdata.rob \ No newline at end of file diff --git a/test/atmega328p/Makefile b/test/atmega328p/Makefile new file mode 100644 index 0000000..0776f91 --- /dev/null +++ b/test/atmega328p/Makefile @@ -0,0 +1,52 @@ +ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) +ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/atmega328p.o + +ROBCMP=../../build/robcmp +INCLUDES=-I ../../lib + +ifndef OPT +#OPT=-g -O0 +OPT=-Oz +endif + +LD_FLAGS=-nostdlib -entry=main -L../../lib -Tatmega328p.ld ../../lib/avr5.o +LD_FLAGS+=-Bstatic +LD_FLAGS+=--gc-sections +LD_FLAGS+=--lto=thin + +DEPENDS=${ROBCMP} Makefile +LINK_DEPENDS=out/atmega328p.o + +all: out test + +out: + mkdir -p out + +out/atmega328p.o : ../../lib/atmega328p.rob ${DEPENDS} + ${ROBCMP} -a atmega328p ${OPT} -o $@ $< + +out/atmega328p.ll : ../../lib/atmega328p.rob ${DEPENDS} + ${ROBCMP} -a atmega328p ${OPT} $< > $@ + +.SECONDARY: +out/%.o : %.rob out/atmega328p.o ${DEPENDS} + ${ROBCMP} -bdep -a atmega328p ${OPT} ${INCLUDES} -o $@ $< + +out/%.ll : %.rob ${DEPENDS} + ${ROBCMP} -bdep -a atmega328p ${OPT} ${INCLUDES} $< > $@ + +%.tt : %.rob ${DEPENDS} + @-./runtest.sh $< $(patsubst %.rob,out/%,$<) + +out/% : out/%.o ${LINK_DEPENDS} + # exchange here if ld.lld show relocation errors + ld.lld ${LD_FLAGS} $^ -o $@ + #avr-ld ${LD_FLAGS} $^ -o $@ + +test: ${ALL_TT} + +clean: + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} + diff --git a/test/atmega328p/bitstruct-field-i5.rob b/test/atmega328p/bitstruct-field-i5.rob new file mode 100644 index 0000000..bf4e1d0 --- /dev/null +++ b/test/atmega328p/bitstruct-field-i5.rob @@ -0,0 +1,18 @@ +/* + * Tests I2C start condition + */ + +use arch.avr.avr5regs; + +int8 main() { + + TWCR = ETWCR.TWSTA | ETWCR.TWEN | ETWCR.TWINT; + while (TWCR & ETWCR.TWINT) == 0; + + if TWSR.TWS != (0x8 >> 3) { + return 1; + } + + return 0; +} + diff --git a/test/atmega328p/bsscheck.rob b/test/atmega328p/bsscheck.rob new file mode 100644 index 0000000..56f3e0f --- /dev/null +++ b/test/atmega328p/bsscheck.rob @@ -0,0 +1,32 @@ + +/* This test case allocates a zeroed matrix in .bss region. + It tests if the assembly func __do_clear_bss, called + before main, is working properly. + */ + +random_seed16 = 0xE7A8; +matrix = {{0u:128}:8}; + +uint16 check_random(uint8 row) { + random_seed16 += row; + return random_seed16; +} + +int8 main() { + row = 0u; + while row < matrix.rows { + col = 0u; + while col < matrix.cols { + if matrix[row][col] != 0 { + return 1; + } + col++; + } + row++; + } + if check_random(row) != 0xE7A8 + 8 { + return 2; + } + return 0; +} + diff --git a/test/atmega328p/bssinjcheck.rob b/test/atmega328p/bssinjcheck.rob new file mode 100644 index 0000000..121f40e --- /dev/null +++ b/test/atmega328p/bssinjcheck.rob @@ -0,0 +1,39 @@ + +/* This test case allocates a type, with a matrix + inside it, in the .bss region. + */ + +interface intf { + uint8 get(uint8 row, uint8 col); + uint8 rows(); + uint8 cols(); +} + +type container implements intf { + buff = {{0u:128}:8}; + uint8 get(uint8 row, uint8 col) { + return buff[row][col]; + } + uint8 rows() { return buff.rows; } + uint8 cols() { return buff.cols; } +} + +c = intf(); +bind container to c singleton; + +int8 main() { + row = 0u; + while row < c.rows() { + col = 0u; + while col < c.cols() { + v = c.get(row, col); + if v != 0 { + return 1; + } + col++; + } + row++; + } + return 0; +} + diff --git a/test/atmega328p/datacheck.rob b/test/atmega328p/datacheck.rob new file mode 100644 index 0000000..cb74e1b --- /dev/null +++ b/test/atmega328p/datacheck.rob @@ -0,0 +1,20 @@ + +/* This test case allocates a variable in data region. + It tests if the assembly func __do_data_copy, called + before main, is working properly. + */ + +random_seed16 = 0xE7A8; + +uint16 check_random() { + random_seed16 += 1; + return random_seed16; +} + +int8 main() { + if check_random() != 0xE7A9 { + return 2; + } + return 0; +} + diff --git a/test/atmega328p/float.rob b/test/atmega328p/float.rob new file mode 100644 index 0000000..9516bd2 --- /dev/null +++ b/test/atmega328p/float.rob @@ -0,0 +1,88 @@ + +/* Test case to check float support on atmega328p */ + +use math.float; + +a = 1.2; +b = 1.1; + +float sum() { + c = a + b; + return c; +} + +float sub() { + c = a - b; + return c; +} + +float mult() { + c = a * b; + return c; +} + +float div() { + c = a / b; + return c; +} + +int64 floattoi64(float x) { + return int64(x); +} + +int32 floattoi32(float x) { + return int32(x); +} + +const epsilon = 0.000001; + +int8 main() { + r = sum(); + if r - 2.3 >= epsilon { + return 1; + } + + r = sub(); + if r - 0.1 >= epsilon { + return 2; + } + + r = mult(); + if r - 1.32 >= epsilon { + return 3; + } + + r = div(); + if r - 1.090909 >= epsilon { + return 4; + } + + r = NAN; + if !isnan(r) { + return 5; + } + + r = INFINITY; + if !isinf(r) { + return 6; + } + + r = -INFINITY; + if !isinf(r) { + return 7; + } + + r = div(); + s = floattoi64(r); + if s != 1 { + return 8; + } + + t = floattoi32(r); + if t != 1 { + return 9; + } + + return 0; +} + diff --git a/test/atmega328p/globaldata.rob b/test/atmega328p/globaldata.rob new file mode 100644 index 0000000..279deb5 --- /dev/null +++ b/test/atmega328p/globaldata.rob @@ -0,0 +1,12 @@ + +random_seed16 = 0xE7A8; + +int8 main() { + + if random_seed16 == 0xE7A8 { + return 0; + } else { + return 1; + } +} + diff --git a/test/atmega328p/globals.rob b/test/atmega328p/globals.rob new file mode 100644 index 0000000..77eed1e --- /dev/null +++ b/test/atmega328p/globals.rob @@ -0,0 +1,17 @@ + +boolean = true; + +vint8 = int8(0); +vint16 = int16(30); +vint32 = int32(16000000); + +int16 main() { + ret = int16(1); + if boolean { + if vint8 + vint16 + vint32 == 16000030 { + ret = 0; + } + } + return ret; +} + diff --git a/test/atmega328p/inline_asm.rob b/test/atmega328p/inline_asm.rob new file mode 100644 index 0000000..bb1a1fb --- /dev/null +++ b/test/atmega328p/inline_asm.rob @@ -0,0 +1,77 @@ + +/* AVR inline assembly constraints +Obtained from https://github.com/avr-llvm/architecture/blob/master/Instructions/inline-assembly-constraints.md +Constraint | Used for | Range +---------- | --------------------------------------------------------------------------|---------------------- +a | Simple upper registers | r16 to r23 +b | Base pointer registers pairs | y, z +d | Upper register | r16 to r31 +e | Pointer register pairs | x, y, z +q | Stack pointer register | SPH:SPL +r | Any register | r0 to r31 +t | Temporary register | r0 +w | Special upper register pairs | r24, r26, r28, r30 +x | Pointer register pair X | x (r27:r26) +y | Pointer register pair Y | y (r29:r28) +z | Pointer register pair Z | z (r31:r30) +G | Floating point constant | 0.0 +I | 6-bit positive integer constant | 0 to 63 +J | 6-bit negative integer constant | -63 to 0 +K | Integer constant | 2 +L | Integer constant | 0 +l | Lower registers | r0 to r15 +M | 8-bit integer constant | 0 to 255 +N | Integer constant | -1 +O | Integer constant | 8, 16, 24 +P | Integer constant | 1 +Q | A memory address based on Y or Z pointer with displacement | +R | Integer constant | -6 to 5 +*/ + +void wait_asm_us2(uint16 count1, uint16 count2) noinline { + // wait 4 cycles per count + + // + 2 cycles in add/adc + // + 4 cycles moving r24:r25 to x and r22:r23 to z + asm "add r26, r30 + adc r27, r31 + 1: + sbiw $0, 1 + brne 1b" // a ret is appended here + : "x(count1),z(count2)"; +} + +void wait_asm_us(uint16 count) inline { + // wait 4 cycles per count + asm "1: + sbiw $0, 1 + brne 1b" // a ret is appended here + : "r(count)"; +} + +uint32 clock() { + return 16e6; +} + +void wait_us(uint16 us) { + count = uint16(clock() / 4e6) * us - 1; + wait_asm_us(count); +} + +int16 main() { + wait_us(10); + // return if non zero + asm "or r24, r25 + brne 1f"; + + // start with a dirty X + asm "ldi r26, 0x1 + ldi r27, 0x0"; + // X will decrease to zero + wait_asm_us2(1000, 2000); + // return X + asm "movw r24, X + 1: ret"; + + // unreachable code + return 0; +} diff --git a/test/atmega328p/itoa.rob b/test/atmega328p/itoa.rob new file mode 100644 index 0000000..4ea607a --- /dev/null +++ b/test/atmega328p/itoa.rob @@ -0,0 +1,83 @@ + +use arch.avr.avr5mcu; +use convert.itoa; + +numbers = {-32123, -15678, -4364, -501, -25, 0, 25, 512, 4364, 15678, 32767}; + +base10 = { + {'-', '3', '2', '1', '2', '3', 0}, + {'-', '1', '5', '6', '7', '8', 0}, + {'-', '4', '3', '6', '4', 0 , 0}, + {'-', '5', '0', '1', 0 , 0 , 0}, + {'-', '2', '5', 0 , 0 , 0 , 0}, + {'0', 0 , 0 , 0 , 0 , 0 , 0}, + {'2', '5', 0 , 0 , 0 , 0 , 0}, + {'5', '1', '2', 0 , 0 , 0 , 0}, + {'4', '3', '6', '4', 0 , 0 , 0}, + {'1', '5', '6', '7', '8', 0 , 0}, + {'3', '2', '7', '6', '7', 0 , 0} +}; + +base16 = { + {'-', '7', 'd', '7', 'b', 0}, + {'-', '3', 'd', '3', 'e', 0}, + {'-', '1', '1', '0', 'c', 0}, + {'-', '1', 'f', '5', 0 , 0}, + {'-', '1', '9', 0 , 0 , 0}, + {'0', 0 , 0 , 0 , 0 , 0}, + {'1', '9', 0 , 0 , 0 , 0}, + {'2', '0', '0', 0 , 0 , 0}, + {'1', '1', '0', 'c', 0 , 0}, + {'3', 'd', '3', 'e', 0 , 0}, + {'7', 'f', 'f', 'f', 0 , 0} +}; + +bool check(uint8 id, char[][] expected, char[] result) { + ret = true; + i = 0u; + while result[i] != 0 and ret { + if result[i] != expected[id][i] { + ret = false; + } + i++; + } + return ret; +} + +void print_result(databus s, char[] result) { + i = 0; + while result[i] != 0 { + s.write(result[i]); + i++; + } + s.write('\n'); +} + +int16 main() { + mmcu = avr5mcu(); + serial = mmcu.uart0; + serial.setup(9600); + + result = {'\0':18}; + ret = true; + i = 0u; + while i < numbers.size and ret { + itoa(numbers[i], 10, result); + ret = check(i, base10, result); + print_result(serial, result); + + if ret { + itoa(numbers[i], 16, result); + ret = check(i, base16, result); + print_result(serial, result); + } + i++; + } + + if ret { + return 0; + } else { + return 1; + } +} + diff --git a/test/atmega328p/memcpycheck.rob b/test/atmega328p/memcpycheck.rob new file mode 100644 index 0000000..6e96818 --- /dev/null +++ b/test/atmega328p/memcpycheck.rob @@ -0,0 +1,42 @@ + +/* This test case allocates a zeroed matrix in .data region. + It checks if the assembly memcpy __xxx___ is working. + */ + +type fillmemory { + a = {{2u:8}:8}; +} + +int8 main() { + x = fillmemory(); + matrix = {{1u:128}:8}; + ma2 = {{0u:32}:8}; + + row = 0u; + while row < matrix.rows { + col = 0u; + while col < matrix.cols { + if matrix[row][col] != 1u { + return 1; + } + col++; + } + row++; + } + + row2 = 0u; + while row2 < ma2.rows { + col2 = 0u; + while col2 < ma2.cols { + v = ma2[row2][col2]; + if v != 0 { + return 2; + } + col2++; + } + row2++; + } + + return 0; +} + diff --git a/test/atmega328p/robcmp-simavr-debug b/test/atmega328p/robcmp-simavr-debug new file mode 120000 index 0000000..d508ef4 --- /dev/null +++ b/test/atmega328p/robcmp-simavr-debug @@ -0,0 +1 @@ +../../platformio/toolchain-robcmp/bin/robcmp-simavr-debug \ No newline at end of file diff --git a/test/atmega328p/runtest.sh b/test/atmega328p/runtest.sh new file mode 100755 index 0000000..435d7c9 --- /dev/null +++ b/test/atmega328p/runtest.sh @@ -0,0 +1,25 @@ +#!/bin/bash +CMD="./robcmp-simavr-debug -c 16000000 -m atmega328p -f $2" + +GREEN="\033[0;32m" +RED="\033[0;31m" +NC="\033[0m" + +echo -n " $1 " +make -s $2 +if [ "$?" -eq 0 ]; then + if [ "$V" = "1" ]; then + ${CMD} + else + timeout 10s ${CMD} &> /dev/null + fi + STATUS=$? + if [ "${STATUS}" -eq 0 ]; then + echo -e \\r${GREEN}[PASS]\\t\\t${NC} + else + echo -e \\r${RED}[FAILED] ${STATUS}\\t${NC} + fi +else + echo -e \\r${RED}[BUILD FAILED]\\t${NC} +fi + diff --git a/test/atmega328p/runtrace.sh b/test/atmega328p/runtrace.sh new file mode 100755 index 0000000..6a76ccf --- /dev/null +++ b/test/atmega328p/runtrace.sh @@ -0,0 +1,2 @@ +#!/bin/bash +./run_avr -g 1234 -t -f 16000000 -m atmega328p -v -v -v $1 diff --git a/test/atmega328p/stepper_uln2003.rob b/test/atmega328p/stepper_uln2003.rob new file mode 100644 index 0000000..20790d7 --- /dev/null +++ b/test/atmega328p/stepper_uln2003.rob @@ -0,0 +1,18 @@ +use intfs.mcu; +use motor.stepper.uln2003; + +mmcu = mcu(); + +int16 main(){ + stepper_base = uln2003(); + + stepper_base.setup(stepper_mode.fullstep); + stepper_base.set_direction(stepper_direction.counterclockwise); + + loop{ + stepper_base.step(); + mmcu.wait_ms(2); + } + + return 0; +} diff --git a/test/atmega328p/stepper_uln2003.spec b/test/atmega328p/stepper_uln2003.spec new file mode 100644 index 0000000..842f07f --- /dev/null +++ b/test/atmega328p/stepper_uln2003.spec @@ -0,0 +1,9 @@ +use arch.avr.avr5mcu; + +bind avr5mcu to mmcu singleton; + +bind avr5mcu.b0 to uln2003.dp1 singleton; +bind avr5mcu.b1 to uln2003.dp2 singleton; +bind avr5mcu.b2 to uln2003.dp3 singleton; +bind avr5mcu.b3 to uln2003.dp4 singleton; + diff --git a/test/atmega328p/uart.rob b/test/atmega328p/uart.rob new file mode 100644 index 0000000..782b596 --- /dev/null +++ b/test/atmega328p/uart.rob @@ -0,0 +1,16 @@ + +use arch.avr.avr5mcu; + +int16 main() { + mmcu = avr5mcu(); + serial = mmcu.uart0; + serial.setup(9600); + + serial.write('A'); + serial.write('B'); + serial.write('C'); + serial.write('\n'); + + return 0; +} + diff --git a/test/atmega328p/uartdata.rob b/test/atmega328p/uartdata.rob new file mode 100644 index 0000000..8b0d314 --- /dev/null +++ b/test/atmega328p/uartdata.rob @@ -0,0 +1,33 @@ + +use arch.avr.avr5mcu; +use convert.itoa; + +random_seed16 = 0xE7A8; + +uint16 check_random() { + random_seed16 += 1; + return random_seed16; +} + +void print_result(databus s, char[] result) { + i = 0; + while result[i] != 0 { + s.write(result[i]); + i++; + } + s.write('\n'); +} + +int16 main() { + mmcu = avr5mcu(); + serial = mmcu.uart0; + serial.setup(9600); + + a = check_random(); + result = {'\0':18}; + itoa(a, 10, result); + print_result(serial, result); + + return 0; +} + diff --git a/test/bellmanford.c b/test/bellmanford.c deleted file mode 100644 index 45b8446..0000000 --- a/test/bellmanford.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include "debug.h" - -int INT_MAX = 9999; - -// edges (u,v,w) -int graph[8][3] = - {{0, 1, -1}, {0, 2, 4}, {1, 2, 3}, - {1, 3, 2}, {1, 4, 2}, {3, 2, 5}, - {3, 1, 1}, {4, 3, -3}}; - -void bellmanford(int V, int E, int src) { - // Initialize distance of all vertices as 0. - int dis[V]; - for(int v = 0; v < V; v++) - dis[v] = INT_MAX; - - // initialize distance of source as 0 - dis[src] = 0; - - /*Relax all edges |V| - 1 times. A simple - shortest path from src to any other - vertex can have at-most |V| - 1 edges*/ - for(int i = 0; i < (V-1); i++) { - for(int j = 0; j < E; j++) { - if(dis[graph[j][0]] + graph[j][2] < dis[graph[j][1]]) - dis[graph[j][1]] = dis[graph[j][0]] + graph[j][2]; - } - } - - /* check for negative-weight cycles. - The above step guarantees shortest - distances if graph doesn't contain - negative weight cycle. If we get a - shorter path, then there is a cycle. */ - for(int i = 0; i < E; i++) { - int x = graph[i][0]; - int y = graph[i][1]; - int weight = graph[i][2]; - if (dis[x] != INT_MAX && dis[x] + weight < dis[y]) - print(2, "Graph contains negative weight cycle\n"); - } - - print(2, "Vertex Distance from Source\n"); - for(int i = 0; i < V; i++) { - print(0, &i); - print(2, "\t"); - print(0, &dis[i]); - print(2, "\n"); - } -} - -int main() { - init(); - bellmanford(5, 8, 0); -} - - diff --git a/test/bellmanford.rob b/test/bellmanford.rob deleted file mode 100644 index 44d4467..0000000 --- a/test/bellmanford.rob +++ /dev/null @@ -1,63 +0,0 @@ - -INT_MAX = 9999; - -// edges (u,v,w) -graph = - {{0, 1, -1}, {0, 2, 4}, {1, 2, 3}, - {1, 3, 2}, {1, 4, 2}, {3, 2, 5}, - {3, 1, 1}, {4, 3, -3}}; - -int16 bellmanford(int16 V, int16 E, int16 src) { - // Initialize distance of all vertices as 0. - dis = {INT_MAX : 5}; - - // initialize distance of source as 0 - dis[src] = 0; - - /* Relax all edges |V| - 1 times. A simple - shortest path from src to any other - vertex can have at-most |V| - 1 edges */ - i = 0; - while(i < (V-1)) { - j = 0; - while(j < E) { - d = dis[graph[j][0]] + graph[j][2]; - if (d < dis[graph[j][1]]) - dis[graph[j][1]] = dis[graph[j][0]] + graph[j][2]; - j++; - } - i++; - } - - /* check for negative-weight cycles. - The above step guarantees shortest - distances if graph doesn't contain - negative weight cycle. If we get a - shorter path, then there is a cycle. */ - i = 0; - while(i < E) { - x = graph[i][0]; - y = graph[i][1]; - weight = graph[i][2]; - if (dis[x] != INT_MAX and dis[x] + weight < dis[y]) - print "Graph contains negative weight cycle\n"; - i++; - } - - print "Vertex Distance from Source\n"; - i = 0; - while (i < V) { - print i; - print dis[i]; - print "\n"; - i++; - } - - return 0; -} - -int16 main() { - bellmanford(5, 8, 0); - return 0; -} - diff --git a/test/debug.c b/test/debug.c deleted file mode 100644 index 3d73bcd..0000000 --- a/test/debug.c +++ /dev/null @@ -1,184 +0,0 @@ - -#include -#include -#include -#include - -void onexit(void) __attribute__ ((destructor)); - -#define ARDUINO_PORTS 14 -int arduino_out_ports[ARDUINO_PORTS]; -int steppers_pos[3] = {0}; - -#define LCD_ROWS 6 -#define LCD_COLS 80 -#define LCD_CHARS (LCD_ROWS*LCD_COLS) -char display[LCD_CHARS]; -int display_pos = 0; -char last_msg[1000]; - -char *port_names[ARDUINO_PORTS] = { - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "14", -}; - -void refresh_screen() { - - mvprintw(1, 1, "Simulador de E/S para Robcmp"); - mvprintw(2, 1, "----------------------------"); - - mvprintw(6, 1, "Ultima msg: "); - attron(COLOR_PAIR(3)); - mvprintw(6, 14, "%s ", last_msg); - attroff(COLOR_PAIR(3)); - - int currow = 10; - mvprintw(currow++, 1, "[ Mensagens print ]"); - mvprintw(currow++, 1, "---------------"); - attron(COLOR_PAIR(2)); - for(int r=0; r ARDUINO_PORTS) { - attron(COLOR_PAIR(3)); - sprintf(last_msg, "Erro: porta %d nao existe.", - port); - attroff(COLOR_PAIR(3)); - } else { - arduino_out_ports[port] = value; - } - - refresh_screen(); -} - -void delay(int milis) { - attron(COLOR_PAIR(3)); - sprintf(last_msg, "Delay %d milis", milis); - attroff(COLOR_PAIR(3)); - refresh_screen(); - - usleep(milis*1000); -} - -void stepper_goto(int stepper, int pos) { - attron(COLOR_PAIR(3)); - sprintf(last_msg, "Motor %d move para posicao %d.", stepper, pos); - attroff(COLOR_PAIR(3)); - refresh_screen(); - usleep(1e6); -} - -void servo_goto(int pos) { - attron(COLOR_PAIR(3)); - if (pos >= 0 && pos <= 30) { - sprintf(last_msg, "Servo move para posicao %d.", pos); - } else { - sprintf(last_msg, "Servo nao pode se mover para posicao %d (0-30).", pos); - } - attroff(COLOR_PAIR(3)); - refresh_screen(); - usleep(1e6); -} - -void onexit(void) { - getchar(); - curs_set(1); - clear(); - endwin(); -} - -/*int main() { - - int r = 10; - float d = 100.903; - - print(1, &d); - print(0, &r); -} -*/ diff --git a/test/debug.h b/test/debug.h deleted file mode 100644 index fdf8330..0000000 --- a/test/debug.h +++ /dev/null @@ -1,16 +0,0 @@ - -#include -#include -#include -#include - -void onexit(void) __attribute__ ((destructor)); -void refresh_screen(); -void init(); -void print(char t, void *data); -int analogRead(unsigned char t); -void analogWrite(char port, short value); -void delay(int milis); -void stepper_goto(int stepper, int pos); -void servo_goto(int pos); - diff --git a/test/debug/.gitignore b/test/debug/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/test/debug/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/test/debug/README b/test/debug/README new file mode 100644 index 0000000..3e5e354 --- /dev/null +++ b/test/debug/README @@ -0,0 +1,4 @@ +To debug a test, put a link to its .rob file here and open Visual Code. +Ex.: +$ ln -s ../../general/sort.rob +$ code . diff --git a/test/debug/platformio.ini b/test/debug/platformio.ini new file mode 100644 index 0000000..c0546d1 --- /dev/null +++ b/test/debug/platformio.ini @@ -0,0 +1,31 @@ + +[env] +platform = robcmp +board = atmega328p +upload_protocol = serial +upload_speed = 115200 + +[env:release] +build_type = release + +[env:debug] +build_type = debug +debug_tool = robcmp-ssd1306 + +[env:native] +board = native +build_type = debug +upload_protocol = none + +[stm32] +platform = robcmp +board = stm32f1 +upload_protocol = stlink +#board_hardware_spec = specs/stm32.spec + +[env:stm32-release] +extends = stm32 + +[env:stm32-debug] +extends = stm32 +build_type = debug \ No newline at end of file diff --git a/test/debug/src/.empty b/test/debug/src/.empty new file mode 100644 index 0000000..e69de29 diff --git a/test/debug/src/.gitignore b/test/debug/src/.gitignore new file mode 100644 index 0000000..0d1593f --- /dev/null +++ b/test/debug/src/.gitignore @@ -0,0 +1 @@ +*.rob diff --git a/test/general/Compare_Local_Global_00.rob b/test/general/Compare_Local_Global_00.rob new file mode 100644 index 0000000..06f237e --- /dev/null +++ b/test/general/Compare_Local_Global_00.rob @@ -0,0 +1,18 @@ + +vector = {7, 8, 9, 10}; + +int16 fa(int16 i) { + localvector = {7, 8, 9, 10}; + return localvector[i]; +} + +int16 main(){ + i = 0; + while i < 4 { + if vector[i] != fa(i) { + return 1; + } + i++; + } + return 0; +} diff --git a/test/general/Compare_Local_Global_01.rob b/test/general/Compare_Local_Global_01.rob new file mode 100644 index 0000000..9e4eb79 --- /dev/null +++ b/test/general/Compare_Local_Global_01.rob @@ -0,0 +1,24 @@ + +matriz = {{7, 8}, {9,10}}; + +int16 fa(int16 i, int16 j) { + localmatriz = {{7,8},{9,10}}; + return localmatriz[i][j]; +} + +int16 main() +{ + i = 0; + while i < 2 { + j = 0; + while j < 2 { + if matriz[i][j] != fa(i,j) { + return 1; + } + j++; + } + i++; + } + + return 0; +} diff --git a/test/general/Function_Call.rob b/test/general/Function_Call.rob new file mode 100644 index 0000000..c49bb08 --- /dev/null +++ b/test/general/Function_Call.rob @@ -0,0 +1,10 @@ + +int16 b() { + t = 0; + return t; +} + +int16 main() { + return b(); +} + diff --git a/test/general/Function_Call_00.rob b/test/general/Function_Call_00.rob new file mode 100644 index 0000000..f82820a --- /dev/null +++ b/test/general/Function_Call_00.rob @@ -0,0 +1,27 @@ + +int16 function_name (int16 b){ + if (b >= 3) { + return b * 2; + } else { + return 1; + } +} + +int16 main(){ + c = {3:5, 24:3}; + a = function_name(3); + if a != 6 { + return 1; + } + + i = 0; + while (i < 8){ + b = function_name(c[i]); + if b != c[i] * 2 { + return 1; + } + i = i+1; + } + + return 0; +} diff --git a/test/general/Function_Return.rob b/test/general/Function_Return.rob new file mode 100644 index 0000000..e38721c --- /dev/null +++ b/test/general/Function_Return.rob @@ -0,0 +1,21 @@ + +void fa(int16 a) { + a = a + 1; +} + +int16 fb(int16 b) { + b = b + 1; + if b == 2 { + return b; + } + return 0; +} + +int16 main(){ + fa(1); + if fb(2) == 0 { + return 0; + } else { + return 1; + } +} diff --git a/test/general/Function_w_Conditional.rob b/test/general/Function_w_Conditional.rob new file mode 100644 index 0000000..fe8081e --- /dev/null +++ b/test/general/Function_w_Conditional.rob @@ -0,0 +1,15 @@ +int16 func(){ + a = true; + if (a == true){ + return 1; + } + else { + return 2; + } + return 0; +} + +int16 main(){ + b = func(); + return 0; +} diff --git a/test/general/Function_w_Params_00.rob b/test/general/Function_w_Params_00.rob new file mode 100644 index 0000000..32889a1 --- /dev/null +++ b/test/general/Function_w_Params_00.rob @@ -0,0 +1,13 @@ + +int16 func (bool a){ + if a == true { + return 1; + } + else { + return 2; + } +} + +int16 main() { + return func(true) - 1; +} diff --git a/test/general/Function_w_Params_01.rob b/test/general/Function_w_Params_01.rob new file mode 100644 index 0000000..954dcb1 --- /dev/null +++ b/test/general/Function_w_Params_01.rob @@ -0,0 +1,11 @@ + +int16 quadrado(int16 a) { + return a * a; +} + +int16 main() { + if quadrado(3) == 9 { + return 0; + } + return 1; +} diff --git a/test/general/Main_w_Condition.rob b/test/general/Main_w_Condition.rob new file mode 100644 index 0000000..42bdc4a --- /dev/null +++ b/test/general/Main_w_Condition.rob @@ -0,0 +1,10 @@ + +int16 main(){ + a = true; + if (a == true){ + return 0; + } + else { + return 1; + } +} diff --git a/test/general/Makefile b/test/general/Makefile new file mode 100644 index 0000000..0c396a2 --- /dev/null +++ b/test/general/Makefile @@ -0,0 +1,52 @@ +ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) +ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) + +OS=$(shell uname -o) + +ifeq ($(OS), Msys) +ROBCMP=../../build/robcmp.exe +else +ROBCMP=../../build/robcmp +endif + +ifndef OPT +#OPT=-g -O0 +OPT=-Oz +endif + +all: out test + +out: + mkdir -p out + +clean: + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} + +.SECONDARY: +out/%.o : %.rob ${ROBCMP} Makefile + @touch temp.spec && truncate -s 0 temp.spec + @[ -f $(patsubst %.rob,%.spec,$<) ] && cp $(patsubst %.rob,%.spec,$<) temp.spec || true + ${ROBCMP} ${OPT} -I ../../lib -bdep -s temp.spec -o $@ $< + +out/%.ll : %.rob ${ROBCMP} Makefile + @touch temp.spec && truncate -s 0 temp.spec + @[ -f $(patsubst %.rob,%.spec,$<) ] && cp $(patsubst %.rob,%.spec,$<) temp.spec || true + ${ROBCMP} ${OPT} -I ../../lib -bdep -s temp.spec $< > $@ + +%.tt : %.rob + @-./runtest.sh $< $(patsubst %.rob,out/%,$<) + +% : %.o +ifeq ($(OS), Msys) + ${LD} -e __main $< -o $@ +else ifeq ($(OS), Darwin) + ${CC} -Wl,-dead_strip $< -o $@ +else + ${CC} -Wl,--gc-sections -no-pie $< -o $@ +endif + +test: ${ALL_TT} + + diff --git a/test/general/Operations.rob b/test/general/Operations.rob new file mode 100644 index 0000000..7b35e58 --- /dev/null +++ b/test/general/Operations.rob @@ -0,0 +1,19 @@ + +int16 main(){ + a = 1; + + b = (-1); + c = (-a); + d = (a-a); + e = (a-1); + f = (1 - -a); + + if (a != 1) { return 1; } + if (b != -1) { return 1; } + if (c != -1) { return 1; } + if (d != 0) { return 1; } + if (e != 0) { return 1; } + if (f != 2) { return 1; } + + return 0; +} diff --git a/test/general/Operations_00.rob b/test/general/Operations_00.rob new file mode 100644 index 0000000..2ded349 --- /dev/null +++ b/test/general/Operations_00.rob @@ -0,0 +1,11 @@ + +int16 main() { + i = 1.2; + i += 1; + i += 7; + i *= 2; + if i != 18.4 { + return 1; + } + return 0; +} diff --git a/test/general/Return_in_While.rob b/test/general/Return_in_While.rob new file mode 100644 index 0000000..b70c4d8 --- /dev/null +++ b/test/general/Return_in_While.rob @@ -0,0 +1,21 @@ +void fb(int16 a) { + b = a; + while b > 3 { + b = b - 1; + } +} + +double fa(int16 a) { + b = a; + while b > 3 { + b = b - 1; + return b; + } + return 0; +} + +int16 main () { + fa(10); + fb(10); + return 0; +} diff --git a/test/general/Vector_Float.rob b/test/general/Vector_Float.rob new file mode 100644 index 0000000..2283f3f --- /dev/null +++ b/test/general/Vector_Float.rob @@ -0,0 +1,15 @@ + +int16 main() { + vector = {3, 2, 5, 2, 1, 4.2, 5, 6, 8, 2, 1}; + check = {3.0, 2.0, 5.0, 2.0, 1.0, 4.2, 5.0, 6.0, 8.0, 2.0, 1.0}; + + i = 0; + while i < 10 { + if vector[i] != check[i] { + return 1; + } + i = i + 1; + } + + return 0; +} diff --git a/test/general/Vector_Float_R.rob b/test/general/Vector_Float_R.rob new file mode 100644 index 0000000..0a0ee0d --- /dev/null +++ b/test/general/Vector_Float_R.rob @@ -0,0 +1,18 @@ + +int16 main() { + vector = {3:3, 4.2}; + + i = 0; + while (i < 4){ + if i < 3 { + if vector[i] != 3 { + return 1; + } + } else if vector[i] != 4.2 { + return 1; + } + i = i + 1; + } + + return 0; +} diff --git a/test/general/Vector_Int.rob b/test/general/Vector_Int.rob new file mode 100644 index 0000000..568ce1d --- /dev/null +++ b/test/general/Vector_Int.rob @@ -0,0 +1,15 @@ + +int16 main(){ + vector = {3, 2, 5, 2, 1, 4, 5, 6, 8, 2, 1}; + check = {3.0, 2, 5, 2, 1, 4, 5, 6, 8, 2, 1}; + + i = 0; + while (i < 10){ + if vector[i] != check[i] { + return 1; + } + i = i + 1; + } + + return 0; +} diff --git a/test/general/Vector_Int_R.rob b/test/general/Vector_Int_R.rob new file mode 100644 index 0000000..0a22d09 --- /dev/null +++ b/test/general/Vector_Int_R.rob @@ -0,0 +1,15 @@ + +int16 main(){ + vector = {3:3, 2:3, 1:3, 2}; + check = {3, 3, 3, 2, 2, 2, 1, 1, 1, 2}; + + i = 0u; + while i < vector.size { + if vector[i] != check[i] { + return 1; + } + i = i + 1; + } + + return 0; +} diff --git a/test/general/Vector_Update.rob b/test/general/Vector_Update.rob new file mode 100644 index 0000000..d45f36f --- /dev/null +++ b/test/general/Vector_Update.rob @@ -0,0 +1,14 @@ + +int16 main(){ + a = {3, 3, 3, 3, 3}; + if a[2] != 3 { + return 1; + } + + a[2] = 1; + if a[2] != 1 { + return 1; + } + + return 0; +} diff --git a/test/general/abs.rob b/test/general/abs.rob new file mode 100644 index 0000000..1a08664 --- /dev/null +++ b/test/general/abs.rob @@ -0,0 +1,33 @@ + +int16 abs(int16 value) { + if value < 0 { + return - value; + } + return value; +} + +int16 abs_bit(int16 value) { + mask = value >> 15; + return (value + mask) ^ mask; +} + +int16 abs_bit2(int16 value) { + mask = value >> 15; + return (value ^ mask) - mask; +} + +int8 main() { + nvalue = -635; + pvalue = 635; + if pvalue != abs(nvalue) { + return 1; + } + if pvalue != abs_bit(nvalue) { + return 1; + } + if pvalue != abs_bit2(nvalue) { + return 1; + } + return 0; +} + diff --git a/test/general/atoi.rob b/test/general/atoi.rob new file mode 100644 index 0000000..4c2dbfd --- /dev/null +++ b/test/general/atoi.rob @@ -0,0 +1,53 @@ + +use convert.atoi; + +strings = { + {'-', '3', '2', '1', '2', '3', 0, 0, 0, 0}, + {'-', '1', '5', '6', '7', '8', 0, 0, 0, 0}, + {'-', '4', '3', '6', '4', 0 , 0, 0, 0, 0}, + {'-', '5', '0', '1', 0 , 0 , 0, 0, 0, 0}, + {'-', '2', '5', 0 , 0 , 0 , 0, 0, 0, 0}, + {'0', 0 , 0 , 0 , 0 , 0 , 0, 0, 0, 0}, + {'2', '5', 0 , 0 , 0 , 0 , 0, 0, 0, 0}, + {'5', '1', '2', 0 , 0 , 0 , 0, 0, 0, 0}, + {'4', '3', '6', '4', 0 , 0 , 0, 0, 0, 0}, + {'1', '5', '6', '7', '8', 0 , 0, 0, 0, 0}, + {'3', '2', '7', '6', '7', 0 , 0, 0, 0, 0} +}; + +results = {-32123, -15678, -4364, -501, -25, 0, 25, 512, 4364, 15678, 32767}; + +bool check(int16 result, int16 expected){ + if result == expected{ + return true; + } + return false; +} + +int16 main() { + ok = true; + + string = {'0':10}; + + i = 0; + while i < strings.rows and ok{ + j = 0; + while j < strings.cols{ + string[j] = strings[i][j]; + j++; + } + r = atoi(string, 10); + if !check(r, results[i]){ + ok = false; + } + i++; + } + + if ok{ + return 0; + } else { + return i; + } +} + + diff --git a/test/general/bellmanford.rob b/test/general/bellmanford.rob new file mode 100644 index 0000000..6162bb5 --- /dev/null +++ b/test/general/bellmanford.rob @@ -0,0 +1,80 @@ +/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */ + +const INT_MAX = 9999; + +// edges (u,v,w) +graph = + {{0, 1, -1}, {0, 2, 4}, {1, 2, 3}, + {1, 3, 2}, {1, 4, 2}, {3, 2, 5}, + {3, 1, 1}, {4, 3, -3}}; + +// expected distances +dise = {0, -1, 2, -2, 1}; + +// Initialize distance of all vertices. +dis = {INT_MAX : 5}; + +bool bellmanford(uint16 V, int16 src) { + + // Number of edges + E = graph.rows; + + // initialize distance of source as 0 + dis[src] = 0; + + /* Relax all edges |V| - 1 times. A simple + * shortest path from src to any other + * vertex can have at-most |V| - 1 edges + */ + i = 0u; + while(i < (V-1)) { + j = 0u; + while(j < E) { + x = graph[j][0]; + y = graph[j][1]; + weight = graph[j][2]; + if (dis[x] + weight < dis[y]) { + dis[y] = dis[x] + weight; + } + j++; + } + i++; + } + + /* check for negative-weight cycles. + * The above step guarantees shortest + * distances if graph doesn't contain + * negative weight cycle. If we get a + * shorter path, then there is a cycle. + */ + i = 0u; + while(i < E) { + x = graph[i][0]; + y = graph[i][1]; + weight = graph[i][2]; + if (dis[x] != INT_MAX and dis[x] + weight < dis[y]) { + //print "Graph contains negative weight cycle\n"; + return false; + } + i++; + } + + return true; +} + +int16 main() { + r = bellmanford(5, 0); + if r == false { + return 1; + } + + i = 0u; + while i < dis.size { + if dis[i] != dise[i] { + return 2; + } + i++; + } + return 0; +} + diff --git a/test/general/bind.rob b/test/general/bind.rob new file mode 100644 index 0000000..e0d377d --- /dev/null +++ b/test/general/bind.rob @@ -0,0 +1,30 @@ +interface port { + int8 get(); +} + +type b3 implements port { + int8 get() { + return 10; + } +} + +type display { + a = 10; + reset = port(); + + int8 get_reset() { + return reset.get(); + } + +} + +int16 main() { + d = display(); + + r = d.get_reset(); + if r == 10 { + return 0; + } else { + return 1; + } +} diff --git a/test/general/bind.spec b/test/general/bind.spec new file mode 100644 index 0000000..0e7d181 --- /dev/null +++ b/test/general/bind.spec @@ -0,0 +1,5 @@ + + +bind b3 to display.reset singleton; + + diff --git a/test/general/bitoper.rob b/test/general/bitoper.rob new file mode 100644 index 0000000..8f3eaf0 --- /dev/null +++ b/test/general/bitoper.rob @@ -0,0 +1,58 @@ + +/* this test case simulates a dot crossing + over a screen diagonally, from (0,0) to + (64,64) and next, from (64,0) to (128,64) + */ + +void set_pixel(int8[][] buffer, uint16 row, uint16 col) { + rowb = row/8; + if col < buffer.cols and rowb < buffer.rows { + v = buffer[rowb][col]; + buffer[rowb][col] = v | (1 << int8(row & 7)); + } +} + +void clear_pixel(int8[][] buffer, uint16 row, uint16 col) { + rowb = row/8; + if col < buffer.cols and rowb < buffer.rows { + v = buffer[rowb][col]; + buffer[rowb][col] = v & ~(1 << int8(row & 7)); + } +} + +int8 main() { + + /* the screen with 128 columns and 64 rows + (8 bits in each of the 8 bytes = 64) */ + buff = {{0:128}:8}; + + col = 0u; + row = 0u; + + loop { + + clear_pixel(buff, row, col); + + aux = buff[row/8][col]; + if aux != 0 { + return 1; // clear failed + } + + col++; + row++; + + if col == 128 and row == 64 { + return 0; + } + if row == 64 { + row = 0; + } + + set_pixel(buff, row, col); + + aux = buff[row/8][col]; + if aux == 0 { + return 2; // set failed + } + } +} diff --git a/test/general/bitstruct.rob b/test/general/bitstruct.rob new file mode 100644 index 0000000..254c96e --- /dev/null +++ b/test/general/bitstruct.rob @@ -0,0 +1,35 @@ + +type bitstruct { + a = false; + b = false; + c = false; + d = false; + e = false; + f = false; + g = false; + h = false; + i = false; + j = false; + k = true; +} + +void set_struct_kfield(bitstruct s) { + s.k = false; +} + +int16 main() { + x = bitstruct(); + x.a = true; + x.c = true; + x.e = true; + x.j = true; + + set_struct_kfield(x); + + if x.c and !x.k and x.j { + return 0; + } else { + return 1; + } +} + diff --git a/test/general/bool.rob b/test/general/bool.rob new file mode 100644 index 0000000..46b126e --- /dev/null +++ b/test/general/bool.rob @@ -0,0 +1,29 @@ + +void func(bool x) { +} + +int16 main() { + a = 1 > 7; + b = 2 <= 3; + c = true; + d = false; + e = a or b; + f = a and c; + g = a or b and c; + + h = {true:2}; + x = !h[0]; + func(x); + func(!h[0]); + h[0] = !h[0]; + + if !(2+1 == 3) or !(2+2 == 4) or d { + return 1; + } + + if a or !b or !c or d or !e or f or !g { + return 1; + } + + return 0; +} diff --git a/test/general/bool_scircuit.rob b/test/general/bool_scircuit.rob new file mode 100644 index 0000000..7f85f37 --- /dev/null +++ b/test/general/bool_scircuit.rob @@ -0,0 +1,19 @@ + +int16 main() { + i1 = int16(0x1FC2); + i2 = int32(7); + i3 = int8(0); + + ret = 0; + while ret > -29 { + i1 |= 0U != i3 or (i2 != 0) < i2; + ret--; + } + + if i1 == 0x1FC3 { + return 0; + } + + return i1; +} + diff --git a/test/general/bool_scircuit2.rob b/test/general/bool_scircuit2.rob new file mode 100644 index 0000000..5bdd4b7 --- /dev/null +++ b/test/general/bool_scircuit2.rob @@ -0,0 +1,30 @@ +uint64 safe_sub(uint64 a, uint64 b) { + return a - b; +} + +uint64 safe_add(uint64 a, uint64 b) { + return a + b; +} + +uint16 safe_rshift(uint16 a, uint16 b) { + return a << b; +} + +uint8 safe_div(uint8 a, uint8 b) { + return a/b; +} + +int16 main() { + l_10 = int64(0xD6C3F0BC5021C3A2); + l_11 = int8(1); + l_12 = int32(5); + l_12 = safe_sub( + safe_rshift( + safe_add( + (safe_div(l_10, l_10) != 0) or (0xECC2 != 0) | l_10 ^ l_10 != l_10 ^ l_11 <= 0xC7B7F609B2B534DE, + 0x885EA6EDAD94E8FE), + 5), + 0xCE4B0AD8EA5F34BD); + return l_12; +} + diff --git a/test/general/bsscheck.rob b/test/general/bsscheck.rob new file mode 120000 index 0000000..3fe20d6 --- /dev/null +++ b/test/general/bsscheck.rob @@ -0,0 +1 @@ +../atmega328p/bsscheck.rob \ No newline at end of file diff --git a/test/general/bssinjcheck.rob b/test/general/bssinjcheck.rob new file mode 120000 index 0000000..18ae991 --- /dev/null +++ b/test/general/bssinjcheck.rob @@ -0,0 +1 @@ +../atmega328p/bssinjcheck.rob \ No newline at end of file diff --git a/test/general/byref-array.rob b/test/general/byref-array.rob new file mode 100644 index 0000000..5c9d299 --- /dev/null +++ b/test/general/byref-array.rob @@ -0,0 +1,61 @@ + +int32 sum_array(int16[] a); + +int32 main() { + x = {int16(0), 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + // y is a reference to x + y = x; + i = 0u; + while i < y.size { + if y[i] != x[i] { + return 1; + } + i++; + } + + // w is a reference to y (same as x) + w = y; + i = 0u; + while i < w.size { + if w[i] != x[i] { + return 1; + } + i++; + } + + // z is a copy of y + z = copy(y); + i = 0u; + while i < z.size { + z[i] = z[i] + 1; + if z[i] != x[i] + 1 { + return int32(i); + } + i++; + } + + zt = sum_array(w); + if zt != 45 + 18 + 10 { + return zt; + } + + return 0; +} + +int32 pass_array_pointer(int16[] b) { + c = b; + d = copy(b); + result = c[9] + d[9] + int32(b.size); + return result; +} + +int32 sum_array(int16[] a) { + i = 0u; + result = int32(0); + while i < a.size { + result += a[i]; + i++; + } + return result + pass_array_pointer(a); +} diff --git a/test/general/byref-matrix.rob b/test/general/byref-matrix.rob new file mode 100644 index 0000000..7af9629 --- /dev/null +++ b/test/general/byref-matrix.rob @@ -0,0 +1,80 @@ + +int32 sum_matrix(int16[][] a); + +int32 main() { + // 3x3 matrix of one's + x = {{int16(1):3}:3}; + + // y is a reference to x + y = x; + + i = 0u; + while i < y.rows { + j = 0u; + while j < y.cols { + if y[i][j] != x[i][j] { + return 1; + } + j++; + } + i++; + } + + + // w is a reference to y (same as x) + w = y; + i = 0u; + while i < w.rows { + j = 0u; + while j < w.cols { + if w[i][j] != x[i][j] { + return 1; + } + j++; + } + i++; + } + + // z is a copy of y + z = copy(y); + i = 0u; + while i < z.rows { + j = 0u; + while j < z.cols { + z[i][j] = z[i][j] + 1; + if z[i][j] != x[i][j] + 1 { + return 1; + } + j++; + } + i++; + } + + zt = sum_matrix(w); + if zt != 9 + 2 + 6 { + return zt; + } + + return 0; +} + +int32 pass_matrix_pointer(int16[][] b) { + c = b; + d = copy(b); + result = c[1][2] + d[2][2] + int32(b.cols) + int32(b.rows); + return result; +} + +int32 sum_matrix(int16[][] a) { + i = 0u; + result = int32(0); + while i < a.rows { + j = 0u; + while j < a.cols { + result += a[i][j]; + j++; + } + i++; + } + return result + pass_matrix_pointer(a); +} diff --git a/test/general/byref-simple.rob b/test/general/byref-simple.rob new file mode 100644 index 0000000..708c169 --- /dev/null +++ b/test/general/byref-simple.rob @@ -0,0 +1,24 @@ + +mapping = { + 0x00E1, 0x00C1, + 0x00E9, 0x00C9 +}; + +type Integer { + codepoint = int32(0); +} + +void utf8_decode(Integer i) { + i.codepoint = 10; +} + +int8 main() { + cp = Integer(); + utf8_decode(cp); + if cp.codepoint != 10 { + return 1; + } + + return 0; +} + diff --git a/test/general/byref.rob b/test/general/byref.rob new file mode 100644 index 0000000..095aa0c --- /dev/null +++ b/test/general/byref.rob @@ -0,0 +1,36 @@ + +interface intf { + void print(int8 v); +} + +type sub_t { + y = 18; +} + +type main_t { + a = 0; + ss = sub_t(); + + void setSubt(sub_t v) { + ss = copy(v); + } + + ii implements intf { + void print(int8 v) {} + } +} + +int16 main() { + a = main_t(); + ss = a.ss; + + x = sub_t(); + x.y = 17; + a.setSubt(x); + + if ss.y == 17 { + return 0; + } + return 1; +} + diff --git a/test/general/cast.rob b/test/general/cast.rob new file mode 100644 index 0000000..53faeed --- /dev/null +++ b/test/general/cast.rob @@ -0,0 +1,9 @@ + +uint8 test() { + return uint8(130); +} + +int8 main() { + a = test(); + return a != 130U; +} \ No newline at end of file diff --git a/test/general/constant-fold.rob b/test/general/constant-fold.rob new file mode 100644 index 0000000..a082f26 --- /dev/null +++ b/test/general/constant-fold.rob @@ -0,0 +1,10 @@ + +a = (10 + 15 + 17.6) * 3; + +int8 main() { + if a == (10 + 15 + 17.6) * 3 { + return 0; + } else { + return 1; + } +} diff --git a/test/general/dispatch.rob b/test/general/dispatch.rob new file mode 100644 index 0000000..65d675d --- /dev/null +++ b/test/general/dispatch.rob @@ -0,0 +1,41 @@ + +interface animal { + int8 sound(); +} + +type cat implements animal { + int8 sound() { + return 0; + } +} + +type dog implements animal { + int8 sound() { + return 1; + } +} + +type bird implements animal { + int8 sound() { + return 2; + } +} + +int8 produce_sound(animal a) { + return a.sound(); +} + +int8 main() { + c = cat(); + d = dog(); + b = bird(); + cs = produce_sound(c); + ds = produce_sound(d); + bs = produce_sound(b); + if cs != 0 or ds != 1 or bs != 2 { + return 1; + } else { + return 0; + } +} + diff --git a/test/general/enum-hex.rob b/test/general/enum-hex.rob new file mode 100644 index 0000000..cd5c3ab --- /dev/null +++ b/test/general/enum-hex.rob @@ -0,0 +1,17 @@ +/* altough simple, this test can catch + bugs in the enum datatype creation, + when the values of enum items are + determined */ + +enum power { ON = 0xAF, SLEEP = 0 } + +int8 main() { + a = power.ON; + b = power.SLEEP; + if uint8(a) != 0xAF or uint8(b) != 0x0 { + return 1; + } else { + return 0; + } +} + diff --git a/test/general/enum-simple.rob b/test/general/enum-simple.rob new file mode 100644 index 0000000..001df15 --- /dev/null +++ b/test/general/enum-simple.rob @@ -0,0 +1,14 @@ + +enum Enum {A, B, C, D, E} + +int16 main() { + a = Enum.B; + b = Enum.C; + + if a == b or b == Enum.E { + return 1; + } else { + return 0; + } +} + diff --git a/test/general/enum-types.rob b/test/general/enum-types.rob new file mode 100644 index 0000000..a9ddd40 --- /dev/null +++ b/test/general/enum-types.rob @@ -0,0 +1,27 @@ + +enum Enum {A = 0x24, B = 10, C, D, E = 200} + +type withenum { + value = Enum.A; +} + +Enum func(Enum e) { + if e == Enum.A { + return Enum.B; + } else { + return Enum.E; + } +} + +int16 main() { + a = Enum.B; + b = func(a); + c = withenum(); + + if a == b or c.value == Enum.B { + return 1; + } else { + return 0; + } +} + diff --git a/test/general/fibonacci.rob b/test/general/fibonacci.rob new file mode 100644 index 0000000..f5d26da --- /dev/null +++ b/test/general/fibonacci.rob @@ -0,0 +1,32 @@ +/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */ + +int32 fibonacci (int32 n) { + if (n == 1 or n == 2) { + return 1; + } else { + return fibonacci(n - 1) + fibonacci(n - 2); + } +} + +int8 main() { + check = {1, 1, 2, 3, 5, 6765}; + + result = { + fibonacci(1), + fibonacci(2), + fibonacci(3), + fibonacci(4), + fibonacci(5), + fibonacci(20) + }; + + i = 0u; + while i < check.size { + if result[i] != check[i] { + return 1; + } + i++; + } + + return 0; +} diff --git a/test/general/float.rob b/test/general/float.rob new file mode 120000 index 0000000..ba4a261 --- /dev/null +++ b/test/general/float.rob @@ -0,0 +1 @@ +../atmega328p/float.rob \ No newline at end of file diff --git a/test/general/function_attribs.rob b/test/general/function_attribs.rob new file mode 100644 index 0000000..b662099 --- /dev/null +++ b/test/general/function_attribs.rob @@ -0,0 +1,9 @@ + +void func_attribs() inline, weak { +} + +int8 main() { + func_attribs(); + return 0; +} + diff --git a/test/general/global-pointer.rob b/test/general/global-pointer.rob new file mode 100644 index 0000000..38b0c38 --- /dev/null +++ b/test/general/global-pointer.rob @@ -0,0 +1,53 @@ + +/* + * Test case for global pointers to interfaces + */ + +use intfs.interrupt; + +myint = interrupt_i8(); + +value = 0xff; + +void call_handler() { + myint.handler(0); +} + +type custom_handler implements interrupt_i8 { + void handler(uint8 byte) { + value = byte; + } +} + +void set_interface(interrupt_i8 i) { + a = i; + myint = a; +} + +int8 main() { + ch = custom_handler(); + vo = void_interrupt_i8(); + + // direct set + a = ch; + myint = a; + call_handler(); + if value != 0 { + return 1; + } + + // direct set is working, restore + // defaults before the next test + value = 0xff; + myint = vo; + + // set through function call + set_interface(ch); + call_handler(); + if value != 0 { + return 2; + } + + return value; +} + diff --git a/test/general/global-string.rob b/test/general/global-string.rob new file mode 100644 index 0000000..9fd573d --- /dev/null +++ b/test/general/global-string.rob @@ -0,0 +1,19 @@ + +a = "-10"; + +bool test() { + return a[0] == '-'; +} + +bool test2(char[] b) { + return b[1] == '1'; +} + +int16 main() { + if a.size == 3 and test() and test2(a) and a[2] == '0' { + return 0; + } else { + return 1; + } +} + diff --git a/test/general/intfinternal.rob b/test/general/intfinternal.rob new file mode 100644 index 0000000..637050f --- /dev/null +++ b/test/general/intfinternal.rob @@ -0,0 +1,39 @@ + +interface bus { + void setup(int32 speed); + void write(int8 b); +} + +type mcu { + + spi implements bus { + speed = int32(0); + lastb = 0; + + void setup(int32 s) { + speed = s; + } + + void write(int8 b) { + lastb = b; + } + } +} + +int16 main() { + m = mcu(); + + if m.spi.speed != 0 or m.spi.lastb != 0 { + return 1; + } + + m.spi.setup(1000); + m.spi.write(8); + + if m.spi.speed != 1000 or m.spi.lastb != 8 { + return 1; + } + + return 0; +} + diff --git a/test/general/intfscope.rob b/test/general/intfscope.rob new file mode 100644 index 0000000..c01cf35 --- /dev/null +++ b/test/general/intfscope.rob @@ -0,0 +1,46 @@ + +interface intf { + int16 get(); + void set(int16 s); +} + +type somevar { + a = int16(0); + + pa implements intf { + b = int16(0); + int16 get() { return b; } + void set(int16 s) { b = s; } + } + + int16 internaltest() { + pa.set(22); + return pa.get(); + } + + void set(int16 v) { + a = v; + } + + int16 get() { + return a; + } +} + +int16 main() { + sv = somevar(); + + in = sv.internaltest(); + + sv.set(18); + sva = sv.get(); + + ex = 33; + + if (in == 22 and ex == 33 and sva == 18) { + return 0; + } else { + return 1; + } +} + diff --git a/test/general/itoa.rob b/test/general/itoa.rob new file mode 100644 index 0000000..6a53422 --- /dev/null +++ b/test/general/itoa.rob @@ -0,0 +1,64 @@ + +use convert.itoa; + +numbers = {-32123, -15678, -4364, -501, -25, 0, 25, 512, 4364, 15678, 32767}; + +base10 = { + {'-', '3', '2', '1', '2', '3', 0}, + {'-', '1', '5', '6', '7', '8', 0}, + {'-', '4', '3', '6', '4', 0 , 0}, + {'-', '5', '0', '1', 0 , 0 , 0}, + {'-', '2', '5', 0 , 0 , 0 , 0}, + {'0', 0 , 0 , 0 , 0 , 0 , 0}, + {'2', '5', 0 , 0 , 0 , 0 , 0}, + {'5', '1', '2', 0 , 0 , 0 , 0}, + {'4', '3', '6', '4', 0 , 0 , 0}, + {'1', '5', '6', '7', '8', 0 , 0}, + {'3', '2', '7', '6', '7', 0 , 0} +}; + +base16 = { + {'-', '7', 'd', '7', 'b', 0}, + {'-', '3', 'd', '3', 'e', 0}, + {'-', '1', '1', '0', 'c', 0}, + {'-', '1', 'f', '5', 0 , 0}, + {'-', '1', '9', 0 , 0 , 0}, + {'0', 0 , 0 , 0 , 0 , 0}, + {'1', '9', 0 , 0 , 0 , 0}, + {'2', '0', '0', 0 , 0 , 0}, + {'1', '1', '0', 'c', 0 , 0}, + {'3', 'd', '3', 'e', 0 , 0}, + {'7', 'f', 'f', 'f', 0 , 0} +}; + +bool check(uint8 id, char[][] expected, char[] result) { + ret = true; + i = 0u; + while result[i] != 0 and ret { + if result[i] != expected[id][i] { + ret = false; + } + i++; + } + return ret; +} + +int16 main() { + result = {'\0':18}; + ret = true; + i = 0u; + while i < numbers.size and ret { + itoa(numbers[i], 10, result); + ret = check(i, base10, result); + if ret { + itoa(numbers[i], 16, result); + ret = check(i, base16, result); + } + i++; + } + if ret { + return 0; + } else { + return 1; + } +} diff --git a/test/general/matrix-global.rob b/test/general/matrix-global.rob new file mode 100644 index 0000000..95096de --- /dev/null +++ b/test/general/matrix-global.rob @@ -0,0 +1,24 @@ + +a = {{3:3}, + {4, 5, 6}, + {7:2, 9}}; + +int16 main() { + b = 1*2; + c = a[2][1] + a[2][2] + a[b][b]; + d = {{int16(a[2][1]):3}, {1,2,3}}; + d[1][1] = 30000; + e = {{a[2][1]:3}, {1,2,3}}; + e[1][1] = 30; + + if d[0][0] != 7 or e[1][0] != 1 { + return 1; + } + + if d[1][1] != 30000 or e[1][1] != 30 { + return 1; + } + + return 0; +} + diff --git a/test/general/matrix_of_type.rob b/test/general/matrix_of_type.rob new file mode 100644 index 0000000..37f313e --- /dev/null +++ b/test/general/matrix_of_type.rob @@ -0,0 +1,83 @@ + +type element { + fa = int16(0); +} + +int16 check(element[][] x) { + values = {10, 20, 30, 40}; + i = 0; + v = 0; + while i < x.rows { + j = 0; + while j < x.cols { + xx = x[i][j]; + if xx.fa != values[v] { + return v+1; + } + v++; + j++; + } + i++; + } + return 0; +} + +int16 test_matrix_of_instances() { + x2 = element(); + x2.fa = 30; + + x3 = element(); + x3.fa = 40; + + x = {{element():2}, {copy(x2), copy(x3)}}; + + x0 = x[0][0]; + x0.fa = 10; + + x1 = x[0][1]; + x1.fa = 20; + + return check(x); +} + +int16 test_matrix_of_pointers() { + x0 = element(); + x1 = element(); + + x2 = element(); + x2.fa = 30; + + x3 = element(); + x3.fa = 50; + + // this will be a vector of references to element + x = {{x0, x1}, {x2, x3}}; + + x0 = x[0][0]; + x0.fa = 10; + + x1 = x[0][1]; + x1.fa = 20; + + // test update of an element + x3_copy = element(); + x3_copy.fa = 40; + x[1][1] = x3_copy; + + return check(x); +} + +int16 main() { + vi = test_matrix_of_instances(); + if vi != 0 { + return vi; + } + + vp = test_matrix_of_pointers(); + if vp != 0 { + return vp; + } + + return 0; +} + diff --git a/test/general/memcpycheck.rob b/test/general/memcpycheck.rob new file mode 120000 index 0000000..4d0b1d5 --- /dev/null +++ b/test/general/memcpycheck.rob @@ -0,0 +1 @@ +../atmega328p/memcpycheck.rob \ No newline at end of file diff --git a/test/general/phior.rob b/test/general/phior.rob new file mode 100644 index 0000000..a903cd6 --- /dev/null +++ b/test/general/phior.rob @@ -0,0 +1,22 @@ + +void func(bool x) { +} + +int8 main() { + a = true; + b = false; + c = true; + d = a or b and c; + e = a and b or c; + + func(e and d and e); + + while a and b and c; + + if (a and b and c) { + return 1; + } + + return 0; +} + diff --git a/test/general/rand16.rob b/test/general/rand16.rob new file mode 100644 index 0000000..22d4a92 --- /dev/null +++ b/test/general/rand16.rob @@ -0,0 +1,17 @@ + +use math.random16; + +int16 main() { + result = 0; + i = 0u; + while i < 200 { + aux = random16ub(100); + if aux > 100 { + result = 1; + } + + i++; + } + return result; +} + diff --git a/test/general/return_a_type.rob b/test/general/return_a_type.rob new file mode 100644 index 0000000..5c9d406 --- /dev/null +++ b/test/general/return_a_type.rob @@ -0,0 +1,20 @@ + +type ta { + x = 0; + y = 0; +} + +ta get_ta(int8 x, int8 y) { + result = ta(); + result.x = x; + result.y = y; + return result; +} + +int8 main() { + result = get_ta(15, 20); + if result.x == 15 and result.y == 20 { + return 0; + } + return 1; +} \ No newline at end of file diff --git a/test/general/runtest.sh b/test/general/runtest.sh new file mode 100755 index 0000000..5166d97 --- /dev/null +++ b/test/general/runtest.sh @@ -0,0 +1,19 @@ +#!/bin/bash +GREEN="\033[0;32m" +RED="\033[0;31m" +NC="\033[0m" + +echo -n " ... $1 " +make -s $2 +if [ "$?" -eq 0 ]; then + timeout 10s ./$2 &> /dev/null + STATUS=$? + if [ "${STATUS}" -eq 0 ]; then + echo -e \\r${GREEN}[PASS]\\t\\t${NC} + else + echo -e \\r${RED}[FAILED] ${STATUS}\\t${NC} + fi +else + echo -e \\r${RED}[BUILD FAILED]\\t${NC} +fi + diff --git a/test/general/scalar-in-two-contexts.rob b/test/general/scalar-in-two-contexts.rob new file mode 100644 index 0000000..1b5ffd0 --- /dev/null +++ b/test/general/scalar-in-two-contexts.rob @@ -0,0 +1,19 @@ + +int8 main() { + block = {false:2}; + i = 2; + while (i > 0) { + row = i; + block[row] = true; + i--; + } + + row = 0; + while row < block.size { + block[row] = false; + row++; + } + + return block[0]; +} + diff --git a/test/general/simple.rob b/test/general/simple.rob new file mode 100644 index 0000000..7d8e82f --- /dev/null +++ b/test/general/simple.rob @@ -0,0 +1,6 @@ +/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */ + +int16 main() { + return 0; +} + diff --git a/test/general/simpleptr.rob b/test/general/simpleptr.rob new file mode 100644 index 0000000..15c3cd9 --- /dev/null +++ b/test/general/simpleptr.rob @@ -0,0 +1,19 @@ + +type tt { + a = int16(0); +} + +void set_a(tt value) { + value.a = 10; +} + +int32 main() { + t = tt(); + set_a(t); + if t.a == 10 { + return 0; + } else { + return 1; + } +} + diff --git a/test/general/simplescope.rob b/test/general/simplescope.rob new file mode 100644 index 0000000..62a8930 --- /dev/null +++ b/test/general/simplescope.rob @@ -0,0 +1,10 @@ +/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */ + +int16 main() { + i = 0; + while i < 6 { + i++; + } + return i != 6; +} + diff --git a/test/general/simplesubtype.rob b/test/general/simplesubtype.rob new file mode 100644 index 0000000..7d2ba24 --- /dev/null +++ b/test/general/simplesubtype.rob @@ -0,0 +1,16 @@ + +interface a { + void print(); +} + +type b { + x implements a { + void print() { } + } +} + +int16 main() { + y = b(); + return 0; +} + diff --git a/test/general/sort.rob b/test/general/sort.rob new file mode 100644 index 0000000..45c615d --- /dev/null +++ b/test/general/sort.rob @@ -0,0 +1,35 @@ +/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab + * sorts the vector a and check the result + */ + +void sort(int16[] a) { + t = 0u; + while t < a.size - 1 { + s = t + 1; + while s < a.size { + if a[t] > a[s] { + temp = a[t]; + a[t] = a[s]; + a[s] = temp; + } + s++; + } + t++; + } +} + +int16 main() { + a = {int16(34), -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; + r = {int16(-9), -5, -3, 0, 6, 6, 11, 12, 12, 17, 22, 22, 34, 44, 56, 100 }; + + sort(a); + i = 0u; + while i < a.size { + if a[i] != r[i] { + return 1; + } + i++; + } + return 0; +} + diff --git a/test/general/strcpy.rob b/test/general/strcpy.rob new file mode 100644 index 0000000..dfabb9c --- /dev/null +++ b/test/general/strcpy.rob @@ -0,0 +1,21 @@ +void strcpy(char[] src, int16 spos, char[] dst, int16 dpos, int16 len) { + i = 0; + while (i < len) { + dst[dpos + i] = src[spos + i]; + i++; + } +} + +int16 main(){ + a = "a noifas SDOINDAda"; + b = "B akjsad ADJNDAODA"; + strcpy(a, 0, b, 0, a.size); + i = 0; + while i < a.size { + if b[i] != a[i] { + return i; + } + i++; + } + return 0; +} diff --git a/test/general/strlen.rob b/test/general/strlen.rob new file mode 100644 index 0000000..d0917c4 --- /dev/null +++ b/test/general/strlen.rob @@ -0,0 +1,16 @@ + +const str = "abcd"; + +int8 strlen(char[] s) { + return s.size; +} + +int8 main() { + r = strlen(str); + if r == 4 { + return 0; + } else { + return 1; + } +} + diff --git a/test/general/type.rob b/test/general/type.rob new file mode 100644 index 0000000..8a12994 --- /dev/null +++ b/test/general/type.rob @@ -0,0 +1,38 @@ + +type A { + field0 = int8(10); + + int8 get() { + return field0; + } +} + +type B { + field0 = int16(10); + field1 = int8(0); + field2 = A(); + + int16 get() { + return field0 + field1 + field2.get(); + } + + void set_field(int8 x) { + field1 = x; + } +} + +int16 main() { + a = A(); + + b = B(); + b.set_field(10); + + x = a.get(); + y = b.get(); + + if x == 10 and y == 30 { + return 0; + } else { + return 1; + } +} diff --git a/test/general/typeandarrays.rob b/test/general/typeandarrays.rob new file mode 100644 index 0000000..e6a2c18 --- /dev/null +++ b/test/general/typeandarrays.rob @@ -0,0 +1,30 @@ + +type array_capsule { + + a = {10, 30, 10:2}; + b = {{1, 2, 3}, {4, 5, 6}}; + + int16 getarr(int16 i) { + return a[i]; + } + + int16 getmatrix(int16 i, int16 j) { + return b[i][j]; + } +} + +int16 main() { + c = array_capsule(); + d = c.getarr(2); + e = c.a[1]; + f = c.getmatrix(1, 1); + g = c.b[0][0]; + + if d == 10 and f == 5 { + if e == 30 and g == 1 { + return 0; + } + } + return 1; +} + diff --git a/test/general/typesetrecursive.rob b/test/general/typesetrecursive.rob new file mode 100644 index 0000000..d37ade8 --- /dev/null +++ b/test/general/typesetrecursive.rob @@ -0,0 +1,39 @@ + +type t0 { + a = 0; + int8 callf(int8 x) { + return x+1; + } +} + +type t1 { + c = {0:2}; + m = {{0:2}:2}; + b = t0(); +} + +type t2 { + d = {0:2}; + e = t1(); + + void sett2(t2 tt) { + tt.d[0] = 1; + tt.e.c[0] = 1; + tt.e.m[0][1] = 1; + } +} + +int16 main() { + x = t2(); + x.e.b.a = 0 + x.e.b.callf(-1); + x.sett2(x); + + x.e.c[1] = 1; + x.e.m[1][1] = 1; + + if x.e.b.a == 0 and x.d[0] == 1 and x.e.c[0] == 1 and x.e.c[0] == 1 and + x.e.m[0][1] == 1 and x.e.m[1][1] == 1 { + return 0; + } + return 1; +} diff --git a/test/general/unsigned.rob b/test/general/unsigned.rob new file mode 100644 index 0000000..e6e0b71 --- /dev/null +++ b/test/general/unsigned.rob @@ -0,0 +1,16 @@ + +uint16 func_b(uint16 x, int16 y); + +uint16 func_a(uint16 x) { + return x / 13u; +} + +int16 main() { + b = 130U; + a = func_a(b); + if a == 10u { + return 0; + } else { + return 1; + } +} diff --git a/test/general/vector_matrix_value.rob b/test/general/vector_matrix_value.rob new file mode 100644 index 0000000..bf43436 --- /dev/null +++ b/test/general/vector_matrix_value.rob @@ -0,0 +1,22 @@ + +int16 main() { + matriz = {{1, 2, 3}:2, {1:2,2}}; + + b = {5, 6, 7, 8}; + + c = matriz[2][2]; + + if c != 2 { + return 1; + } + + if b[c] != 7 { + return 1; + } + + if b[matriz[0][2]] != 8 { + return 1; + } + + return 0; +} diff --git a/test/general/vector_of_type.rob b/test/general/vector_of_type.rob new file mode 100644 index 0000000..72d5765 --- /dev/null +++ b/test/general/vector_of_type.rob @@ -0,0 +1,76 @@ + +type element { + fa = int16(0); +} + +int16 check(element[] x) { + i = 0; + while i < x.size { + xx = x[i]; + if xx.fa != (i+1)*10 { + return i+1; + } + i++; + } + return 0; +} + +int16 test_vector_of_instances() { + x2 = element(); + x2.fa = 30; + + x3 = element(); + x3.fa = 40; + + x = {element():2, copy(x2), copy(x3)}; + + x0 = x[0]; + x0.fa = 10; + + x1 = x[1]; + x1.fa = 20; + + return check(x); +} + +int16 test_vector_of_pointers() { + x0 = element(); + x1 = element(); + + x2 = element(); + x2.fa = 30; + + x3 = element(); + x3.fa = 50; + + // this will be a vector of references to element + x = {x0, x1, x2, x3}; + + x0 = x[0]; + x0.fa = 10; + + x1 = x[1]; + x1.fa = 20; + + // test update of an element + x3_copy = element(); + x3_copy.fa = 40; + x[3] = x3_copy; + + return check(x); +} + +int16 main() { + vi = test_vector_of_instances(); + if vi != 0 { + return vi; + } + + vp = test_vector_of_pointers(); + if vp != 0 { + return vp; + } + + return 0; +} + diff --git a/test/general/vector_vector_value.rob b/test/general/vector_vector_value.rob new file mode 100644 index 0000000..6075c93 --- /dev/null +++ b/test/general/vector_vector_value.rob @@ -0,0 +1,14 @@ + +int16 main(){ + a = {3, 2, 1}; + if a[1] != 2 { + return 1; + } + + b = {2, 2, 4}; + if b[a[1]] != 4 { + return 1; + } + + return 0; +} diff --git a/test/general/vector_vector_value_01.rob b/test/general/vector_vector_value_01.rob new file mode 100644 index 0000000..61b8248 --- /dev/null +++ b/test/general/vector_vector_value_01.rob @@ -0,0 +1,20 @@ + +int16 main(){ + a = 1; + b = {1, 2, 3}; + c = {5, 6, 7, 8}; + + if b[a] != 2 { + return 1; + } + + if c[b[1]] != 7 { + return 1; + } + + if c[b[a+1]] != 8 { + return 1; + } + + return 0; +} diff --git a/test/matrix-global.rob b/test/matrix-global.rob deleted file mode 100644 index 8fa37b2..0000000 --- a/test/matrix-global.rob +++ /dev/null @@ -1,14 +0,0 @@ - -a = {{3:3}, - {4, 5, 6}, - {7:2, 9}}; - -int16 main() { - b = 1*2; - c = a[2][1] + a[2][2] + a[b][b]; - d = {{(int16)a[2][1]:3}, {1,2,3}}; - d[2][2] = 30000; - e = {{a[2][1]:3}, {1,2,3}}; - e[2][2] = 30000; -} - diff --git a/test/rp2040/Makefile b/test/rp2040/Makefile new file mode 100644 index 0000000..3e48dda --- /dev/null +++ b/test/rp2040/Makefile @@ -0,0 +1,59 @@ +ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) +ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/stm32f1.o + +TOOL_OPEN_OCD_FOLDER=~/.platformio/packages/tool-openocd +ROBCMP=../../build/robcmp +INCLUDES=-I ../../lib + +ifndef OPT +#OPT=-g -O0 +OPT=-Oz +endif + +LD_FLAGS=-nostdlib -entry=main -L../../lib -Tarch/rp/rp2040/rp2040.ld +LD_FLAGS+=-Bstatic +LD_FLAGS+=--gc-sections +LD_FLAGS+=--lto=thin + +DEPENDS=${ROBCMP} Makefile +LINK_DEPENDS=out/init.o ../../lib/arch/rp/rp2040/boot2.o ../../lib/arm-none-eabi-thumb-v6m-libgcc.a ../../lib/cortex-m0plus-arm-missing.o +#../../lib/libclang_rt.builtins-armv6.a + +all: out test + +out: + mkdir -p out + +out/init.o : ../../lib/arch/rp/rp2040/init.rob ${DEPENDS} + ${ROBCMP} -a rp2040 ${OPT} -o $@ $< + +out/init.ll : ../../lib/arch/rp/rp2040/init.rob ${DEPENDS} + ${ROBCMP} -a stm32f1 ${OPT} $< > $@ + +out/%.o : %.rob out/init.o ${DEPENDS} + ${ROBCMP} -bdep -a rp2040 ${OPT} ${INCLUDES} -o $@ $< + +out/%.ll : %.rob ${DEPENDS} + ${ROBCMP} -bdep -a rp2040 ${OPT} ${INCLUDES} $< > $@ + +%.tt : %.rob ${DEPENDS} + @-./runtest.sh $< $(patsubst %.rob,out/%,$<) + +out/%.uf2 : out/% + llvm-size $< + ./elf2uf2/elf2uf2 -v $< $@ + +out/% : out/%.o ${LINK_DEPENDS} + ld.lld ${LD_FLAGS} $^ -o $@ + +%.up : out/%.uf2 + cp $< /Volumes/RPI-RP2 + +test: ${ALL_TT} + +clean: + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} + @rm out/* + diff --git a/test/rp2040/blink.rob b/test/rp2040/blink.rob new file mode 100644 index 0000000..3f49b6f --- /dev/null +++ b/test/rp2040/blink.rob @@ -0,0 +1,20 @@ +/* + * Blinks the board default led + */ + +use intfs.ports; +use arch.rp.rp2040.mcu; + +int16 main() { + mmcu = rp2040mcu(); + led = mmcu.io25; + + led.mode(port_mode.output); + + loop { + led.set(true); + mmcu.wait_ms(100); + led.set(false); + mmcu.wait_ms(100); + } +} diff --git a/test/rp2040/runtest.sh b/test/rp2040/runtest.sh new file mode 100755 index 0000000..5676a41 --- /dev/null +++ b/test/rp2040/runtest.sh @@ -0,0 +1,27 @@ +#!/bin/bash +#CMD="./robcmp-simavr-debug -c 16000000 -m atmega328p -f $2" +CMD="echo \"no simulator for stm32f1 yet.\"" + +GREEN="\033[0;32m" +RED="\033[0;31m" +NC="\033[0m" + +echo -n " $1 " +make -s $2 +if [ "$?" -eq 0 ]; then + if [ "$V" = "1" ]; then + ${CMD} + else + timeout 10s ${CMD} &> /dev/null + fi + STATUS=$? + #if [ "${STATUS}" -eq 0 ]; then + # echo -e \\r${GREEN}[PASS]\\t\\t${NC} + #else + # echo -e \\r${RED}[FAILED] ${STATUS}\\t${NC} + #fi + ${CMD} +else + echo -e \\r${RED}[BUILD FAILED]\\t${NC} +fi + diff --git a/test/simple_array.rob b/test/simple_array.rob deleted file mode 100644 index 8634635..0000000 --- a/test/simple_array.rob +++ /dev/null @@ -1,11 +0,0 @@ - -a = {1, 2, 3, 4, 5, 6}; - -i = 0; -while (i < 16) { - c = a[i]; - print c; - i++; -} -print "\n"; - diff --git a/test/sort.rob b/test/sort.rob deleted file mode 100644 index b433bdd..0000000 --- a/test/sort.rob +++ /dev/null @@ -1,47 +0,0 @@ -/* - * sample file for robcmp compiler - * this code sorts and print the vector a - */ - -a = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; - -long double sqrtl(long double n); -double sqrt(double n); -float sqrtf(float n); -long int teste(int n); - -int sort (int n) { - t = 0; - s = 0; - temp = 0; - while (t < n - 1) { - s = t + 1; - while (s < n) { - if ( a[t] > a[s] ) { - temp = a[t]; - a[t] = a[s]; - a[s] = temp; - } - s++; - } - t++; - //print t; - } - return 0; -} - -i = 0; -while (i < 16 and 1 == 1) { - print sqrtf(a[i]); - i++; -} - -print "\n"; - -sort(16); - -i = 0; -while (i < 16) { - print a[i]; - i++; -} diff --git a/test/stm32f1/Makefile b/test/stm32f1/Makefile new file mode 100644 index 0000000..53c5eb4 --- /dev/null +++ b/test/stm32f1/Makefile @@ -0,0 +1,54 @@ +ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) +ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/stm32f1.o + +TOOL_OPEN_OCD_FOLDER=~/.platformio/packages/tool-openocd +ROBCMP=../../build/robcmp +INCLUDES=-I ../../lib + +ifndef OPT +#OPT=-g -O0 +OPT=-Oz +endif + +LD_FLAGS=-nostdlib -entry=main -L../../lib -Tstm32f1.ld +LD_FLAGS+=-Bstatic +LD_FLAGS+=--gc-sections +LD_FLAGS+=--lto=thin + +DEPENDS=${ROBCMP} Makefile +LINK_DEPENDS=out/stm32f1.o ../../lib/cortex-m3-arm-missing.o ../../lib/arm-eabi-libgcc.a + +all: out test + +out: + mkdir -p out + +out/stm32f1.o : ../../lib/stm32f1.rob ${DEPENDS} + ${ROBCMP} -a stm32f1 ${OPT} -o $@ $< + +out/stm32f1.ll : ../../lib/stm32f1.rob ${DEPENDS} + ${ROBCMP} -a stm32f1 ${OPT} $< > $@ + +.SECONDARY: +out/%.o : %.rob out/stm32f1.o ${DEPENDS} + ${ROBCMP} -bdep -a stm32f1 ${OPT} ${INCLUDES} -o $@ $< + +out/%.ll : %.rob ${DEPENDS} + ${ROBCMP} -bdep -a stm32f1 ${OPT} ${INCLUDES} $< > $@ + +%.tt : %.rob ${DEPENDS} + @-./runtest.sh $< $(patsubst %.rob,out/%,$<) + +%.up : %.tt ${DEPENDS} + ${TOOL_OPEN_OCD_FOLDER}/bin/openocd -f ${TOOL_OPEN_OCD_FOLDER}/scripts/interface/stlink.cfg -f ${TOOL_OPEN_OCD_FOLDER}/scripts/target/stm32f1x.cfg -c "program $(patsubst %.tt,out/%,$<) reset exit" + +out/% : out/%.o ${LINK_DEPENDS} + ld.lld ${LD_FLAGS} $^ -o $@ + +test: ${ALL_TT} + +clean: + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} + diff --git a/test/stm32f1/blink.rob b/test/stm32f1/blink.rob new file mode 100644 index 0000000..06ff3b1 --- /dev/null +++ b/test/stm32f1/blink.rob @@ -0,0 +1,20 @@ +/* + * Blinks the board default led + */ + +use intfs.ports; +use arch.stm32.stm32f1; + +int16 main() { + mmcu = stm32f1(); + led = mmcu.c13; + + led.mode(port_mode.output); + + loop { + led.set(true); + mmcu.wait_ms(500); + led.set(false); + mmcu.wait_ms(500); + } +} diff --git a/test/stm32f1/coseno.rob b/test/stm32f1/coseno.rob new file mode 100644 index 0000000..ba7bbca --- /dev/null +++ b/test/stm32f1/coseno.rob @@ -0,0 +1,94 @@ + +use intfs.ports; +use arch.stm32.stm32f1; +use convert.itoa; + +use math.abs; +use math.fconsts; +use math.trigonometric; + +precision_digits=1E6; + +values={ + 1.000000,0.999962,0.999848,0.999657,0.999391,0.999048,0.998630,0.998135,0.997564,0.996917,0.996195,0.995396,0.994522,0.993572,0.992546,0.991445,0.990268,0.989016,0.987688,0.986286, + 0.984808,0.983255,0.981627,0.979925,0.978148,0.976296,0.974370,0.972370,0.970296,0.968148,0.965926,0.963630,0.961262,0.958820,0.956305,0.953717,0.951057,0.948324,0.945519,0.942641, + 0.939693,0.936672,0.933580,0.930418,0.927184,0.923880,0.920505,0.917060,0.913545,0.909961,0.906308,0.902585,0.898794,0.894934,0.891007,0.887011,0.882948,0.878817,0.874620,0.870356, + 0.866025,0.861629,0.857167,0.852640,0.848048,0.843391,0.838671,0.833886,0.829038,0.824126,0.819152,0.814116,0.809017,0.803857,0.798636,0.793353,0.788011,0.782608,0.777146,0.771625, + 0.766044,0.760406,0.754710,0.748956,0.743145,0.737277,0.731354,0.725374,0.719340,0.713250,0.707107,0.700909,0.694658,0.688355,0.681998,0.675590,0.669131,0.662620,0.656059,0.649448, + 0.642788,0.636078,0.629320,0.622515,0.615662,0.608761,0.601815,0.594823,0.587785,0.580703,0.573576,0.566406,0.559193,0.551937,0.544639,0.537300,0.529919,0.522498,0.515038,0.507538, + 0.500000,0.492424,0.484810,0.477159,0.469472,0.461749,0.453991,0.446198,0.438371,0.430511,0.422618,0.414693,0.406737,0.398749,0.390731,0.382683,0.374607,0.366501,0.358368,0.350207, + 0.342020,0.333807,0.325568,0.317305,0.309017,0.300706,0.292372,0.284015,0.275637,0.267238,0.258819,0.250380,0.241922,0.233445,0.224951,0.216440,0.207912,0.199368,0.190809,0.182236, + 0.173648,0.165048,0.156434,0.147809,0.139173,0.130526,0.121869,0.113203,0.104528,0.095846,0.087156,0.078459,0.069757,0.061049,0.052336,0.043619,0.034899,0.026177,0.017452,0.008727, + -0.000000,-0.008727,-0.017452,-0.026177,-0.034899,-0.043619,-0.052336,-0.061049,-0.069756,-0.078459,-0.087156,-0.095846,-0.104529,-0.113203,-0.121869,-0.130526,-0.139173,-0.147809,-0.156434,-0.165048, + -0.173648,-0.182235,-0.190809,-0.199368,-0.207912,-0.216440,-0.224951,-0.233445,-0.241922,-0.250380,-0.258819,-0.267238,-0.275637,-0.284015,-0.292372,-0.300706,-0.309017,-0.317305,-0.325568,-0.333807, + -0.342020,-0.350207,-0.358368,-0.366501,-0.374607,-0.382683,-0.390731,-0.398749,-0.406737,-0.414693,-0.422618,-0.430511,-0.438371,-0.446198,-0.453991,-0.461749,-0.469472,-0.477159,-0.484810,-0.492424, + -0.500000,-0.507538,-0.515038,-0.522498,-0.529919,-0.537300,-0.544639,-0.551937,-0.559193,-0.566406,-0.573576,-0.580703,-0.587785,-0.594823,-0.601815,-0.608761,-0.615661,-0.622515,-0.629320,-0.636078, + -0.642788,-0.649448,-0.656059,-0.662620,-0.669131,-0.675590,-0.681998,-0.688354,-0.694658,-0.700909,-0.707107,-0.713250,-0.719340,-0.725374,-0.731354,-0.737277,-0.743145,-0.748956,-0.754710,-0.760406, + -0.766044,-0.771625,-0.777146,-0.782608,-0.788011,-0.793353,-0.798635,-0.803857,-0.809017,-0.814116,-0.819152,-0.824126,-0.829038,-0.833886,-0.838671,-0.843391,-0.848048,-0.852640,-0.857167,-0.861629, + -0.866025,-0.870356,-0.874620,-0.878817,-0.882948,-0.887011,-0.891006,-0.894934,-0.898794,-0.902585,-0.906308,-0.909961,-0.913545,-0.917060,-0.920505,-0.923880,-0.927184,-0.930418,-0.933580,-0.936672, + -0.939693,-0.942642,-0.945519,-0.948324,-0.951056,-0.953717,-0.956305,-0.958820,-0.961262,-0.963630,-0.965926,-0.968148,-0.970296,-0.972370,-0.974370,-0.976296,-0.978148,-0.979925,-0.981627,-0.983255, + -0.984808,-0.986286,-0.987688,-0.989016,-0.990268,-0.991445,-0.992546,-0.993572,-0.994522,-0.995396,-0.996195,-0.996917,-0.997564,-0.998135,-0.998630,-0.999048,-0.999391,-0.999657,-0.999848,-0.999962, + -1.000000,-0.999962,-0.999848,-0.999657,-0.999391,-0.999048,-0.998630,-0.998135,-0.997564,-0.996917,-0.996195,-0.995396,-0.994522,-0.993572,-0.992546,-0.991445,-0.990268,-0.989016,-0.987688,-0.986286, + -0.984808,-0.983255,-0.981627,-0.979925,-0.978148,-0.976296,-0.974370,-0.972370,-0.970296,-0.968148,-0.965926,-0.963630,-0.961262,-0.958820,-0.956305,-0.953717,-0.951057,-0.948324,-0.945519,-0.942641, + -0.939693 + }; + + +int16 run_test(stm32f1 mmcu) { + + degress=float(0.0); + value=int32(0); + result=int32(0); + i = int32(0); + while degress <= 200.0 { + value=int32(values[i]*precision_digits); + result=int32(Cos((float(degress) * FM_PI) / 180.0,18)*precision_digits); + if (abs32(value-result)>10) { + if i!=0 { + return int16(i); + } else { + return 1; + } + } + i=i+1; + degress+=0.5; + } + return 0; +} + +int16 main() { + mmcu = stm32f1(); + serial = mmcu.uart2; + serial.setup(9600); + serial.enable(); + + //led = mmcu.c13; + //led.mode(port_mode.output); + + loop { + start = mmcu.millis(); + + ret = run_test(mmcu); + + // millis is counting downwards, thus start - current + time = start - mmcu.millis(); + + timestr = {'0': 10}; + chars = itoa(time, 10, timestr); + + if ret != 0 { + serial.write_array("FAIL"); + } else { + timestr[chars] = ' '; + timestr[chars+1] = 'm'; + timestr[chars+2] = 's'; + timestr[chars+3] = ' '; + serial.write_array(timestr); + } + serial.write('\r'); + serial.write('\n'); + + } + return 0; +} + diff --git a/test/stm32f1/example.rob b/test/stm32f1/example.rob new file mode 100644 index 0000000..e02e4d2 --- /dev/null +++ b/test/stm32f1/example.rob @@ -0,0 +1,41 @@ + +use intfs.ports; +use arch.stm32.stm32f1; +use convert.itoa; + +void run_test(stm32f1 mmcu) { + mmcu.wait_ms(500); +} + +int16 main() { + mmcu = stm32f1(); + serial = mmcu.uart2; + serial.setup(9600); + serial.enable(); + + //led = mmcu.c13; + //led.mode(port_mode.output); + + loop { + start = mmcu.millis(); + + run_test(mmcu); + + time = mmcu.millis() - start; + + timestr = {'0': 10}; + itoa(time, 10, timestr); + + serial.write_array(timestr); + serial.write('\r'); + serial.write('\n'); + + /*led.set(true); + mmcu.wait_ms(500); + led.set(false); + mmcu.wait_ms(500);*/ + + } + return 0; +} + diff --git a/test/stm32f1/runtest.sh b/test/stm32f1/runtest.sh new file mode 100755 index 0000000..5676a41 --- /dev/null +++ b/test/stm32f1/runtest.sh @@ -0,0 +1,27 @@ +#!/bin/bash +#CMD="./robcmp-simavr-debug -c 16000000 -m atmega328p -f $2" +CMD="echo \"no simulator for stm32f1 yet.\"" + +GREEN="\033[0;32m" +RED="\033[0;31m" +NC="\033[0m" + +echo -n " $1 " +make -s $2 +if [ "$?" -eq 0 ]; then + if [ "$V" = "1" ]; then + ${CMD} + else + timeout 10s ${CMD} &> /dev/null + fi + STATUS=$? + #if [ "${STATUS}" -eq 0 ]; then + # echo -e \\r${GREEN}[PASS]\\t\\t${NC} + #else + # echo -e \\r${RED}[FAILED] ${STATUS}\\t${NC} + #fi + ${CMD} +else + echo -e \\r${RED}[BUILD FAILED]\\t${NC} +fi + diff --git a/test/stm32f1/uart.rob b/test/stm32f1/uart.rob new file mode 100644 index 0000000..1863f45 --- /dev/null +++ b/test/stm32f1/uart.rob @@ -0,0 +1,41 @@ + +use intfs.ports; +use arch.stm32.stm32f1; +use convert.itoa; + +void run_test() { + +} + +int16 main() { + mmcu = stm32f1(); + serial = mmcu.uart2; + serial.setup(9600); + serial.enable(); + + //led = mmcu.c13; + //led.mode(port_mode.output); + + loop { + start = mmcu.time(); + + run_test(); + + time = mmcu.time() - start; + + timestr = {'0': 10}; + itoa(time, 10, timestr); + + serial.write(timestr); + serial.write('\r'); + serial.write('\n'); + + /*led.set(true); + mmcu.wait_ms(500); + led.set(false); + mmcu.wait_ms(500);*/ + + } + return 0; +} + diff --git a/test/test2.txt b/test/test2.txt deleted file mode 100644 index 928e44b..0000000 --- a/test/test2.txt +++ /dev/null @@ -1,4 +0,0 @@ -a = {3, 2, 1}; -print a[1]; -b = {2, 2, 4}; -print b[a[1]]; diff --git a/test/testando.txt b/test/testando.txt deleted file mode 100644 index 0218052..0000000 --- a/test/testando.txt +++ /dev/null @@ -1,6 +0,0 @@ -if (true == true){ - print 1; -} -else{ - print 2; -} diff --git a/test/teste.txt b/test/teste.txt deleted file mode 100644 index 1e0b1e0..0000000 --- a/test/teste.txt +++ /dev/null @@ -1,11 +0,0 @@ -int a (int b){ - if (b == 1){ - return (b + 1); - } - else{ - return b; - } - return 1; -} - -print a(2); diff --git a/test/teste23.txt b/test/teste23.txt deleted file mode 100644 index 34859a2..0000000 --- a/test/teste23.txt +++ /dev/null @@ -1,11 +0,0 @@ -a = 1; - -print -1; -print -a; -print a-a; -print a-1; -print 1--a; - -if (a > a-1){ - print 2; -} diff --git a/test/testeHalf.txt b/test/testeHalf.txt deleted file mode 100644 index ede09e3..0000000 --- a/test/testeHalf.txt +++ /dev/null @@ -1 +0,0 @@ -var = ( short float ) 3.0; diff --git a/test/teste_func_matrix.txt b/test/teste_func_matrix.txt deleted file mode 100644 index e3dc27e..0000000 --- a/test/teste_func_matrix.txt +++ /dev/null @@ -1,10 +0,0 @@ - -matriz = {{7, 8}, {9,10}}; - -int fa(int i, int j) { - localmatriz = {{1,2},{3,4},{5,6}}; - return localmatriz[i][j]; -} - -print matriz[1][1]; // print 10 -print fa(2,1); // print 6 diff --git a/test/teste_func_vector.txt b/test/teste_func_vector.txt deleted file mode 100644 index ab21353..0000000 --- a/test/teste_func_vector.txt +++ /dev/null @@ -1,10 +0,0 @@ - -vector = {7, 8, 9, 10}; - -int fa(int i) { - localvector = {1,2,3,4,5,6}; - return localvector[i]; -} - -print vector[1]; // print 8 -print fa(2); // print 3 diff --git a/test/teste_function_returns.txt b/test/teste_function_returns.txt deleted file mode 100644 index d999724..0000000 --- a/test/teste_function_returns.txt +++ /dev/null @@ -1,15 +0,0 @@ - -void fa(int a) { - a = a + 1; -} - -int fb(int b) { - b = b + 1; - if (b == 2) - return b; - return 0; -} - -fa(1); -print fb(2); - diff --git a/test/teste_idx_matrix.txt b/test/teste_idx_matrix.txt deleted file mode 100644 index 0b1431b..0000000 --- a/test/teste_idx_matrix.txt +++ /dev/null @@ -1,11 +0,0 @@ - -matriz = {{1, 2, 3}:2, {1:2,2}}; - -b = {5, 6, 7, 8}; - -c = matriz[2][2]; - -print c; // print 2 -print b[c]; // print 7 -print b[matriz[0][2]]; // print 8 - diff --git a/test/teste_idx_vector.txt b/test/teste_idx_vector.txt deleted file mode 100644 index ca9d82b..0000000 --- a/test/teste_idx_vector.txt +++ /dev/null @@ -1,8 +0,0 @@ - -a = 1; -b = {1, 2, 3}; -c = {5, 6, 7, 8}; -print b[a]; // print 2 -print c[b[1]]; // print 7 -print c[b[a+1]]; // print 8 - diff --git a/test/teste_while_return.txt b/test/teste_while_return.txt deleted file mode 100644 index 5a22b5d..0000000 --- a/test/teste_while_return.txt +++ /dev/null @@ -1,18 +0,0 @@ - -void fb(int a) { - b = a; - while(b > 3) { - b = b - 1; - } -} - -double fa(int a) { - b = a; - while(b > 3) { - b = b - 1; - return b; - } -} - -fa(10); - diff --git a/test/updateteste.txt b/test/updateteste.txt deleted file mode 100644 index a8e1fe4..0000000 --- a/test/updateteste.txt +++ /dev/null @@ -1,4 +0,0 @@ -a = {3, 3, 3, 3, 3}; -print a[2]; -a[2] = 1; -print a[2]; diff --git a/test/varpp.txt b/test/varpp.txt deleted file mode 100644 index 51cfcb4..0000000 --- a/test/varpp.txt +++ /dev/null @@ -1,6 +0,0 @@ -i = 1.2; -i++; -i+=7; -print i; -i*=2; -print i; diff --git a/test/vector-global.rob b/test/vector-global.rob deleted file mode 100644 index 2ef25b0..0000000 --- a/test/vector-global.rob +++ /dev/null @@ -1,11 +0,0 @@ - -const d = 1; -a = {1, 2, 3:3, 100:2, d}; - -int16 main() { - b = a[10]; - c = {5:10, 9.9, 10.7D, a[2], b}; - e = c[6] + b; - return e; -} - diff --git a/winbuild b/winbuild new file mode 100644 index 0000000..b83d2b9 --- /dev/null +++ b/winbuild @@ -0,0 +1 @@ +cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ..